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

1.1     ! misho       1: #if !defined(lint) && !defined(SABER)
        !             2: static const char rcsid[] = "$Id: res_update.c,v 1.15.310.2 2009-07-24 22:04:52 sar Exp $";
        !             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>