root/source3/libaddns/dnsrecord.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dns_create_query
  2. dns_create_update
  3. dns_create_rrec
  4. dns_create_a_record
  5. dns_create_name_in_use_record
  6. dns_create_name_not_in_use_record
  7. dns_create_delete_record
  8. dns_create_tkey_record
  9. dns_unmarshall_tkey_record
  10. dns_create_tsig_record
  11. dns_add_rrec
  12. dns_create_probe
  13. dns_create_update_request

   1 /*
   2   Linux DNS client library implementation
   3   Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
   4   Copyright (C) 2006 Gerald Carter <jerry@samba.org>
   5 
   6      ** NOTE! The following LGPL license applies to the libaddns
   7      ** library. This does NOT imply that all of Samba is released
   8      ** under the LGPL
   9 
  10   This library is free software; you can redistribute it and/or
  11   modify it under the terms of the GNU Lesser General Public
  12   License as published by the Free Software Foundation; either
  13   version 2.1 of the License, or (at your option) any later version.
  14 
  15   This library is distributed in the hope that it will be useful,
  16   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18   Lesser General Public License for more details.
  19 
  20   You should have received a copy of the GNU Lesser General Public
  21   License along with this library; if not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "dns.h"
  25 
  26 DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
  27                             uint16 q_type, uint16 q_class,
  28                             struct dns_request **preq )
  29 {
  30         struct dns_request *req;
  31         struct dns_question *q;
  32         DNS_ERROR err;
  33 
  34         if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) ||
  35             !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) ||
  36             !(req->questions[0] = talloc(req->questions,
  37                                          struct dns_question))) {
  38                 TALLOC_FREE(req);
  39                 return ERROR_DNS_NO_MEMORY;
  40         }
  41 
  42         req->id = random();
  43 
  44         req->num_questions = 1;
  45         q = req->questions[0];
  46 
  47         err = dns_domain_name_from_string(q, name, &q->name);
  48         if (!ERR_DNS_IS_OK(err)) {
  49                 TALLOC_FREE(req);
  50                 return err;
  51         }
  52 
  53         q->q_type = q_type;
  54         q->q_class = q_class;
  55 
  56         *preq = req;
  57         return ERROR_DNS_SUCCESS;
  58 }
  59 
  60 DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
  61                              struct dns_update_request **preq )
  62 {
  63         struct dns_update_request *req;
  64         struct dns_zone *z;
  65         DNS_ERROR err;
  66 
  67         if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) ||
  68             !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) ||
  69             !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
  70                 TALLOC_FREE(req);
  71                 return ERROR_DNS_NO_MEMORY;
  72         }
  73 
  74         req->id = random();
  75         req->flags = 0x2800;    /* Dynamic update */
  76 
  77         req->num_zones = 1;
  78         z = req->zones[0];
  79 
  80         err = dns_domain_name_from_string(z, name, &z->name);
  81         if (!ERR_DNS_IS_OK(err)) {
  82                 TALLOC_FREE(req);
  83                 return err;
  84         }
  85 
  86         z->z_type = QTYPE_SOA;
  87         z->z_class = DNS_CLASS_IN;
  88 
  89         *preq = req;
  90         return ERROR_DNS_SUCCESS;
  91 }
  92 
  93 DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
  94                           uint16 type, uint16 r_class, uint32 ttl,
  95                           uint16 data_length, uint8 *data,
  96                           struct dns_rrec **prec)
  97 {
  98         struct dns_rrec *rec;
  99         DNS_ERROR err;
 100 
 101         if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
 102                 return ERROR_DNS_NO_MEMORY;
 103         }
 104 
 105         err = dns_domain_name_from_string(rec, name, &rec->name);
 106         if (!(ERR_DNS_IS_OK(err))) {
 107                 TALLOC_FREE(rec);
 108                 return err;
 109         }
 110 
 111         rec->type = type;
 112         rec->r_class = r_class;
 113         rec->ttl = ttl;
 114         rec->data_length = data_length;
 115         rec->data = talloc_move(rec, &data);
 116 
 117         *prec = rec;
 118         return ERROR_DNS_SUCCESS;
 119 }
 120 
 121 DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
     /* [<][>][^][v][top][bottom][index][help] */
 122                               uint32 ttl, const struct sockaddr_storage *pss,
 123                               struct dns_rrec **prec)
 124 {
 125         uint8 *data;
 126         DNS_ERROR err;
 127         struct in_addr ip;
 128 
 129         if (pss->ss_family != AF_INET) {
 130                 /* Silently ignore this. */
 131                 return ERROR_DNS_SUCCESS;
 132         }
 133 
 134         ip = ((struct sockaddr_in *)pss)->sin_addr;
 135         if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr,
 136                                             sizeof(ip.s_addr)))) {
 137                 return ERROR_DNS_NO_MEMORY;
 138         }
 139 
 140         err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
 141                               sizeof(ip.s_addr), data, prec);
 142 
 143         if (!ERR_DNS_IS_OK(err)) {
 144                 TALLOC_FREE(data);
 145         }
 146 
 147         return err;
 148 }
 149 
 150 DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 151                                         const char *name,
 152                                         const struct sockaddr_storage *ss,
 153                                         struct dns_rrec **prec)
 154 {
 155         if (ss != NULL) {
 156                 return dns_create_a_record(mem_ctx, name, 0, ss, prec);
 157         }
 158 
 159         return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
 160                                NULL, prec);
 161 }
 162 
 163 DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 164                                             const char *name, uint32 type,
 165                                             struct dns_rrec **prec)
 166 {
 167         return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
 168                                0, NULL, prec);
 169 }
 170 
 171 DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
 172                                    uint16 type, uint16 r_class,
 173                                    struct dns_rrec **prec)
 174 {
 175         return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
 176 }
 177 
 178 DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
     /* [<][>][^][v][top][bottom][index][help] */
 179                                  const char *algorithm_name, time_t inception,
 180                                  time_t expiration, uint16 mode, uint16 error,
 181                                  uint16 key_length, const uint8 *key,
 182                                  struct dns_rrec **prec)
 183 {
 184         struct dns_buffer *buf;
 185         struct dns_domain_name *algorithm;
 186         DNS_ERROR err;
 187 
 188         if (!(buf = dns_create_buffer(mem_ctx))) {
 189                 return ERROR_DNS_NO_MEMORY;
 190         }
 191 
 192         err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
 193         if (!ERR_DNS_IS_OK(err)) goto error;
 194 
 195         dns_marshall_domain_name(buf, algorithm);
 196         dns_marshall_uint32(buf, inception);
 197         dns_marshall_uint32(buf, expiration);
 198         dns_marshall_uint16(buf, mode);
 199         dns_marshall_uint16(buf, error);
 200         dns_marshall_uint16(buf, key_length);
 201         dns_marshall_buffer(buf, key, key_length);
 202         dns_marshall_uint16(buf, 0); /* Other Size */
 203 
 204         if (!ERR_DNS_IS_OK(buf->error)) {
 205                 err = buf->error;
 206                 goto error;
 207         }
 208 
 209         err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
 210                               buf->offset, buf->data, prec);
 211 
 212  error:
 213         TALLOC_FREE(buf);
 214         return err;
 215 }
 216 
 217 DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
     /* [<][>][^][v][top][bottom][index][help] */
 218                                      struct dns_tkey_record **ptkey)
 219 {
 220         struct dns_tkey_record *tkey;
 221         struct dns_buffer buf;
 222         uint32 tmp_inception, tmp_expiration;
 223         
 224         if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
 225                 return ERROR_DNS_NO_MEMORY;
 226         }
 227 
 228         buf.data = rec->data;
 229         buf.size = rec->data_length;
 230         buf.offset = 0;
 231         buf.error = ERROR_DNS_SUCCESS;
 232 
 233         dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
 234         dns_unmarshall_uint32(&buf, &tmp_inception);
 235         dns_unmarshall_uint32(&buf, &tmp_expiration);
 236         dns_unmarshall_uint16(&buf, &tkey->mode);
 237         dns_unmarshall_uint16(&buf, &tkey->error);
 238         dns_unmarshall_uint16(&buf, &tkey->key_length);
 239 
 240         if (!ERR_DNS_IS_OK(buf.error)) goto error;
 241 
 242         if (tkey->key_length) {
 243                 if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
 244                         buf.error = ERROR_DNS_NO_MEMORY;
 245                         goto error;
 246                 }
 247         } else {
 248                 tkey->key = NULL;
 249         }
 250 
 251         dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
 252         if (!ERR_DNS_IS_OK(buf.error)) goto error;
 253 
 254         tkey->inception = (time_t)tmp_inception;
 255         tkey->expiration = (time_t)tmp_expiration;
 256 
 257         *ptkey = tkey;
 258         return ERROR_DNS_SUCCESS;
 259 
 260  error:
 261         TALLOC_FREE(tkey);
 262         return buf.error;
 263 }
 264 
 265 DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
     /* [<][>][^][v][top][bottom][index][help] */
 266                                  const char *algorithm_name,
 267                                  time_t time_signed, uint16 fudge,
 268                                  uint16 mac_length, const uint8 *mac,
 269                                  uint16 original_id, uint16 error,
 270                                  struct dns_rrec **prec)
 271 {
 272         struct dns_buffer *buf;
 273         struct dns_domain_name *algorithm;
 274         DNS_ERROR err;
 275 
 276         if (!(buf = dns_create_buffer(mem_ctx))) {
 277                 return ERROR_DNS_NO_MEMORY;
 278         }
 279 
 280         err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
 281         if (!ERR_DNS_IS_OK(err)) goto error;
 282 
 283         dns_marshall_domain_name(buf, algorithm);
 284         dns_marshall_uint16(buf, 0); /* time prefix */
 285         dns_marshall_uint32(buf, time_signed);
 286         dns_marshall_uint16(buf, fudge);
 287         dns_marshall_uint16(buf, mac_length);
 288         dns_marshall_buffer(buf, mac, mac_length);
 289         dns_marshall_uint16(buf, original_id);
 290         dns_marshall_uint16(buf, error);
 291         dns_marshall_uint16(buf, 0); /* Other Size */
 292 
 293         if (!ERR_DNS_IS_OK(buf->error)) {
 294                 err = buf->error;
 295                 goto error;
 296         }
 297 
 298         err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
 299                               buf->offset, buf->data, prec);
 300 
 301  error:
 302         TALLOC_FREE(buf);
 303         return err;
 304 }
 305 
 306 DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
     /* [<][>][^][v][top][bottom][index][help] */
 307                        uint16 *num_records, struct dns_rrec ***records)
 308 {
 309         struct dns_rrec **new_records;
 310 
 311         if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
 312                                                  struct dns_rrec *,
 313                                                  (*num_records)+1))) {
 314                 return ERROR_DNS_NO_MEMORY;
 315         }
 316 
 317         new_records[*num_records] = talloc_move(new_records, &rec);
 318 
 319         *num_records += 1;
 320         *records = new_records;
 321         return ERROR_DNS_SUCCESS;
 322 }
 323 
 324 /*
 325  * Create a request that probes a server whether the list of IP addresses
 326  * provides meets our expectations
 327  */
 328 
 329 DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
     /* [<][>][^][v][top][bottom][index][help] */
 330                            const char *host, int num_ips,
 331                            const struct sockaddr_storage *sslist,
 332                            struct dns_update_request **preq)
 333 {
 334         struct dns_update_request *req;
 335         struct dns_rrec *rec;
 336         DNS_ERROR err;
 337         uint16 i;
 338 
 339         err = dns_create_update(mem_ctx, zone, &req);
 340         if (!ERR_DNS_IS_OK(err)) goto error;
 341 
 342         err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
 343         if (!ERR_DNS_IS_OK(err)) goto error;
 344 
 345         err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
 346         if (!ERR_DNS_IS_OK(err)) goto error;
 347 
 348         for (i=0; i<num_ips; i++) {
 349                 err = dns_create_name_in_use_record(req, host,
 350                                                     &sslist[i], &rec);
 351                 if (!ERR_DNS_IS_OK(err)) goto error;
 352 
 353                 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
 354                 if (!ERR_DNS_IS_OK(err)) goto error;
 355         }
 356 
 357         *preq = req;
 358         return ERROR_DNS_SUCCESS;
 359 
 360  error:
 361         TALLOC_FREE(req);
 362         return err;
 363 }
 364                            
 365 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 366                                     const char *domainname,
 367                                     const char *hostname,
 368                                     const struct sockaddr_storage *ss_addrs,
 369                                     size_t num_addrs,
 370                                     struct dns_update_request **preq)
 371 {
 372         struct dns_update_request *req;
 373         struct dns_rrec *rec;
 374         DNS_ERROR err;
 375         size_t i;
 376 
 377         err = dns_create_update(mem_ctx, domainname, &req);
 378         if (!ERR_DNS_IS_OK(err)) return err;
 379 
 380         /*
 381          * Use the same prereq as WinXP -- No CNAME records for this host.
 382          */
 383 
 384         err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
 385                               0, 0, NULL, &rec);
 386         if (!ERR_DNS_IS_OK(err)) goto error;
 387 
 388         err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
 389         if (!ERR_DNS_IS_OK(err)) goto error;
 390 
 391         /*
 392          * Delete any existing A records
 393          */
 394 
 395         err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
 396                                        &rec);
 397         if (!ERR_DNS_IS_OK(err)) goto error;
 398 
 399         err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
 400         if (!ERR_DNS_IS_OK(err)) goto error;
 401 
 402         /*
 403          * .. and add our IPs
 404          */
 405 
 406         for ( i=0; i<num_addrs; i++ ) {
 407                 err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
 408                 if (!ERR_DNS_IS_OK(err))
 409                         goto error;
 410 
 411                 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
 412                 if (!ERR_DNS_IS_OK(err))
 413                         goto error;
 414         }
 415 
 416         *preq = req;
 417         return ERROR_DNS_SUCCESS;
 418 
 419  error:
 420         TALLOC_FREE(req);
 421         return err;
 422 }

/* [<][>][^][v][top][bottom][index][help] */