libaddns/dnsrecord.c

説明を見る。
00001 /*
00002   Linux DNS client library implementation
00003   Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
00004   Copyright (C) 2006 Gerald Carter <jerry@samba.org>
00005 
00006      ** NOTE! The following LGPL license applies to the libaddns
00007      ** library. This does NOT imply that all of Samba is released
00008      ** under the LGPL
00009 
00010   This library is free software; you can redistribute it and/or
00011   modify it under the terms of the GNU Lesser General Public
00012   License as published by the Free Software Foundation; either
00013   version 2.1 of the License, or (at your option) any later version.
00014 
00015   This library is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY; without even the implied warranty of
00017   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018   Lesser General Public License for more details.
00019 
00020   You should have received a copy of the GNU Lesser General Public
00021   License along with this library; if not, write to the Free Software
00022   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
00023   02110-1301  USA
00024 */
00025 
00026 #include "dns.h"
00027 
00028 DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
00029                             uint16 q_type, uint16 q_class,
00030                             struct dns_request **preq )
00031 {
00032         struct dns_request *req;
00033         struct dns_question *q;
00034         DNS_ERROR err;
00035 
00036         if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) ||
00037             !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) ||
00038             !(req->questions[0] = talloc(req->questions,
00039                                          struct dns_question))) {
00040                 TALLOC_FREE(req);
00041                 return ERROR_DNS_NO_MEMORY;
00042         }
00043 
00044         req->id = random();
00045 
00046         req->num_questions = 1;
00047         q = req->questions[0];
00048 
00049         err = dns_domain_name_from_string(q, name, &q->name);
00050         if (!ERR_DNS_IS_OK(err)) {
00051                 TALLOC_FREE(req);
00052                 return err;
00053         }
00054 
00055         q->q_type = q_type;
00056         q->q_class = q_class;
00057 
00058         *preq = req;
00059         return ERROR_DNS_SUCCESS;
00060 }
00061 
00062 DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
00063                              struct dns_update_request **preq )
00064 {
00065         struct dns_update_request *req;
00066         struct dns_zone *z;
00067         DNS_ERROR err;
00068 
00069         if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) ||
00070             !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) ||
00071             !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
00072                 TALLOC_FREE(req);
00073                 return ERROR_DNS_NO_MEMORY;
00074         }
00075 
00076         req->id = random();
00077         req->flags = 0x2800;    /* Dynamic update */
00078 
00079         req->num_zones = 1;
00080         z = req->zones[0];
00081 
00082         err = dns_domain_name_from_string(z, name, &z->name);
00083         if (!ERR_DNS_IS_OK(err)) {
00084                 TALLOC_FREE(req);
00085                 return err;
00086         }
00087 
00088         z->z_type = QTYPE_SOA;
00089         z->z_class = DNS_CLASS_IN;
00090 
00091         *preq = req;
00092         return ERROR_DNS_SUCCESS;
00093 }
00094 
00095 DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
00096                           uint16 type, uint16 r_class, uint32 ttl,
00097                           uint16 data_length, uint8 *data,
00098                           struct dns_rrec **prec)
00099 {
00100         struct dns_rrec *rec;
00101         DNS_ERROR err;
00102 
00103         if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
00104                 return ERROR_DNS_NO_MEMORY;
00105         }
00106 
00107         err = dns_domain_name_from_string(rec, name, &rec->name);
00108         if (!(ERR_DNS_IS_OK(err))) {
00109                 TALLOC_FREE(rec);
00110                 return err;
00111         }
00112 
00113         rec->type = type;
00114         rec->r_class = r_class;
00115         rec->ttl = ttl;
00116         rec->data_length = data_length;
00117         rec->data = talloc_move(rec, &data);
00118 
00119         *prec = rec;
00120         return ERROR_DNS_SUCCESS;
00121 }
00122 
00123 DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
00124                               uint32 ttl, struct in_addr ip,
00125                               struct dns_rrec **prec)
00126 {
00127         uint8 *data;
00128         DNS_ERROR err;
00129 
00130         if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr,
00131                                             sizeof(ip.s_addr)))) {
00132                 return ERROR_DNS_NO_MEMORY;
00133         }
00134 
00135         err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
00136                               sizeof(ip.s_addr), data, prec);
00137 
00138         if (!ERR_DNS_IS_OK(err)) {
00139                 TALLOC_FREE(data);
00140         }
00141 
00142         return err;
00143 }
00144 
00145 DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
00146                                         const char *name,
00147                                         const struct in_addr *ip,
00148                                         struct dns_rrec **prec)
00149 {
00150         if (ip != NULL) {
00151                 return dns_create_a_record(mem_ctx, name, 0, *ip, prec);
00152         }
00153 
00154         return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
00155                                NULL, prec);
00156 }
00157 
00158 DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
00159                                             const char *name, uint32 type,
00160                                             struct dns_rrec **prec)
00161 {
00162         return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
00163                                0, NULL, prec);
00164 }
00165 
00166 DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
00167                                    uint16 type, uint16 r_class,
00168                                    struct dns_rrec **prec)
00169 {
00170         return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
00171 }
00172 
00173 DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
00174                                  const char *algorithm_name, time_t inception,
00175                                  time_t expiration, uint16 mode, uint16 error,
00176                                  uint16 key_length, const uint8 *key,
00177                                  struct dns_rrec **prec)
00178 {
00179         struct dns_buffer *buf;
00180         struct dns_domain_name *algorithm;
00181         DNS_ERROR err;
00182 
00183         if (!(buf = dns_create_buffer(mem_ctx))) {
00184                 return ERROR_DNS_NO_MEMORY;
00185         }
00186 
00187         err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
00188         if (!ERR_DNS_IS_OK(err)) goto error;
00189 
00190         dns_marshall_domain_name(buf, algorithm);
00191         dns_marshall_uint32(buf, inception);
00192         dns_marshall_uint32(buf, expiration);
00193         dns_marshall_uint16(buf, mode);
00194         dns_marshall_uint16(buf, error);
00195         dns_marshall_uint16(buf, key_length);
00196         dns_marshall_buffer(buf, key, key_length);
00197         dns_marshall_uint16(buf, 0); /* Other Size */
00198 
00199         if (!ERR_DNS_IS_OK(buf->error)) {
00200                 err = buf->error;
00201                 goto error;
00202         }
00203 
00204         err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
00205                               buf->offset, buf->data, prec);
00206 
00207  error:
00208         TALLOC_FREE(buf);
00209         return err;
00210 }
00211 
00212 DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
00213                                      struct dns_tkey_record **ptkey)
00214 {
00215         struct dns_tkey_record *tkey;
00216         struct dns_buffer buf;
00217         uint32 tmp_inception, tmp_expiration;
00218         
00219         if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
00220                 return ERROR_DNS_NO_MEMORY;
00221         }
00222 
00223         buf.data = rec->data;
00224         buf.size = rec->data_length;
00225         buf.offset = 0;
00226         buf.error = ERROR_DNS_SUCCESS;
00227 
00228         dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
00229         dns_unmarshall_uint32(&buf, &tmp_inception);
00230         dns_unmarshall_uint32(&buf, &tmp_expiration);
00231         dns_unmarshall_uint16(&buf, &tkey->mode);
00232         dns_unmarshall_uint16(&buf, &tkey->error);
00233         dns_unmarshall_uint16(&buf, &tkey->key_length);
00234 
00235         if (!ERR_DNS_IS_OK(buf.error)) goto error;
00236 
00237         if (tkey->key_length) {
00238                 if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
00239                         buf.error = ERROR_DNS_NO_MEMORY;
00240                         goto error;
00241                 }
00242         } else {
00243                 tkey->key = NULL;
00244         }
00245 
00246         dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
00247         if (!ERR_DNS_IS_OK(buf.error)) goto error;
00248 
00249         tkey->inception = (time_t)tmp_inception;
00250         tkey->expiration = (time_t)tmp_expiration;
00251 
00252         *ptkey = tkey;
00253         return ERROR_DNS_SUCCESS;
00254 
00255  error:
00256         TALLOC_FREE(tkey);
00257         return buf.error;
00258 }
00259 
00260 DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
00261                                  const char *algorithm_name,
00262                                  time_t time_signed, uint16 fudge,
00263                                  uint16 mac_length, const uint8 *mac,
00264                                  uint16 original_id, uint16 error,
00265                                  struct dns_rrec **prec)
00266 {
00267         struct dns_buffer *buf;
00268         struct dns_domain_name *algorithm;
00269         DNS_ERROR err;
00270 
00271         if (!(buf = dns_create_buffer(mem_ctx))) {
00272                 return ERROR_DNS_NO_MEMORY;
00273         }
00274 
00275         err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
00276         if (!ERR_DNS_IS_OK(err)) goto error;
00277 
00278         dns_marshall_domain_name(buf, algorithm);
00279         dns_marshall_uint16(buf, 0); /* time prefix */
00280         dns_marshall_uint32(buf, time_signed);
00281         dns_marshall_uint16(buf, fudge);
00282         dns_marshall_uint16(buf, mac_length);
00283         dns_marshall_buffer(buf, mac, mac_length);
00284         dns_marshall_uint16(buf, original_id);
00285         dns_marshall_uint16(buf, error);
00286         dns_marshall_uint16(buf, 0); /* Other Size */
00287 
00288         if (!ERR_DNS_IS_OK(buf->error)) {
00289                 err = buf->error;
00290                 goto error;
00291         }
00292 
00293         err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
00294                               buf->offset, buf->data, prec);
00295 
00296  error:
00297         TALLOC_FREE(buf);
00298         return err;
00299 }
00300 
00301 DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
00302                        uint16 *num_records, struct dns_rrec ***records)
00303 {
00304         struct dns_rrec **new_records;
00305 
00306         if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
00307                                                  struct dns_rrec *,
00308                                                  (*num_records)+1))) {
00309                 return ERROR_DNS_NO_MEMORY;
00310         }
00311 
00312         new_records[*num_records] = talloc_move(new_records, &rec);
00313 
00314         *num_records += 1;
00315         *records = new_records;
00316         return ERROR_DNS_SUCCESS;
00317 }
00318 
00319 /*
00320  * Create a request that probes a server whether the list of IP addresses
00321  * provides meets our expectations
00322  */
00323 
00324 DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
00325                            const char *host, int num_ips,
00326                            const struct in_addr *iplist,
00327                            struct dns_update_request **preq)
00328 {
00329         struct dns_update_request *req;
00330         struct dns_rrec *rec;
00331         DNS_ERROR err;
00332         uint16 i;
00333 
00334         err = dns_create_update(mem_ctx, zone, &req);
00335         if (!ERR_DNS_IS_OK(err)) goto error;
00336 
00337         err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
00338         if (!ERR_DNS_IS_OK(err)) goto error;
00339 
00340         err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
00341         if (!ERR_DNS_IS_OK(err)) goto error;
00342 
00343         for (i=0; i<num_ips; i++) {
00344                 err = dns_create_name_in_use_record(req, host,
00345                                                     &iplist[i], &rec);
00346                 if (!ERR_DNS_IS_OK(err)) goto error;
00347 
00348                 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
00349                 if (!ERR_DNS_IS_OK(err)) goto error;
00350         }
00351 
00352         *preq = req;
00353         return ERROR_DNS_SUCCESS;
00354 
00355  error:
00356         TALLOC_FREE(req);
00357         return err;
00358 }
00359                            
00360 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
00361                                     const char *domainname,
00362                                     const char *hostname,
00363                                     const struct in_addr *ip_addrs,
00364                                     size_t num_addrs,
00365                                     struct dns_update_request **preq)
00366 {
00367         struct dns_update_request *req;
00368         struct dns_rrec *rec;
00369         DNS_ERROR err;
00370         size_t i;       
00371 
00372         err = dns_create_update(mem_ctx, domainname, &req);
00373         if (!ERR_DNS_IS_OK(err)) return err;
00374 
00375         /*
00376          * The zone must be used at all
00377          */
00378 
00379         err = dns_create_rrec(req, domainname, QTYPE_ANY, DNS_CLASS_ANY,
00380                               0, 0, NULL, &rec);
00381         if (!ERR_DNS_IS_OK(err)) goto error;
00382 
00383         err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
00384         if (!ERR_DNS_IS_OK(err)) goto error;
00385 
00386         /*
00387          * Delete any existing A records
00388          */
00389 
00390         err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
00391                                        &rec);
00392         if (!ERR_DNS_IS_OK(err)) goto error;
00393         
00394         err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
00395         if (!ERR_DNS_IS_OK(err)) goto error;
00396 
00397         /*
00398          * .. and add our IPs
00399          */
00400 
00401         for ( i=0; i<num_addrs; i++ ) {         
00402                 err = dns_create_a_record(req, hostname, 3600, ip_addrs[i], &rec);
00403                 if (!ERR_DNS_IS_OK(err)) 
00404                         goto error;
00405 
00406                 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
00407                 if (!ERR_DNS_IS_OK(err)) 
00408                         goto error;
00409         }       
00410 
00411         *preq = req;
00412         return ERROR_DNS_SUCCESS;
00413 
00414  error:
00415         TALLOC_FREE(req);
00416         return err;
00417 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7