d7ce7006 |
1 | #if !defined(lint) && !defined(SABER)\r |
2 | static char rcsid[] = "$Id: res_update.c,v 1.1.1.1 2003/11/19 01:51:39 kyu3 Exp $";\r |
3 | #endif /* not lint */\r |
4 | \r |
5 | /*\r |
6 | * Copyright (c) 1996 by Internet Software Consortium.\r |
7 | *\r |
8 | * Permission to use, copy, modify, and distribute this software for any\r |
9 | * purpose with or without fee is hereby granted, provided that the above\r |
10 | * copyright notice and this permission notice appear in all copies.\r |
11 | *\r |
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS\r |
13 | * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES\r |
14 | * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE\r |
15 | * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\r |
16 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\r |
17 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\r |
18 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r |
19 | * SOFTWARE.\r |
20 | */\r |
21 | \r |
22 | /*\r |
23 | * Portions copyright (c) 1999, 2000\r |
24 | * Intel Corporation.\r |
25 | * All rights reserved.\r |
26 | *\r |
27 | * Redistribution and use in source and binary forms, with or without\r |
28 | * modification, are permitted provided that the following conditions\r |
29 | * are met:\r |
30 | *\r |
31 | * 1. Redistributions of source code must retain the above copyright\r |
32 | * notice, this list of conditions and the following disclaimer.\r |
33 | *\r |
34 | * 2. Redistributions in binary form must reproduce the above copyright\r |
35 | * notice, this list of conditions and the following disclaimer in the\r |
36 | * documentation and/or other materials provided with the distribution.\r |
37 | *\r |
38 | * 3. All advertising materials mentioning features or use of this software\r |
39 | * must display the following acknowledgement:\r |
40 | *\r |
41 | * This product includes software developed by Intel Corporation and\r |
42 | * its contributors.\r |
43 | *\r |
44 | * 4. Neither the name of Intel Corporation or its contributors may be\r |
45 | * used to endorse or promote products derived from this software\r |
46 | * without specific prior written permission.\r |
47 | *\r |
48 | * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''\r |
49 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE\r |
52 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r |
53 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r |
54 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r |
55 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r |
56 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r |
57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r |
58 | * THE POSSIBILITY OF SUCH DAMAGE.\r |
59 | *\r |
60 | */\r |
61 | \r |
62 | /*\r |
63 | * Based on the Dynamic DNS reference implementation by Viraj Bais\r |
64 | * <viraj_bais@ccm.fm.intel.com>\r |
65 | */\r |
66 | \r |
67 | #include <sys/param.h>\r |
68 | #include <sys/socket.h>\r |
69 | #include <sys/time.h>\r |
70 | #include <netinet/in.h>\r |
71 | #include <arpa/inet.h>\r |
72 | #include <arpa/nameser.h>\r |
73 | #include <errno.h>\r |
74 | #include <limits.h>\r |
75 | #include <netdb.h>\r |
76 | #include <resolv.h>\r |
77 | #include <stdio.h>\r |
78 | #include <stdlib.h>\r |
79 | #include <string.h>\r |
80 | \r |
81 | /*\r |
82 | * Separate a linked list of records into groups so that all records\r |
83 | * in a group will belong to a single zone on the nameserver.\r |
84 | * Create a dynamic update packet for each zone and send it to the\r |
85 | * nameservers for that zone, and await answer.\r |
86 | * Abort if error occurs in updating any zone.\r |
87 | * Return the number of zones updated on success, < 0 on error.\r |
88 | *\r |
89 | * On error, caller must deal with the unsynchronized zones\r |
90 | * eg. an A record might have been successfully added to the forward\r |
91 | * zone but the corresponding PTR record would be missing if error\r |
92 | * was encountered while updating the reverse zone.\r |
93 | */\r |
94 | \r |
95 | #define NSMAX 16\r |
96 | \r |
97 | struct ns1 {\r |
98 | char nsname[MAXDNAME];\r |
99 | struct in_addr nsaddr1;\r |
100 | };\r |
101 | \r |
102 | struct zonegrp {\r |
103 | char z_origin[MAXDNAME];\r |
104 | int16_t z_class;\r |
105 | char z_soardata[MAXDNAME + 5 * INT32SZ];\r |
106 | struct ns1 z_ns[NSMAX];\r |
107 | int z_nscount;\r |
108 | ns_updrec * z_rr;\r |
109 | struct zonegrp *z_next;\r |
110 | };\r |
111 | \r |
112 | \r |
113 | int\r |
114 | res_update(ns_updrec *rrecp_in) {\r |
115 | ns_updrec *rrecp, *tmprrecp;\r |
116 | u_char buf[PACKETSZ], answer[PACKETSZ], packet[2*PACKETSZ];\r |
117 | char name[MAXDNAME], zname[MAXDNAME], primary[MAXDNAME],\r |
118 | mailaddr[MAXDNAME];\r |
119 | u_char soardata[2*MAXCDNAME+5*INT32SZ];\r |
120 | char *dname, *svdname, *cp1, *target;\r |
121 | u_char *cp, *eom;\r |
122 | HEADER *hp = (HEADER *) answer;\r |
123 | struct zonegrp *zptr = NULL, *tmpzptr, *prevzptr, *zgrp_start = NULL;\r |
124 | int i, j, k = 0, n, ancount, nscount, arcount, rcode, rdatasize,\r |
125 | newgroup, done, myzone, seen_before, numzones = 0;\r |
126 | u_int16_t dlen, class, qclass, type, qtype;\r |
127 | u_int32_t ttl;\r |
128 | \r |
129 | if ((_res.options & RES_INIT) == 0 && res_init() == -1) {\r |
130 | h_errno = NETDB_INTERNAL;\r |
131 | return (-1);\r |
132 | }\r |
133 | \r |
134 | for (rrecp = rrecp_in; rrecp; rrecp = rrecp->r_next) {\r |
135 | dname = rrecp->r_dname;\r |
136 | n = (int)strlen(dname);\r |
137 | if (dname[n-1] == '.')\r |
138 | dname[n-1] = '\0';\r |
139 | qtype = T_SOA;\r |
140 | qclass = rrecp->r_class;\r |
141 | done = 0;\r |
142 | seen_before = 0;\r |
143 | \r |
144 | while (!done && dname) {\r |
145 | if (qtype == T_SOA) {\r |
146 | for (tmpzptr = zgrp_start;\r |
147 | tmpzptr && !seen_before;\r |
148 | tmpzptr = tmpzptr->z_next) {\r |
149 | if (strcasecmp(dname,\r |
150 | tmpzptr->z_origin) == 0 &&\r |
151 | tmpzptr->z_class == qclass)\r |
152 | seen_before++;\r |
153 | for (tmprrecp = tmpzptr->z_rr;\r |
154 | tmprrecp && !seen_before;\r |
155 | tmprrecp = tmprrecp->r_grpnext)\r |
156 | if (strcasecmp(dname, tmprrecp->r_dname) == 0\r |
157 | && tmprrecp->r_class == qclass) {\r |
158 | seen_before++;\r |
159 | break;\r |
160 | }\r |
161 | if (seen_before) {\r |
162 | /*\r |
163 | * Append to the end of\r |
164 | * current group.\r |
165 | */\r |
166 | for (tmprrecp = tmpzptr->z_rr;\r |
167 | tmprrecp->r_grpnext;\r |
168 | tmprrecp = tmprrecp->r_grpnext)\r |
169 | (void)NULL;\r |
170 | tmprrecp->r_grpnext = rrecp;\r |
171 | rrecp->r_grpnext = NULL;\r |
172 | done = 1;\r |
173 | break;\r |
174 | }\r |
175 | }\r |
176 | } else if (qtype == T_A) {\r |
177 | for (tmpzptr = zgrp_start;\r |
178 | tmpzptr && !done;\r |
179 | tmpzptr = tmpzptr->z_next)\r |
180 | for (i = 0; i < tmpzptr->z_nscount; i++)\r |
181 | if (tmpzptr->z_class == qclass &&\r |
182 | strcasecmp(tmpzptr->z_ns[i].nsname,\r |
183 | dname) == 0 &&\r |
184 | tmpzptr->z_ns[i].nsaddr1.s_addr != 0) {\r |
185 | zptr->z_ns[k].nsaddr1.s_addr =\r |
186 | tmpzptr->z_ns[i].nsaddr1.s_addr;\r |
187 | done = 1;\r |
188 | break;\r |
189 | }\r |
190 | }\r |
191 | if (done)\r |
192 | break;\r |
193 | n = res_mkquery(QUERY, dname, qclass, qtype, NULL,\r |
194 | 0, NULL, buf, sizeof buf);\r |
195 | if (n <= 0) {\r |
196 | fprintf(stderr, "res_update: mkquery failed\n");\r |
197 | return (n);\r |
198 | }\r |
199 | n = res_send(buf, n, answer, sizeof answer);\r |
200 | if (n < 0) {\r |
201 | fprintf(stderr, "res_update: send error for %s\n",\r |
202 | rrecp->r_dname);\r |
203 | return (n);\r |
204 | }\r |
205 | if (n < HFIXEDSZ)\r |
206 | return (-1);\r |
207 | ancount = ntohs(hp->ancount);\r |
208 | nscount = ntohs(hp->nscount);\r |
209 | arcount = ntohs(hp->arcount);\r |
210 | rcode = hp->rcode;\r |
211 | cp = answer + HFIXEDSZ;\r |
212 | eom = answer + n;\r |
213 | /* skip the question section */\r |
214 | n = dn_skipname(cp, eom);\r |
215 | if (n < 0 || cp + n + 2 * INT16SZ > eom)\r |
216 | return (-1);\r |
217 | cp += n + 2 * INT16SZ;\r |
218 | \r |
219 | if (qtype == T_SOA) {\r |
220 | if (ancount == 0 && nscount == 0 && arcount == 0) {\r |
221 | /*\r |
222 | * if (rcode == NOERROR) then the dname exists but\r |
223 | * has no soa record associated with it.\r |
224 | * if (rcode == NXDOMAIN) then the dname does not\r |
225 | * exist and the server is replying out of NCACHE.\r |
226 | * in either case, proceed with the next try\r |
227 | */\r |
228 | dname = strchr(dname, '.');\r |
229 | if (dname != NULL)\r |
230 | dname++;\r |
231 | continue;\r |
232 | } else if ((rcode == NOERROR || rcode == NXDOMAIN) &&\r |
233 | ancount == 0 &&\r |
234 | nscount == 1 && arcount == 0) {\r |
235 | /*\r |
236 | * name/data does not exist, soa record supplied in the\r |
237 | * authority section\r |
238 | */\r |
239 | /* authority section must contain the soa record */\r |
240 | if ((n = dn_expand(answer, eom, cp, zname,\r |
241 | sizeof zname)) < 0)\r |
242 | return (n);\r |
243 | cp += n;\r |
244 | if (cp + 2 * INT16SZ > eom)\r |
245 | return (-1);\r |
246 | GETSHORT(type, cp);\r |
247 | GETSHORT(class, cp);\r |
248 | if (type != T_SOA || class != qclass) {\r |
249 | fprintf(stderr, "unknown answer\n");\r |
250 | return (-1);\r |
251 | }\r |
252 | myzone = 0;\r |
253 | svdname = dname;\r |
254 | while (dname)\r |
255 | if (strcasecmp(dname, zname) == 0) {\r |
256 | myzone = 1;\r |
257 | break;\r |
258 | } else if ((dname = strchr(dname, '.')) != NULL)\r |
259 | dname++;\r |
260 | if (!myzone) {\r |
261 | dname = strchr(svdname, '.');\r |
262 | if (dname != NULL)\r |
263 | dname++;\r |
264 | continue;\r |
265 | }\r |
266 | nscount = 0;\r |
267 | /* fallthrough */\r |
268 | } else if (rcode == NOERROR && ancount == 1) {\r |
269 | /*\r |
270 | * found the zone name\r |
271 | * new servers will supply NS records for the zone\r |
272 | * in authority section and A records for those\r |
273 | * nameservers in the additional section\r |
274 | * older servers have to be explicitly queried for\r |
275 | * NS records for the zone\r |
276 | */\r |
277 | /* answer section must contain the soa record */\r |
278 | if ((n = dn_expand(answer, eom, cp, zname,\r |
279 | sizeof zname)) < 0)\r |
280 | return (n);\r |
281 | else\r |
282 | cp += n;\r |
283 | if (cp + 2 * INT16SZ > eom)\r |
284 | return (-1);\r |
285 | GETSHORT(type, cp);\r |
286 | GETSHORT(class, cp);\r |
287 | if (type == T_CNAME) {\r |
288 | dname = strchr(dname, '.');\r |
289 | if (dname != NULL)\r |
290 | dname++;\r |
291 | continue;\r |
292 | }\r |
293 | if (strcasecmp(dname, zname) != 0 ||\r |
294 | type != T_SOA ||\r |
295 | class != rrecp->r_class) {\r |
296 | fprintf(stderr, "unknown answer\n");\r |
297 | return (-1);\r |
298 | }\r |
299 | /* FALLTHROUGH */\r |
300 | } else {\r |
301 | fprintf(stderr,\r |
302 | "unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n",\r |
303 | ancount, nscount, arcount, hp->rcode);\r |
304 | return (-1);\r |
305 | }\r |
306 | if (cp + INT32SZ + INT16SZ > eom)\r |
307 | return (-1);\r |
308 | /* continue processing the soa record */\r |
309 | GETLONG(ttl, cp);\r |
310 | GETSHORT(dlen, cp);\r |
311 | if (cp + dlen > eom)\r |
312 | return (-1);\r |
313 | newgroup = 1;\r |
314 | zptr = zgrp_start;\r |
315 | prevzptr = NULL;\r |
316 | while (zptr) {\r |
317 | if (strcasecmp(zname, zptr->z_origin) == 0 &&\r |
318 | type == T_SOA && class == qclass) {\r |
319 | newgroup = 0;\r |
320 | break;\r |
321 | }\r |
322 | prevzptr = zptr;\r |
323 | zptr = zptr->z_next;\r |
324 | }\r |
325 | if (!newgroup) {\r |
326 | for (tmprrecp = zptr->z_rr;\r |
327 | tmprrecp->r_grpnext;\r |
328 | tmprrecp = tmprrecp->r_grpnext)\r |
329 | ;\r |
330 | tmprrecp->r_grpnext = rrecp;\r |
331 | rrecp->r_grpnext = NULL;\r |
332 | done = 1;\r |
333 | cp += dlen;\r |
334 | break;\r |
335 | } else {\r |
336 | if ((n = dn_expand(answer, eom, cp, primary,\r |
337 | sizeof primary)) < 0)\r |
338 | return (n);\r |
339 | cp += n;\r |
340 | /*\r |
341 | * We don't have to bounds check here because the\r |
342 | * next use of 'cp' is in dn_expand().\r |
343 | */\r |
344 | cp1 = (char *)soardata;\r |
345 | strcpy(cp1, primary);\r |
346 | cp1 += strlen(cp1) + 1;\r |
347 | if ((n = dn_expand(answer, eom, cp, mailaddr,\r |
348 | sizeof mailaddr)) < 0)\r |
349 | return (n);\r |
350 | cp += n;\r |
351 | strcpy(cp1, mailaddr);\r |
352 | cp1 += strlen(cp1) + 1;\r |
353 | if (cp + 5*INT32SZ > eom)\r |
354 | return (-1);\r |
355 | memcpy(cp1, cp, 5*INT32SZ);\r |
356 | cp += 5*INT32SZ;\r |
357 | cp1 += 5*INT32SZ;\r |
358 | rdatasize = (int)((u_char *)cp1 - soardata);\r |
359 | zptr = calloc(1, sizeof(struct zonegrp));\r |
360 | if (zptr == NULL)\r |
361 | return (-1);\r |
362 | if (zgrp_start == NULL)\r |
363 | zgrp_start = zptr;\r |
364 | else\r |
365 | prevzptr->z_next = zptr;\r |
366 | zptr->z_rr = rrecp;\r |
367 | rrecp->r_grpnext = NULL;\r |
368 | strcpy(zptr->z_origin, zname);\r |
369 | zptr->z_class = class;\r |
370 | memcpy(zptr->z_soardata, soardata, rdatasize);\r |
371 | /* fallthrough to process NS and A records */\r |
372 | }\r |
373 | } else if (qtype == T_NS) {\r |
374 | if (rcode == NOERROR && ancount > 0) {\r |
375 | strcpy(zname, dname);\r |
376 | for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {\r |
377 | if (strcasecmp(zname, zptr->z_origin) == 0)\r |
378 | break;\r |
379 | }\r |
380 | if (zptr == NULL)\r |
381 | /* should not happen */\r |
382 | return (-1);\r |
383 | if (nscount > 0) {\r |
384 | /*\r |
385 | * answer and authority sections contain\r |
386 | * the same information, skip answer section\r |
387 | */\r |
388 | for (j = 0; j < ancount; j++) {\r |
389 | n = dn_skipname(cp, eom);\r |
390 | if (n < 0)\r |
391 | return (-1);\r |
392 | n += 2*INT16SZ + INT32SZ;\r |
393 | if (cp + n + INT16SZ > eom)\r |
394 | return (-1);\r |
395 | cp += n;\r |
396 | GETSHORT(dlen, cp);\r |
397 | cp += dlen;\r |
398 | }\r |
399 | } else\r |
400 | nscount = ancount;\r |
401 | /* fallthrough to process NS and A records */\r |
402 | } else {\r |
403 | fprintf(stderr, "cannot determine nameservers for %s:\\r |
404 | ans=%d, auth=%d, add=%d, rcode=%d\n",\r |
405 | dname, ancount, nscount, arcount, hp->rcode);\r |
406 | return (-1);\r |
407 | }\r |
408 | } else if (qtype == T_A) {\r |
409 | if (rcode == NOERROR && ancount > 0) {\r |
410 | arcount = ancount;\r |
411 | ancount = nscount = 0;\r |
412 | /* fallthrough to process A records */\r |
413 | } else {\r |
414 | fprintf(stderr, "cannot determine address for %s:\\r |
415 | ans=%d, auth=%d, add=%d, rcode=%d\n",\r |
416 | dname, ancount, nscount, arcount, hp->rcode);\r |
417 | return (-1);\r |
418 | }\r |
419 | }\r |
420 | /* process NS records for the zone */\r |
421 | j = 0;\r |
422 | for (i = 0; i < nscount; i++) {\r |
423 | if ((n = dn_expand(answer, eom, cp, name,\r |
424 | sizeof name)) < 0)\r |
425 | return (n);\r |
426 | cp += n;\r |
427 | if (cp + 3 * INT16SZ + INT32SZ > eom)\r |
428 | return (-1);\r |
429 | GETSHORT(type, cp);\r |
430 | GETSHORT(class, cp);\r |
431 | GETLONG(ttl, cp);\r |
432 | GETSHORT(dlen, cp);\r |
433 | if (cp + dlen > eom)\r |
434 | return (-1);\r |
435 | if (strcasecmp(name, zname) == 0 &&\r |
436 | type == T_NS && class == qclass) {\r |
437 | if ((n = dn_expand(answer, eom, cp,\r |
438 | name, sizeof name)) < 0)\r |
439 | return (n);\r |
440 | target = zptr->z_ns[j++].nsname;\r |
441 | strcpy(target, name);\r |
442 | }\r |
443 | cp += dlen;\r |
444 | }\r |
445 | if (zptr->z_nscount == 0)\r |
446 | zptr->z_nscount = j;\r |
447 | /* get addresses for the nameservers */\r |
448 | for (i = 0; i < arcount; i++) {\r |
449 | if ((n = dn_expand(answer, eom, cp, name,\r |
450 | sizeof name)) < 0)\r |
451 | return (n);\r |
452 | cp += n;\r |
453 | if (cp + 3 * INT16SZ + INT32SZ > eom)\r |
454 | return (-1);\r |
455 | GETSHORT(type, cp);\r |
456 | GETSHORT(class, cp);\r |
457 | GETLONG(ttl, cp);\r |
458 | GETSHORT(dlen, cp);\r |
459 | if (cp + dlen > eom)\r |
460 | return (-1);\r |
461 | if (type == T_A && dlen == INT32SZ && class == qclass) {\r |
462 | for (j = 0; j < zptr->z_nscount; j++)\r |
463 | if (strcasecmp(name, zptr->z_ns[j].nsname) == 0) {\r |
464 | memcpy(&zptr->z_ns[j].nsaddr1.s_addr, cp,\r |
465 | INT32SZ);\r |
466 | break;\r |
467 | }\r |
468 | }\r |
469 | cp += dlen;\r |
470 | }\r |
471 | if (zptr->z_nscount == 0) {\r |
472 | dname = zname;\r |
473 | qtype = T_NS;\r |
474 | continue;\r |
475 | }\r |
476 | done = 1;\r |
477 | for (k = 0; k < zptr->z_nscount; k++)\r |
478 | if (zptr->z_ns[k].nsaddr1.s_addr == 0) {\r |
479 | done = 0;\r |
480 | dname = zptr->z_ns[k].nsname;\r |
481 | qtype = T_A;\r |
482 | }\r |
483 | \r |
484 | } /* while */\r |
485 | }\r |
486 | \r |
487 | _res.options |= RES_DEBUG;\r |
488 | for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {\r |
489 | \r |
490 | /* append zone section */\r |
491 | rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,\r |
492 | zptr->z_class, ns_t_soa, 0);\r |
493 | if (rrecp == NULL) {\r |
494 | fprintf(stderr, "saverrec error\n");\r |
495 | fflush(stderr);\r |
496 | return (-1);\r |
497 | }\r |
498 | rrecp->r_grpnext = zptr->z_rr;\r |
499 | zptr->z_rr = rrecp;\r |
500 | \r |
501 | n = res_mkupdate(zptr->z_rr, packet, sizeof packet);\r |
502 | if (n < 0) {\r |
503 | fprintf(stderr, "res_mkupdate error\n");\r |
504 | fflush(stderr);\r |
505 | return (-1);\r |
506 | } else\r |
507 | fprintf(stdout, "res_mkupdate: packet size = %d\n", n);\r |
508 | \r |
509 | /*\r |
510 | * Override the list of NS records from res_init() with\r |
511 | * the authoritative nameservers for the zone being updated.\r |
512 | * Sort primary to be the first in the list of nameservers.\r |
513 | */\r |
514 | for (i = 0; i < zptr->z_nscount; i++) {\r |
515 | if (strcasecmp(zptr->z_ns[i].nsname,\r |
516 | zptr->z_soardata) == 0) {\r |
517 | struct in_addr tmpaddr;\r |
518 | \r |
519 | if (i != 0) {\r |
520 | strcpy(zptr->z_ns[i].nsname,\r |
521 | zptr->z_ns[0].nsname);\r |
522 | strcpy(zptr->z_ns[0].nsname,\r |
523 | zptr->z_soardata);\r |
524 | tmpaddr = zptr->z_ns[i].nsaddr1;\r |
525 | zptr->z_ns[i].nsaddr1 =\r |
526 | zptr->z_ns[0].nsaddr1;\r |
527 | zptr->z_ns[0].nsaddr1 = tmpaddr;\r |
528 | }\r |
529 | break;\r |
530 | }\r |
531 | }\r |
532 | for (i = 0; i < MAXNS; i++) {\r |
533 | _res.nsaddr_list[i].sin_addr = zptr->z_ns[i].nsaddr1;\r |
534 | _res.nsaddr_list[i].sin_family = AF_INET;\r |
535 | _res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);\r |
536 | }\r |
537 | _res.nscount = (zptr->z_nscount < MAXNS) ?\r |
538 | zptr->z_nscount : MAXNS;\r |
539 | n = res_send(packet, n, answer, sizeof(answer));\r |
540 | if (n < 0) {\r |
541 | fprintf(stderr, "res_send: send error, n=%d\n", n);\r |
542 | break;\r |
543 | } else\r |
544 | numzones++;\r |
545 | }\r |
546 | \r |
547 | /* free malloc'ed memory */\r |
548 | while(zgrp_start) {\r |
549 | zptr = zgrp_start;\r |
550 | zgrp_start = zgrp_start->z_next;\r |
551 | res_freeupdrec(zptr->z_rr); /* Zone section we allocated. */\r |
552 | free((char *)zptr);\r |
553 | }\r |
554 | \r |
555 | return (numzones);\r |
556 | }\r |