[BACK]Return to res_update.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libresolv

Annotation of src/lib/libresolv/res_update.c, Revision 1.1

1.1     ! christos    1: /*     $NetBSD: res_update.c,v 1.1.1.2 2012/09/09 16:08:08 christos Exp $      */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
        !             5:  * Copyright (c) 1996-1999 by Internet Software Consortium.
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            17:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: /*! \file
        !            21:  * \brief
        !            22:  * Based on the Dynamic DNS reference implementation by Viraj Bais
        !            23:  * <viraj_bais@ccm.fm.intel.com>
        !            24:  */
        !            25: #include <sys/cdefs.h>
        !            26: #if 0
        !            27: static const char rcsid[] = "Id: res_update.c,v 1.13 2005/04/27 04:56:43 sra Exp ";
        !            28: #else
        !            29: __RCSID("$NetBSD$");
        !            30: #endif
        !            31:
        !            32:
        !            33: #include "port_before.h"
        !            34:
        !            35: #include <sys/param.h>
        !            36: #include <sys/socket.h>
        !            37: #include <sys/time.h>
        !            38:
        !            39: #include <netinet/in.h>
        !            40: #include <arpa/inet.h>
        !            41: #include <arpa/nameser.h>
        !            42:
        !            43: #include <errno.h>
        !            44: #include <limits.h>
        !            45: #include <netdb.h>
        !            46: #include <res_update.h>
        !            47: #include <stdarg.h>
        !            48: #include <stdio.h>
        !            49: #include <stdlib.h>
        !            50: #include <string.h>
        !            51:
        !            52: #include <isc/list.h>
        !            53: #include <resolv.h>
        !            54:
        !            55: #include "port_after.h"
        !            56: #include "res_private.h"
        !            57:
        !            58: /*%
        !            59:  * Separate a linked list of records into groups so that all records
        !            60:  * in a group will belong to a single zone on the nameserver.
        !            61:  * Create a dynamic update packet for each zone and send it to the
        !            62:  * nameservers for that zone, and await answer.
        !            63:  * Abort if error occurs in updating any zone.
        !            64:  * Return the number of zones updated on success, < 0 on error.
        !            65:  *
        !            66:  * On error, caller must deal with the unsynchronized zones
        !            67:  * eg. an A record might have been successfully added to the forward
        !            68:  * zone but the corresponding PTR record would be missing if error
        !            69:  * was encountered while updating the reverse zone.
        !            70:  */
        !            71:
        !            72: struct zonegrp {
        !            73:        char                    z_origin[MAXDNAME];
        !            74:        ns_class                z_class;
        !            75:        union res_sockaddr_union z_nsaddrs[MAXNS];
        !            76:        int                     z_nscount;
        !            77:        int                     z_flags;
        !            78:        TAILQ_HEAD(, ns_updrec) z_rrlist;
        !            79:        TAILQ_ENTRY(zonegrp)    z_link;
        !            80: };
        !            81:
        !            82: #define ZG_F_ZONESECTADDED     0x0001
        !            83:
        !            84: /* Forward. */
        !            85:
        !            86: static void    res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
        !            87:
        !            88: /* Macros. */
        !            89:
        !            90: #define DPRINTF(x) do {\
        !            91:                int save_errno = errno; \
        !            92:                if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \
        !            93:                errno = save_errno; \
        !            94:        } while (/*CONSTCOND*/0)
        !            95:
        !            96: /* Public. */
        !            97:
        !            98: int
        !            99: res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) {
        !           100:        ns_updrec *rrecp;
        !           101:        u_char answer[PACKETSZ];
        !           102:        u_char *packet;
        !           103:        struct zonegrp *zptr, tgrp;
        !           104:        TAILQ_HEAD(, zonegrp) zgrps;
        !           105:        int nzones = 0, nscount = 0, n;
        !           106:        union res_sockaddr_union nsaddrs[MAXNS];
        !           107:
        !           108:        packet = malloc(NS_MAXMSG);
        !           109:        if (packet == NULL) {
        !           110:                DPRINTF(("malloc failed"));
        !           111:                return (0);
        !           112:        }
        !           113:        /* Thread all of the updates onto a list of groups. */
        !           114:        TAILQ_INIT(&zgrps);
        !           115:        memset(&tgrp, 0, sizeof (tgrp));
        !           116:        for (rrecp = rrecp_in; rrecp; rrecp = TAILQ_NEXT(rrecp, r_link)) {
        !           117:                int nscnt;
        !           118:                /* Find the origin for it if there is one. */
        !           119:                tgrp.z_class = rrecp->r_class;
        !           120:                nscnt = res_findzonecut2(statp, rrecp->r_dname, tgrp.z_class,
        !           121:                                         RES_EXHAUSTIVE, tgrp.z_origin,
        !           122:                                         sizeof tgrp.z_origin,
        !           123:                                         tgrp.z_nsaddrs, MAXNS);
        !           124:                if (nscnt <= 0) {
        !           125:                        DPRINTF(("res_findzonecut failed (%d)", nscnt));
        !           126:                        goto done;
        !           127:                }
        !           128:                tgrp.z_nscount = nscnt;
        !           129:                /* Find the group for it if there is one. */
        !           130:                TAILQ_FOREACH(zptr, &zgrps, z_link)
        !           131:                        if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 &&
        !           132:                            tgrp.z_class == zptr->z_class)
        !           133:                                break;
        !           134:                /* Make a group for it if there isn't one. */
        !           135:                if (zptr == NULL) {
        !           136:                        zptr = malloc(sizeof *zptr);
        !           137:                        if (zptr == NULL) {
        !           138:                                DPRINTF(("malloc failed"));
        !           139:                                goto done;
        !           140:                        }
        !           141:                        *zptr = tgrp;
        !           142:                        zptr->z_flags = 0;
        !           143:                        TAILQ_INIT(&zptr->z_rrlist);
        !           144:                        TAILQ_INSERT_TAIL(&zgrps, zptr, z_link);
        !           145:                }
        !           146:                /* Thread this rrecp onto the right group. */
        !           147:                TAILQ_INSERT_TAIL(&zptr->z_rrlist, rrecp, r_glink);
        !           148:        }
        !           149:
        !           150:        TAILQ_FOREACH(zptr, &zgrps, z_link) {
        !           151:                HEADER h;
        !           152:                /* Construct zone section and prepend it. */
        !           153:                rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
        !           154:                                     (u_int)zptr->z_class, ns_t_soa, 0);
        !           155:                if (rrecp == NULL) {
        !           156:                        DPRINTF(("res_mkupdrec failed"));
        !           157:                        goto done;
        !           158:                }
        !           159:                TAILQ_INSERT_HEAD(&zptr->z_rrlist, rrecp, r_glink);
        !           160:                zptr->z_flags |= ZG_F_ZONESECTADDED;
        !           161:
        !           162:                /* Marshall the update message. */
        !           163:                n = res_nmkupdate(statp, TAILQ_FIRST(&zptr->z_rrlist),
        !           164:                                  packet, NS_MAXMSG);
        !           165:                DPRINTF(("res_mkupdate -> %d", n));
        !           166:                if (n < 0)
        !           167:                        goto done;
        !           168:
        !           169:                /* Temporarily replace the resolver's nameserver set. */
        !           170:                nscount = res_getservers(statp, nsaddrs, MAXNS);
        !           171:                res_setservers(statp, zptr->z_nsaddrs, zptr->z_nscount);
        !           172:
        !           173:                /* Send the update and remember the result. */
        !           174:                if (key != NULL)
        !           175:                        n = res_nsendsigned(statp, packet, n, key,
        !           176:                                            answer, (int)sizeof answer);
        !           177:                else
        !           178:                        n = res_nsend(statp, packet, n, answer,
        !           179:                                      (int)sizeof answer);
        !           180:                if (n < 0) {
        !           181:                        DPRINTF(("res_nsend: send error, n=%d (%s)\n",
        !           182:                                 n, strerror(errno)));
        !           183:                        goto done;
        !           184:                }
        !           185:                memcpy(&h, answer, sizeof(h));
        !           186:                if (h.rcode == NOERROR)
        !           187:                        nzones++;
        !           188:
        !           189:                /* Restore resolver's nameserver set. */
        !           190:                res_setservers(statp, nsaddrs, nscount);
        !           191:                nscount = 0;
        !           192:        }
        !           193:  done:
        !           194:        while (!TAILQ_EMPTY(&zgrps)) {
        !           195:                zptr = TAILQ_FIRST(&zgrps);
        !           196:                if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0)
        !           197:                        res_freeupdrec(TAILQ_FIRST(&zptr->z_rrlist));
        !           198:                TAILQ_REMOVE(&zgrps, zptr, z_link);
        !           199:                free(zptr);
        !           200:        }
        !           201:        if (nscount != 0)
        !           202:                res_setservers(statp, nsaddrs, nscount);
        !           203:
        !           204:        free(packet);
        !           205:        return (nzones);
        !           206: }
        !           207:
        !           208: /* Private. */
        !           209:
        !           210: static void
        !           211: res_dprintf(const char *fmt, ...) {
        !           212:        va_list ap;
        !           213:
        !           214:        va_start(ap, fmt);
        !           215:        fputs(";; res_nupdate: ", stderr);
        !           216:        vfprintf(stderr, fmt, ap);
        !           217:        fputc('\n', stderr);
        !           218:        va_end(ap);
        !           219: }

CVSweb <webmaster@jp.NetBSD.org>