Annotation of embedaddon/dhcp/minires/res_update.c, revision 1.1.1.1

1.1       misho       1: #if !defined(lint) && !defined(SABER)
1.1.1.1 ! misho       2: static const char rcsid[] = "$Id: res_update.c,v 1.15.310.2 2009/07/24 22:04:52 sar Exp $";
1.1       misho       3: #endif /* not lint */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
                      7:  * Copyright (c) 1996-2003 by Internet Software Consortium
                      8:  *
                      9:  * Permission to use, copy, modify, and distribute this software for any
                     10:  * purpose with or without fee is hereby granted, provided that the above
                     11:  * copyright notice and this permission notice appear in all copies.
                     12:  *
                     13:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     14:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     15:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     16:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     17:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     18:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     19:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     20:  *
                     21:  *   Internet Systems Consortium, Inc.
                     22:  *   950 Charter Street
                     23:  *   Redwood City, CA 94063
                     24:  *   <info@isc.org>
                     25:  *   https://www.isc.org/
                     26:  */
                     27: 
                     28: /*
                     29:  * Based on the Dynamic DNS reference implementation by Viraj Bais
                     30:  * <viraj_bais@ccm.fm.intel.com>
                     31:  */
                     32: 
                     33: #include <sys/param.h>
                     34: #include <sys/socket.h>
                     35: #include <sys/time.h>
                     36: 
                     37: #include <netinet/in.h>
                     38: #include <arpa/inet.h>
                     39: 
                     40: #include <errno.h>
                     41: #include <limits.h>
                     42: #include <netdb.h>
                     43: #include <stdarg.h>
                     44: #include <stdio.h>
                     45: #include <stdlib.h>
                     46: #include <string.h>
                     47: 
                     48: #include <isc-dhcp/list.h>
                     49: #include "minires/minires.h"
                     50: #include "arpa/nameser.h"
                     51: 
                     52: /*
                     53:  * Separate a linked list of records into groups so that all records
                     54:  * in a group will belong to a single zone on the nameserver.
                     55:  * Create a dynamic update packet for each zone and send it to the
                     56:  * nameservers for that zone, and await answer.
                     57:  * Abort if error occurs in updating any zone.
                     58:  * Return the number of zones updated on success, < 0 on error.
                     59:  *
                     60:  * On error, caller must deal with the unsynchronized zones
                     61:  * eg. an A record might have been successfully added to the forward
                     62:  * zone but the corresponding PTR record would be missing if error
                     63:  * was encountered while updating the reverse zone.
                     64:  */
                     65: 
                     66: struct zonegrp {
                     67:        char z_origin[MAXDNAME];
                     68:        ns_class z_class;
                     69:        struct in_addr z_nsaddrs[MAXNS];
                     70:        int z_nscount;
                     71:        int z_flags;
                     72:        ISC_LIST(ns_updrec) z_rrlist;
                     73:        ISC_LINK(struct zonegrp) z_link;
                     74: };
                     75: 
                     76: #define ZG_F_ZONESECTADDED     0x0001
                     77: 
                     78: /* Forward. */
                     79: 
                     80: static int     nscopy(struct sockaddr_in *, const struct sockaddr_in *, int);
                     81: static int     nsprom(struct sockaddr_in *, const struct in_addr *, int);
                     82: 
                     83: void tkey_free (ns_tsig_key **);
                     84: 
                     85: isc_result_t
                     86: res_nupdate(res_state statp, ns_updrec *rrecp_in) {
                     87:        ns_updrec *rrecp;
                     88:        double answer[PACKETSZ / sizeof (double)];
                     89:        double packet[2*PACKETSZ / sizeof (double)];
                     90:        struct zonegrp *zptr, tgrp;
                     91:        int nscount = 0;
                     92:        unsigned n;
                     93:        unsigned rval;
                     94:        struct sockaddr_in nsaddrs[MAXNS];
                     95:        ns_tsig_key *key;
                     96:        void *zcookie = 0;
                     97:        void *zcookp = &zcookie;
                     98:        isc_result_t rcode;
                     99: 
                    100:       again:
                    101:        /* Make sure all the updates are in the same zone, and find out
                    102:           what zone they are in. */
                    103:        zptr = NULL;
                    104:        for (rrecp = rrecp_in; rrecp; rrecp = ISC_LIST_NEXT(rrecp, r_link)) {
                    105:                /* Find the origin for it if there is one. */
                    106:                tgrp.z_class = rrecp->r_class;
                    107:                rcode = res_findzonecut(statp, rrecp->r_dname, tgrp.z_class,
                    108:                                        RES_EXHAUSTIVE,
                    109:                                        tgrp.z_origin,
                    110:                                        sizeof tgrp.z_origin,
                    111:                                        tgrp.z_nsaddrs, MAXNS, &tgrp.z_nscount,
                    112:                                        zcookp);
                    113:                if (rcode != ISC_R_SUCCESS)
                    114:                        goto done;
                    115:                if (tgrp.z_nscount <= 0) {
                    116:                        rcode = ISC_R_NOTZONE;
                    117:                        goto done;
                    118:                }
                    119:                /* Make a group for it if there isn't one. */
                    120:                if (zptr == NULL) {
                    121:                        zptr = malloc(sizeof *zptr);
                    122:                        if (zptr == NULL) {
                    123:                                rcode = ISC_R_NOMEMORY;
                    124:                                goto done;
                    125:                        }
                    126:                        *zptr = tgrp;
                    127:                        zptr->z_flags = 0;
                    128:                        ISC_LIST_INIT(zptr->z_rrlist);
                    129:                } else if (ns_samename(tgrp.z_origin, zptr->z_origin) == 0 ||
                    130:                           tgrp.z_class != zptr->z_class) {
                    131:                        /* Some of the records are in different zones. */
                    132:                        rcode = ISC_R_CROSSZONE;
                    133:                        goto done;
                    134:                }
                    135:                /* Thread this rrecp onto the zone group. */
                    136:                ISC_LIST_APPEND(zptr->z_rrlist, rrecp, r_glink);
                    137:        }
                    138: 
                    139:        /* Construct zone section and prepend it. */
                    140:        rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
                    141:                             zptr->z_class, ns_t_soa, 0);
                    142:        if (rrecp == NULL) {
                    143:                rcode = ISC_R_UNEXPECTED;
                    144:                goto done;
                    145:        }
                    146:        ISC_LIST_PREPEND(zptr->z_rrlist, rrecp, r_glink);
                    147:        zptr->z_flags |= ZG_F_ZONESECTADDED;
                    148: 
                    149:        /* Marshall the update message. */
                    150:        n = sizeof packet;
                    151:        rcode = res_nmkupdate(statp,
                    152:                              ISC_LIST_HEAD(zptr->z_rrlist), packet, &n);
                    153:        if (rcode != ISC_R_SUCCESS)
                    154:                goto done;
                    155: 
                    156:        /* Temporarily replace the resolver's nameserver set. */
                    157:        nscount = nscopy(nsaddrs, statp->nsaddr_list, statp->nscount);
                    158:        statp->nscount = nsprom(statp->nsaddr_list,
                    159:                                zptr->z_nsaddrs, zptr->z_nscount);
                    160: 
                    161:        /* Send the update and remember the result. */
                    162:        key = (ns_tsig_key *)0;
                    163:        rcode = find_tsig_key (&key, zptr->z_origin, zcookie);
                    164:        if (rcode == ISC_R_SUCCESS) {
                    165:                rcode = res_nsendsigned(statp, packet, n, key,
                    166:                                        answer, sizeof answer, &rval);
                    167:                tkey_free (&key);
                    168:        } else if (rcode == ISC_R_NOTFOUND || rcode == ISC_R_KEY_UNKNOWN) {
                    169:                rcode = res_nsend(statp, packet, n,
                    170:                                  answer, sizeof answer, &rval);
                    171:        }
                    172:        if (rcode != ISC_R_SUCCESS)
                    173:                goto undone;
                    174: 
                    175:        rcode = ns_rcode_to_isc (((HEADER *)answer)->rcode);
                    176:        if (zcookie && rcode == ISC_R_BADSIG) {
                    177:                repudiate_zone (&zcookie);
                    178:        }
                    179: 
                    180:  undone:
                    181:        /* Restore resolver's nameserver set. */
                    182:        statp->nscount = nscopy(statp->nsaddr_list, nsaddrs, nscount);
                    183:        nscount = 0;
                    184:  done:
                    185:        if (zptr) {
                    186:                if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0)
                    187:                        res_freeupdrec(ISC_LIST_HEAD(zptr->z_rrlist));
                    188:                free(zptr);
                    189:        }
                    190: 
                    191:        /* If the update failed because we used a cached zone and it
                    192:           didn't work, try it again without the cached zone. */
                    193:        if (zcookp && (rcode == ISC_R_NOTZONE || rcode == ISC_R_BADSIG)) {
                    194:                zcookp = 0;
                    195:                goto again;
                    196:        }
                    197: 
                    198:        if (zcookie)
                    199:                forget_zone (&zcookie);
                    200:        return rcode;
                    201: }
                    202: 
                    203: /* Private. */
                    204: 
                    205: static int
                    206: nscopy(struct sockaddr_in *dst, const struct sockaddr_in *src, int n) {
                    207:        int i;
                    208: 
                    209:        for (i = 0; i < n; i++)
                    210:                dst[i] = src[i];
                    211:        return (n);
                    212: }
                    213: 
                    214: static int
                    215: nsprom(struct sockaddr_in *dst, const struct in_addr *src, int n) {
                    216:        int i;
                    217: 
                    218:        for (i = 0; i < n; i++) {
                    219:                memset(&dst[i], 0, sizeof dst[i]);
                    220:                dst[i].sin_family = AF_INET;
                    221:                dst[i].sin_port = htons(NS_DEFAULTPORT);
                    222:                dst[i].sin_addr = src[i];
                    223:        }
                    224:        return (n);
                    225: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>