]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/res_update.c
1 #if !defined(lint) && !defined(SABER)
2 static char rcsid
[] = "$Id: res_update.c,v 1.1.1.1 2003/11/19 01:51:39 kyu3 Exp $";
6 * Copyright (c) 1996 by Internet Software Consortium.
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
13 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
14 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
18 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 * Portions copyright (c) 1999, 2000
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
41 * This product includes software developed by Intel Corporation and
44 * 4. Neither the name of Intel Corporation or its contributors may be
45 * used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
49 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
52 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58 * THE POSSIBILITY OF SUCH DAMAGE.
63 * Based on the Dynamic DNS reference implementation by Viraj Bais
64 * <viraj_bais@ccm.fm.intel.com>
67 #include <sys/param.h>
68 #include <sys/socket.h>
70 #include <netinet/in.h>
71 #include <arpa/inet.h>
72 #include <arpa/nameser.h>
82 * Separate a linked list of records into groups so that all records
83 * in a group will belong to a single zone on the nameserver.
84 * Create a dynamic update packet for each zone and send it to the
85 * nameservers for that zone, and await answer.
86 * Abort if error occurs in updating any zone.
87 * Return the number of zones updated on success, < 0 on error.
89 * On error, caller must deal with the unsynchronized zones
90 * eg. an A record might have been successfully added to the forward
91 * zone but the corresponding PTR record would be missing if error
92 * was encountered while updating the reverse zone.
98 char nsname
[MAXDNAME
];
99 struct in_addr nsaddr1
;
103 char z_origin
[MAXDNAME
];
105 char z_soardata
[MAXDNAME
+ 5 * INT32SZ
];
106 struct ns1 z_ns
[NSMAX
];
109 struct zonegrp
*z_next
;
114 res_update(ns_updrec
*rrecp_in
) {
115 ns_updrec
*rrecp
, *tmprrecp
;
116 u_char buf
[PACKETSZ
], answer
[PACKETSZ
], packet
[2*PACKETSZ
];
117 char name
[MAXDNAME
], zname
[MAXDNAME
], primary
[MAXDNAME
],
119 u_char soardata
[2*MAXCDNAME
+5*INT32SZ
];
120 char *dname
, *svdname
, *cp1
, *target
;
122 HEADER
*hp
= (HEADER
*) answer
;
123 struct zonegrp
*zptr
= NULL
, *tmpzptr
, *prevzptr
, *zgrp_start
= NULL
;
124 int i
, j
, k
= 0, n
, ancount
, nscount
, arcount
, rcode
, rdatasize
,
125 newgroup
, done
, myzone
, seen_before
, numzones
= 0;
126 u_int16_t dlen
, class, qclass
, type
, qtype
;
129 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
130 h_errno
= NETDB_INTERNAL
;
134 for (rrecp
= rrecp_in
; rrecp
; rrecp
= rrecp
->r_next
) {
135 dname
= rrecp
->r_dname
;
136 n
= (int)strlen(dname
);
137 if (dname
[n
-1] == '.')
140 qclass
= rrecp
->r_class
;
144 while (!done
&& dname
) {
145 if (qtype
== T_SOA
) {
146 for (tmpzptr
= zgrp_start
;
147 tmpzptr
&& !seen_before
;
148 tmpzptr
= tmpzptr
->z_next
) {
149 if (strcasecmp(dname
,
150 tmpzptr
->z_origin
) == 0 &&
151 tmpzptr
->z_class
== qclass
)
153 for (tmprrecp
= tmpzptr
->z_rr
;
154 tmprrecp
&& !seen_before
;
155 tmprrecp
= tmprrecp
->r_grpnext
)
156 if (strcasecmp(dname
, tmprrecp
->r_dname
) == 0
157 && tmprrecp
->r_class
== qclass
) {
163 * Append to the end of
166 for (tmprrecp
= tmpzptr
->z_rr
;
168 tmprrecp
= tmprrecp
->r_grpnext
)
170 tmprrecp
->r_grpnext
= rrecp
;
171 rrecp
->r_grpnext
= NULL
;
176 } else if (qtype
== T_A
) {
177 for (tmpzptr
= zgrp_start
;
179 tmpzptr
= tmpzptr
->z_next
)
180 for (i
= 0; i
< tmpzptr
->z_nscount
; i
++)
181 if (tmpzptr
->z_class
== qclass
&&
182 strcasecmp(tmpzptr
->z_ns
[i
].nsname
,
184 tmpzptr
->z_ns
[i
].nsaddr1
.s_addr
!= 0) {
185 zptr
->z_ns
[k
].nsaddr1
.s_addr
=
186 tmpzptr
->z_ns
[i
].nsaddr1
.s_addr
;
193 n
= res_mkquery(QUERY
, dname
, qclass
, qtype
, NULL
,
194 0, NULL
, buf
, sizeof buf
);
196 fprintf(stderr
, "res_update: mkquery failed\n");
199 n
= res_send(buf
, n
, answer
, sizeof answer
);
201 fprintf(stderr
, "res_update: send error for %s\n",
207 ancount
= ntohs(hp
->ancount
);
208 nscount
= ntohs(hp
->nscount
);
209 arcount
= ntohs(hp
->arcount
);
211 cp
= answer
+ HFIXEDSZ
;
213 /* skip the question section */
214 n
= dn_skipname(cp
, eom
);
215 if (n
< 0 || cp
+ n
+ 2 * INT16SZ
> eom
)
217 cp
+= n
+ 2 * INT16SZ
;
219 if (qtype
== T_SOA
) {
220 if (ancount
== 0 && nscount
== 0 && arcount
== 0) {
222 * if (rcode == NOERROR) then the dname exists but
223 * has no soa record associated with it.
224 * if (rcode == NXDOMAIN) then the dname does not
225 * exist and the server is replying out of NCACHE.
226 * in either case, proceed with the next try
228 dname
= strchr(dname
, '.');
232 } else if ((rcode
== NOERROR
|| rcode
== NXDOMAIN
) &&
234 nscount
== 1 && arcount
== 0) {
236 * name/data does not exist, soa record supplied in the
239 /* authority section must contain the soa record */
240 if ((n
= dn_expand(answer
, eom
, cp
, zname
,
244 if (cp
+ 2 * INT16SZ
> eom
)
248 if (type
!= T_SOA
|| class != qclass
) {
249 fprintf(stderr
, "unknown answer\n");
255 if (strcasecmp(dname
, zname
) == 0) {
258 } else if ((dname
= strchr(dname
, '.')) != NULL
)
261 dname
= strchr(svdname
, '.');
268 } else if (rcode
== NOERROR
&& ancount
== 1) {
270 * found the zone name
271 * new servers will supply NS records for the zone
272 * in authority section and A records for those
273 * nameservers in the additional section
274 * older servers have to be explicitly queried for
275 * NS records for the zone
277 /* answer section must contain the soa record */
278 if ((n
= dn_expand(answer
, eom
, cp
, zname
,
283 if (cp
+ 2 * INT16SZ
> eom
)
287 if (type
== T_CNAME
) {
288 dname
= strchr(dname
, '.');
293 if (strcasecmp(dname
, zname
) != 0 ||
295 class != rrecp
->r_class
) {
296 fprintf(stderr
, "unknown answer\n");
302 "unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n",
303 ancount
, nscount
, arcount
, hp
->rcode
);
306 if (cp
+ INT32SZ
+ INT16SZ
> eom
)
308 /* continue processing the soa record */
317 if (strcasecmp(zname
, zptr
->z_origin
) == 0 &&
318 type
== T_SOA
&& class == qclass
) {
326 for (tmprrecp
= zptr
->z_rr
;
328 tmprrecp
= tmprrecp
->r_grpnext
)
330 tmprrecp
->r_grpnext
= rrecp
;
331 rrecp
->r_grpnext
= NULL
;
336 if ((n
= dn_expand(answer
, eom
, cp
, primary
,
337 sizeof primary
)) < 0)
341 * We don't have to bounds check here because the
342 * next use of 'cp' is in dn_expand().
344 cp1
= (char *)soardata
;
345 strcpy(cp1
, primary
);
346 cp1
+= strlen(cp1
) + 1;
347 if ((n
= dn_expand(answer
, eom
, cp
, mailaddr
,
348 sizeof mailaddr
)) < 0)
351 strcpy(cp1
, mailaddr
);
352 cp1
+= strlen(cp1
) + 1;
353 if (cp
+ 5*INT32SZ
> eom
)
355 memcpy(cp1
, cp
, 5*INT32SZ
);
358 rdatasize
= (int)((u_char
*)cp1
- soardata
);
359 zptr
= calloc(1, sizeof(struct zonegrp
));
362 if (zgrp_start
== NULL
)
365 prevzptr
->z_next
= zptr
;
367 rrecp
->r_grpnext
= NULL
;
368 strcpy(zptr
->z_origin
, zname
);
369 zptr
->z_class
= class;
370 memcpy(zptr
->z_soardata
, soardata
, rdatasize
);
371 /* fallthrough to process NS and A records */
373 } else if (qtype
== T_NS
) {
374 if (rcode
== NOERROR
&& ancount
> 0) {
375 strcpy(zname
, dname
);
376 for (zptr
= zgrp_start
; zptr
; zptr
= zptr
->z_next
) {
377 if (strcasecmp(zname
, zptr
->z_origin
) == 0)
381 /* should not happen */
385 * answer and authority sections contain
386 * the same information, skip answer section
388 for (j
= 0; j
< ancount
; j
++) {
389 n
= dn_skipname(cp
, eom
);
392 n
+= 2*INT16SZ
+ INT32SZ
;
393 if (cp
+ n
+ INT16SZ
> eom
)
401 /* fallthrough to process NS and A records */
403 fprintf(stderr
, "cannot determine nameservers for %s:\
404 ans=%d, auth=%d, add=%d, rcode=%d\n",
405 dname
, ancount
, nscount
, arcount
, hp
->rcode
);
408 } else if (qtype
== T_A
) {
409 if (rcode
== NOERROR
&& ancount
> 0) {
411 ancount
= nscount
= 0;
412 /* fallthrough to process A records */
414 fprintf(stderr
, "cannot determine address for %s:\
415 ans=%d, auth=%d, add=%d, rcode=%d\n",
416 dname
, ancount
, nscount
, arcount
, hp
->rcode
);
420 /* process NS records for the zone */
422 for (i
= 0; i
< nscount
; i
++) {
423 if ((n
= dn_expand(answer
, eom
, cp
, name
,
427 if (cp
+ 3 * INT16SZ
+ INT32SZ
> eom
)
435 if (strcasecmp(name
, zname
) == 0 &&
436 type
== T_NS
&& class == qclass
) {
437 if ((n
= dn_expand(answer
, eom
, cp
,
438 name
, sizeof name
)) < 0)
440 target
= zptr
->z_ns
[j
++].nsname
;
441 strcpy(target
, name
);
445 if (zptr
->z_nscount
== 0)
447 /* get addresses for the nameservers */
448 for (i
= 0; i
< arcount
; i
++) {
449 if ((n
= dn_expand(answer
, eom
, cp
, name
,
453 if (cp
+ 3 * INT16SZ
+ INT32SZ
> eom
)
461 if (type
== T_A
&& dlen
== INT32SZ
&& class == qclass
) {
462 for (j
= 0; j
< zptr
->z_nscount
; j
++)
463 if (strcasecmp(name
, zptr
->z_ns
[j
].nsname
) == 0) {
464 memcpy(&zptr
->z_ns
[j
].nsaddr1
.s_addr
, cp
,
471 if (zptr
->z_nscount
== 0) {
477 for (k
= 0; k
< zptr
->z_nscount
; k
++)
478 if (zptr
->z_ns
[k
].nsaddr1
.s_addr
== 0) {
480 dname
= zptr
->z_ns
[k
].nsname
;
487 _res
.options
|= RES_DEBUG
;
488 for (zptr
= zgrp_start
; zptr
; zptr
= zptr
->z_next
) {
490 /* append zone section */
491 rrecp
= res_mkupdrec(ns_s_zn
, zptr
->z_origin
,
492 zptr
->z_class
, ns_t_soa
, 0);
494 fprintf(stderr
, "saverrec error\n");
498 rrecp
->r_grpnext
= zptr
->z_rr
;
501 n
= res_mkupdate(zptr
->z_rr
, packet
, sizeof packet
);
503 fprintf(stderr
, "res_mkupdate error\n");
507 fprintf(stdout
, "res_mkupdate: packet size = %d\n", n
);
510 * Override the list of NS records from res_init() with
511 * the authoritative nameservers for the zone being updated.
512 * Sort primary to be the first in the list of nameservers.
514 for (i
= 0; i
< zptr
->z_nscount
; i
++) {
515 if (strcasecmp(zptr
->z_ns
[i
].nsname
,
516 zptr
->z_soardata
) == 0) {
517 struct in_addr tmpaddr
;
520 strcpy(zptr
->z_ns
[i
].nsname
,
521 zptr
->z_ns
[0].nsname
);
522 strcpy(zptr
->z_ns
[0].nsname
,
524 tmpaddr
= zptr
->z_ns
[i
].nsaddr1
;
525 zptr
->z_ns
[i
].nsaddr1
=
526 zptr
->z_ns
[0].nsaddr1
;
527 zptr
->z_ns
[0].nsaddr1
= tmpaddr
;
532 for (i
= 0; i
< MAXNS
; i
++) {
533 _res
.nsaddr_list
[i
].sin_addr
= zptr
->z_ns
[i
].nsaddr1
;
534 _res
.nsaddr_list
[i
].sin_family
= AF_INET
;
535 _res
.nsaddr_list
[i
].sin_port
= htons(NAMESERVER_PORT
);
537 _res
.nscount
= (zptr
->z_nscount
< MAXNS
) ?
538 zptr
->z_nscount
: MAXNS
;
539 n
= res_send(packet
, n
, answer
, sizeof(answer
));
541 fprintf(stderr
, "res_send: send error, n=%d\n", n
);
547 /* free malloc'ed memory */
550 zgrp_start
= zgrp_start
->z_next
;
551 res_freeupdrec(zptr
->z_rr
); /* Zone section we allocated. */