]> git.saurik.com Git - apple/libresolv.git/blob - res_mkupdate.c
libresolv-67.40.1.tar.gz
[apple/libresolv.git] / res_mkupdate.c
1 /*
2 * Copyright (c) 1996-1999 by Internet Software Consortium.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15 * SOFTWARE.
16 */
17
18 /*
19 * Based on the Dynamic DNS reference implementation by Viraj Bais
20 * <viraj_bais@ccm.fm.intel.com>
21 */
22
23 #ifndef __APPLE__
24 #if !defined(lint) && !defined(SABER)
25 static const char rcsid[] = "$Id: res_mkupdate.c,v 1.1 2006/03/01 19:01:38 majka Exp $";
26 #endif /* not lint */
27 #endif
28
29 #ifndef __APPLE__
30 #include "port_before.h"
31 #endif
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35
36 #include <netinet/in.h>
37 #include <arpa/nameser.h>
38 #include <arpa/inet.h>
39
40 #include <errno.h>
41 #include <limits.h>
42 #include <netdb.h>
43 #include <resolv.h>
44 #include <res_update.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 #include <ctype.h>
50
51 #include "res_private.h"
52
53 #ifndef __APPLE__
54 #include "port_after.h"
55 #endif
56
57 /* Options. Leave them on. */
58 #define DEBUG
59 #define MAXPORT 1024
60
61 static int getnum_str(u_char **, u_char *);
62 static int gethexnum_str(u_char **, u_char *);
63 static int getword_str(char *, int, u_char **, u_char *);
64 static int getstr_str(char *, int, u_char **, u_char *);
65
66 #define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
67
68 /* Forward. */
69
70 #ifdef __APPLE__
71 static
72 #endif
73 int res_protocolnumber(const char *);
74 #ifdef __APPLE__
75 static
76 #endif
77 int res_servicenumber(const char *);
78
79 /*
80 * Form update packets.
81 * Returns the size of the resulting packet if no error
82 * On error,
83 * returns -1 if error in reading a word/number in rdata
84 * portion for update packets
85 * -2 if length of buffer passed is insufficient
86 * -3 if zone section is not the first section in
87 * the linked list, or section order has a problem
88 * -4 on a number overflow
89 * -5 unknown operation or no records
90 */
91 int
92 res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) {
93 ns_updrec *rrecp_start = rrecp_in;
94 HEADER *hp;
95 u_char *cp, *sp1, *sp2, *startp, *endp;
96 int n, i, soanum, multiline;
97 ns_updrec *rrecp;
98 struct in_addr ina;
99 struct in6_addr in6a;
100 char buf2[NS_MAXDNAME];
101 u_char buf3[NS_MAXDNAME];
102 int section, numrrs = 0, counts[ns_s_max];
103 u_int16_t rtype, rclass;
104 u_int32_t n1, rttl;
105 u_char *dnptrs[20], **dpp, **lastdnptr;
106 int siglen, keylen, certlen;
107
108 /*
109 * Initialize header fields.
110 */
111 if ((buf == NULL) || (buflen < NS_HFIXEDSZ))
112 return (-1);
113 memset(buf, 0, NS_HFIXEDSZ);
114 hp = (HEADER *) buf;
115 #ifdef __APPLE__
116 hp->id = res_randomid();
117 #else
118 hp->id = htons(++statp->id);
119 #endif
120 hp->opcode = ns_o_update;
121 hp->rcode = ns_r_noerror;
122 sp1 = buf + 2*NS_INT16SZ; /* save pointer to zocount */
123 cp = buf + NS_HFIXEDSZ;
124 buflen -= NS_HFIXEDSZ;
125 dpp = dnptrs;
126 *dpp++ = buf;
127 *dpp++ = NULL;
128 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
129
130 if (rrecp_start == NULL)
131 return (-5);
132 else if (rrecp_start->r_section != ns_s_zn)
133 return (-3);
134
135 memset(counts, 0, sizeof counts);
136 for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) {
137 numrrs++;
138 section = rrecp->r_section;
139 if (section < 0 || section >= ns_s_max)
140 return (-1);
141 counts[section]++;
142 for (i = section + 1; i < ns_s_max; i++)
143 if (counts[i])
144 return (-3);
145 rtype = rrecp->r_type;
146 rclass = rrecp->r_class;
147 rttl = rrecp->r_ttl;
148 /* overload class and type */
149 if (section == ns_s_pr) {
150 rttl = 0;
151 switch (rrecp->r_opcode) {
152 case ns_r_yxdomain:
153 rclass = ns_c_any;
154 rtype = ns_t_any;
155 rrecp->r_size = 0;
156 break;
157 case ns_r_nxdomain:
158 rclass = ns_c_none;
159 rtype = ns_t_any;
160 rrecp->r_size = 0;
161 break;
162 case ns_r_nxrrset:
163 rclass = ns_c_none;
164 rrecp->r_size = 0;
165 break;
166 case ns_r_yxrrset:
167 if (rrecp->r_size == 0)
168 rclass = ns_c_any;
169 break;
170 default:
171 fprintf(stderr,
172 "res_mkupdate: incorrect opcode: %d\n",
173 rrecp->r_opcode);
174 fflush(stderr);
175 return (-1);
176 }
177 } else if (section == ns_s_ud) {
178 switch (rrecp->r_opcode) {
179 case ns_uop_delete:
180 rclass = rrecp->r_size == 0 ? ns_c_any : ns_c_none;
181 break;
182 case ns_uop_add:
183 break;
184 default:
185 fprintf(stderr,
186 "res_mkupdate: incorrect opcode: %d\n",
187 rrecp->r_opcode);
188 fflush(stderr);
189 return (-1);
190 }
191 }
192
193 /*
194 * XXX appending default domain to owner name is omitted,
195 * fqdn must be provided
196 */
197 if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
198 lastdnptr)) < 0)
199 return (-1);
200 cp += n;
201 ShrinkBuffer(n + 2*NS_INT16SZ);
202 NS_PUT16(rtype, cp);
203 NS_PUT16(rclass, cp);
204 if (section == ns_s_zn) {
205 if (numrrs != 1 || rrecp->r_type != ns_t_soa)
206 return (-3);
207 continue;
208 }
209 ShrinkBuffer(NS_INT32SZ + NS_INT16SZ);
210 NS_PUT32(rttl, cp);
211 sp2 = cp; /* save pointer to length byte */
212 cp += NS_INT16SZ;
213 if (rrecp->r_size == 0) {
214 if (section == ns_s_ud && rclass != ns_c_any)
215 return (-1);
216 else {
217 NS_PUT16(0, sp2);
218 continue;
219 }
220 }
221 startp = rrecp->r_data;
222 endp = startp + rrecp->r_size - 1;
223 /* XXX this should be done centrally. */
224 switch (rrecp->r_type) {
225 case ns_t_a:
226 if (!getword_str(buf2, sizeof buf2, &startp, endp))
227 return (-1);
228 if (!inet_aton(buf2, &ina))
229 return (-1);
230 n1 = ntohl(ina.s_addr);
231 ShrinkBuffer(NS_INT32SZ);
232 NS_PUT32(n1, cp);
233 break;
234 case ns_t_cname:
235 case ns_t_mb:
236 case ns_t_mg:
237 case ns_t_mr:
238 case ns_t_ns:
239 case ns_t_ptr:
240 if (!getword_str(buf2, sizeof buf2, &startp, endp))
241 return (-1);
242 n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
243 if (n < 0)
244 return (-1);
245 cp += n;
246 ShrinkBuffer(n);
247 break;
248 case ns_t_minfo:
249 case ns_t_soa:
250 case ns_t_rp:
251 for (i = 0; i < 2; i++) {
252 if (!getword_str(buf2, sizeof buf2, &startp,
253 endp))
254 return (-1);
255 n = dn_comp(buf2, cp, buflen,
256 dnptrs, lastdnptr);
257 if (n < 0)
258 return (-1);
259 cp += n;
260 ShrinkBuffer(n);
261 }
262 if (rrecp->r_type == ns_t_soa) {
263 ShrinkBuffer(5 * NS_INT32SZ);
264 while (isspace(*startp) || !*startp)
265 startp++;
266 if (*startp == '(') {
267 multiline = 1;
268 startp++;
269 } else
270 multiline = 0;
271 /* serial, refresh, retry, expire, minimum */
272 for (i = 0; i < 5; i++) {
273 soanum = getnum_str(&startp, endp);
274 if (soanum < 0)
275 return (-1);
276 NS_PUT32(soanum, cp);
277 }
278 if (multiline) {
279 while (isspace(*startp) || !*startp)
280 startp++;
281 if (*startp != ')')
282 return (-1);
283 }
284 }
285 break;
286 case ns_t_mx:
287 case ns_t_afsdb:
288 case ns_t_rt:
289 n = getnum_str(&startp, endp);
290 if (n < 0)
291 return (-1);
292 ShrinkBuffer(NS_INT16SZ);
293 NS_PUT16(n, cp);
294 if (!getword_str(buf2, sizeof buf2, &startp, endp))
295 return (-1);
296 n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
297 if (n < 0)
298 return (-1);
299 cp += n;
300 ShrinkBuffer(n);
301 break;
302 case ns_t_srv:
303 n = getnum_str(&startp, endp);
304 if (n < 0)
305 return (-1);
306 ShrinkBuffer(NS_INT16SZ);
307 NS_PUT16(n, cp);
308
309 n = getnum_str(&startp, endp);
310 if (n < 0)
311 return (-1);
312 ShrinkBuffer(NS_INT16SZ);
313 NS_PUT16(n, cp);
314
315 n = getnum_str(&startp, endp);
316 if (n < 0)
317 return (-1);
318 ShrinkBuffer(NS_INT16SZ);
319 NS_PUT16(n, cp);
320
321 if (!getword_str(buf2, sizeof buf2, &startp, endp))
322 return (-1);
323 n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
324 if (n < 0)
325 return (-1);
326 cp += n;
327 ShrinkBuffer(n);
328 break;
329 case ns_t_px:
330 n = getnum_str(&startp, endp);
331 if (n < 0)
332 return (-1);
333 NS_PUT16(n, cp);
334 ShrinkBuffer(NS_INT16SZ);
335 for (i = 0; i < 2; i++) {
336 if (!getword_str(buf2, sizeof buf2, &startp,
337 endp))
338 return (-1);
339 n = dn_comp(buf2, cp, buflen, dnptrs,
340 lastdnptr);
341 if (n < 0)
342 return (-1);
343 cp += n;
344 ShrinkBuffer(n);
345 }
346 break;
347 case ns_t_wks: {
348 char bm[MAXPORT/8];
349 unsigned int maxbm = 0;
350
351 if (!getword_str(buf2, sizeof buf2, &startp, endp))
352 return (-1);
353 if (!inet_aton(buf2, &ina))
354 return (-1);
355 n1 = ntohl(ina.s_addr);
356 ShrinkBuffer(NS_INT32SZ);
357 NS_PUT32(n1, cp);
358
359 if (!getword_str(buf2, sizeof buf2, &startp, endp))
360 return (-1);
361 if ((i = res_protocolnumber(buf2)) < 0)
362 return (-1);
363 ShrinkBuffer(1);
364 *cp++ = i & 0xff;
365
366 for (i = 0; i < MAXPORT/8 ; i++)
367 bm[i] = 0;
368
369 while (getword_str(buf2, sizeof buf2, &startp, endp)) {
370 if ((n1 = res_servicenumber(buf2)) <= 0)
371 return (-1);
372
373 if (n1 < MAXPORT) {
374 bm[n1/8] |= (0x80>>(n1%8));
375 if (n1 > maxbm)
376 maxbm = n1;
377 } else
378 return (-1);
379 }
380 maxbm = maxbm/8 + 1;
381 ShrinkBuffer(maxbm);
382 memcpy(cp, bm, maxbm);
383 cp += maxbm;
384 break;
385 }
386 case ns_t_hinfo:
387 for (i = 0; i < 2; i++) {
388 if ((n = getstr_str(buf2, sizeof buf2,
389 &startp, endp)) < 0)
390 return (-1);
391 if (n > 255)
392 return (-1);
393 ShrinkBuffer(n+1);
394 *cp++ = n;
395 memcpy(cp, buf2, n);
396 cp += n;
397 }
398 break;
399 case ns_t_txt:
400 while (1) {
401 if ((n = getstr_str(buf2, sizeof buf2,
402 &startp, endp)) < 0) {
403 if (cp != (sp2 + NS_INT16SZ))
404 break;
405 return (-1);
406 }
407 if (n > 255)
408 return (-1);
409 ShrinkBuffer(n+1);
410 *cp++ = n;
411 memcpy(cp, buf2, n);
412 cp += n;
413 }
414 break;
415 case ns_t_x25:
416 /* RFC 1183 */
417 if ((n = getstr_str(buf2, sizeof buf2, &startp,
418 endp)) < 0)
419 return (-1);
420 if (n > 255)
421 return (-1);
422 ShrinkBuffer(n+1);
423 *cp++ = n;
424 memcpy(cp, buf2, n);
425 cp += n;
426 break;
427 case ns_t_isdn:
428 /* RFC 1183 */
429 if ((n = getstr_str(buf2, sizeof buf2, &startp,
430 endp)) < 0)
431 return (-1);
432 if ((n > 255) || (n == 0))
433 return (-1);
434 ShrinkBuffer(n+1);
435 *cp++ = n;
436 memcpy(cp, buf2, n);
437 cp += n;
438 if ((n = getstr_str(buf2, sizeof buf2, &startp,
439 endp)) < 0)
440 n = 0;
441 if (n > 255)
442 return (-1);
443 ShrinkBuffer(n+1);
444 *cp++ = n;
445 memcpy(cp, buf2, n);
446 cp += n;
447 break;
448 case ns_t_nsap:
449 if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) {
450 ShrinkBuffer(n);
451 memcpy(cp, buf2, n);
452 cp += n;
453 } else {
454 return (-1);
455 }
456 break;
457 case ns_t_loc:
458 if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) {
459 ShrinkBuffer(n);
460 memcpy(cp, buf2, n);
461 cp += n;
462 } else
463 return (-1);
464 break;
465 case ns_t_sig:
466 {
467 int sig_type, success, dateerror;
468 u_int32_t exptime, timesigned;
469
470 /* type */
471 if ((n = getword_str(buf2, sizeof buf2,
472 &startp, endp)) < 0)
473 return (-1);
474 sig_type = sym_ston(__p_type_syms, buf2, &success);
475 if (!success || sig_type == ns_t_any)
476 return (-1);
477 ShrinkBuffer(NS_INT16SZ);
478 NS_PUT16(sig_type, cp);
479 /* alg */
480 n = getnum_str(&startp, endp);
481 if (n < 0)
482 return (-1);
483 ShrinkBuffer(1);
484 *cp++ = n;
485 /* labels */
486 n = getnum_str(&startp, endp);
487 if (n <= 0 || n > 255)
488 return (-1);
489 ShrinkBuffer(1);
490 *cp++ = n;
491 /* ottl & expire */
492 if (!getword_str(buf2, sizeof buf2, &startp, endp))
493 return (-1);
494 exptime = ns_datetosecs(buf2, &dateerror);
495 if (!dateerror) {
496 ShrinkBuffer(NS_INT32SZ);
497 NS_PUT32(rttl, cp);
498 }
499 else {
500 char *ulendp;
501 u_int32_t ottl;
502
503 ottl = strtoul(buf2, &ulendp, 10);
504 if (ulendp != NULL && *ulendp != '\0')
505 return (-1);
506 ShrinkBuffer(NS_INT32SZ);
507 NS_PUT32(ottl, cp);
508 if (!getword_str(buf2, sizeof buf2, &startp,
509 endp))
510 return (-1);
511 exptime = ns_datetosecs(buf2, &dateerror);
512 if (dateerror)
513 return (-1);
514 }
515 /* expire */
516 ShrinkBuffer(NS_INT32SZ);
517 NS_PUT32(exptime, cp);
518 /* timesigned */
519 if (!getword_str(buf2, sizeof buf2, &startp, endp))
520 return (-1);
521 timesigned = ns_datetosecs(buf2, &dateerror);
522 if (!dateerror) {
523 ShrinkBuffer(NS_INT32SZ);
524 NS_PUT32(timesigned, cp);
525 }
526 else
527 return (-1);
528 /* footprint */
529 n = getnum_str(&startp, endp);
530 if (n < 0)
531 return (-1);
532 ShrinkBuffer(NS_INT16SZ);
533 NS_PUT16(n, cp);
534 /* signer name */
535 if (!getword_str(buf2, sizeof buf2, &startp, endp))
536 return (-1);
537 n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
538 if (n < 0)
539 return (-1);
540 cp += n;
541 ShrinkBuffer(n);
542 /* sig */
543 if ((n = getword_str(buf2, sizeof buf2,
544 &startp, endp)) < 0)
545 return (-1);
546 siglen = b64_pton(buf2, buf3, sizeof(buf3));
547 if (siglen < 0)
548 return (-1);
549 ShrinkBuffer(siglen);
550 memcpy(cp, buf3, siglen);
551 cp += siglen;
552 break;
553 }
554 case ns_t_key:
555 /* flags */
556 n = gethexnum_str(&startp, endp);
557 if (n < 0)
558 return (-1);
559 ShrinkBuffer(NS_INT16SZ);
560 NS_PUT16(n, cp);
561 /* proto */
562 n = getnum_str(&startp, endp);
563 if (n < 0)
564 return (-1);
565 ShrinkBuffer(1);
566 *cp++ = n;
567 /* alg */
568 n = getnum_str(&startp, endp);
569 if (n < 0)
570 return (-1);
571 ShrinkBuffer(1);
572 *cp++ = n;
573 /* key */
574 if ((n = getword_str(buf2, sizeof buf2,
575 &startp, endp)) < 0)
576 return (-1);
577 keylen = b64_pton(buf2, buf3, sizeof(buf3));
578 if (keylen < 0)
579 return (-1);
580 ShrinkBuffer(keylen);
581 memcpy(cp, buf3, keylen);
582 cp += keylen;
583 break;
584 case ns_t_nxt:
585 {
586 int success, nxt_type;
587 u_char data[32];
588 int maxtype;
589
590 /* next name */
591 if (!getword_str(buf2, sizeof buf2, &startp, endp))
592 return (-1);
593 n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
594 if (n < 0)
595 return (-1);
596 cp += n;
597 ShrinkBuffer(n);
598 maxtype = 0;
599 memset(data, 0, sizeof data);
600 while (1) {
601 if (!getword_str(buf2, sizeof buf2, &startp,
602 endp))
603 break;
604 nxt_type = sym_ston(__p_type_syms, buf2,
605 &success);
606 if (!success || !ns_t_rr_p(nxt_type))
607 return (-1);
608 NS_NXT_BIT_SET(nxt_type, data);
609 if (nxt_type > maxtype)
610 maxtype = nxt_type;
611 }
612 n = maxtype/NS_NXT_BITS+1;
613 ShrinkBuffer(n);
614 memcpy(cp, data, n);
615 cp += n;
616 break;
617 }
618 case ns_t_cert:
619 /* type */
620 n = getnum_str(&startp, endp);
621 if (n < 0)
622 return (-1);
623 ShrinkBuffer(NS_INT16SZ);
624 NS_PUT16(n, cp);
625 /* key tag */
626 n = getnum_str(&startp, endp);
627 if (n < 0)
628 return (-1);
629 ShrinkBuffer(NS_INT16SZ);
630 NS_PUT16(n, cp);
631 /* alg */
632 n = getnum_str(&startp, endp);
633 if (n < 0)
634 return (-1);
635 ShrinkBuffer(1);
636 *cp++ = n;
637 /* cert */
638 if ((n = getword_str(buf2, sizeof buf2,
639 &startp, endp)) < 0)
640 return (-1);
641 certlen = b64_pton(buf2, buf3, sizeof(buf3));
642 if (certlen < 0)
643 return (-1);
644 ShrinkBuffer(certlen);
645 memcpy(cp, buf3, certlen);
646 cp += certlen;
647 break;
648 case ns_t_aaaa:
649 if (!getword_str(buf2, sizeof buf2, &startp, endp))
650 return (-1);
651 if (inet_pton(AF_INET6, buf2, &in6a) <= 0)
652 return (-1);
653 ShrinkBuffer(NS_IN6ADDRSZ);
654 memcpy(cp, &in6a, NS_IN6ADDRSZ);
655 cp += NS_IN6ADDRSZ;
656 break;
657 default:
658 return (-1);
659 } /*switch*/
660 n = (u_int16_t)((cp - sp2) - NS_INT16SZ);
661 NS_PUT16(n, sp2);
662 } /*for*/
663
664 hp->qdcount = htons(counts[0]);
665 hp->ancount = htons(counts[1]);
666 hp->nscount = htons(counts[2]);
667 hp->arcount = htons(counts[3]);
668 return (cp - buf);
669 }
670
671 /*
672 * Get a whitespace delimited word from a string (not file)
673 * into buf. modify the start pointer to point after the
674 * word in the string.
675 */
676 static int
677 getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
678 char *cp;
679 int c;
680
681 for (cp = buf; *startpp <= endp; ) {
682 c = **startpp;
683 if (isspace(c) || c == '\0') {
684 if (cp != buf) /* trailing whitespace */
685 break;
686 else { /* leading whitespace */
687 (*startpp)++;
688 continue;
689 }
690 }
691 (*startpp)++;
692 if (cp >= buf+size-1)
693 break;
694 *cp++ = (u_char)c;
695 }
696 *cp = '\0';
697 return (cp != buf);
698 }
699
700 /*
701 * get a white spae delimited string from memory. Process quoted strings
702 * and \DDD escapes. Return length or -1 on error. Returned string may
703 * contain nulls.
704 */
705 static char digits[] = "0123456789";
706 static int
707 getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
708 char *cp;
709 int c, c1 = 0;
710 int inquote = 0;
711 int seen_quote = 0;
712 int escape = 0;
713 int dig = 0;
714
715 for (cp = buf; *startpp <= endp; ) {
716 if ((c = **startpp) == '\0')
717 break;
718 /* leading white space */
719 if ((cp == buf) && !seen_quote && isspace(c)) {
720 (*startpp)++;
721 continue;
722 }
723
724 switch (c) {
725 case '\\':
726 if (!escape) {
727 escape = 1;
728 dig = 0;
729 c1 = 0;
730 (*startpp)++;
731 continue;
732 }
733 goto do_escape;
734 case '"':
735 if (!escape) {
736 inquote = !inquote;
737 seen_quote = 1;
738 (*startpp)++;
739 continue;
740 }
741 /* fall through */
742 default:
743 do_escape:
744 if (escape) {
745 switch (c) {
746 case '0':
747 case '1':
748 case '2':
749 case '3':
750 case '4':
751 case '5':
752 case '6':
753 case '7':
754 case '8':
755 case '9':
756 c1 = c1 * 10 +
757 (strchr(digits, c) - digits);
758
759 if (++dig == 3) {
760 c = c1 &0xff;
761 break;
762 }
763 (*startpp)++;
764 continue;
765 }
766 escape = 0;
767 } else if (!inquote && isspace(c))
768 goto done;
769 if (cp >= buf+size-1)
770 goto done;
771 *cp++ = (u_char)c;
772 (*startpp)++;
773 }
774 }
775 done:
776 *cp = '\0';
777 return ((cp == buf)? (seen_quote? 0: -1): (cp - buf));
778 }
779 /*
780 * Get a whitespace delimited base 16 number from a string (not file) into buf
781 * update the start pointer to point after the number in the string.
782 */
783 static int
784 gethexnum_str(u_char **startpp, u_char *endp) {
785 int c, n;
786 int seendigit = 0;
787 int m = 0;
788
789 if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0)
790 return getnum_str(startpp, endp);
791 (*startpp)+=2;
792 for (n = 0; *startpp <= endp; ) {
793 c = **startpp;
794 if (isspace(c) || c == '\0') {
795 if (seendigit) /* trailing whitespace */
796 break;
797 else { /* leading whitespace */
798 (*startpp)++;
799 continue;
800 }
801 }
802 if (c == ';') {
803 while ((*startpp <= endp) &&
804 ((c = **startpp) != '\n'))
805 (*startpp)++;
806 if (seendigit)
807 break;
808 continue;
809 }
810 if (!isxdigit(c)) {
811 if (c == ')' && seendigit) {
812 (*startpp)--;
813 break;
814 }
815 return (-1);
816 }
817 (*startpp)++;
818 if (isdigit(c))
819 n = n * 16 + (c - '0');
820 else
821 n = n * 16 + (tolower(c) - 'a' + 10);
822 seendigit = 1;
823 }
824 return (n + m);
825 }
826
827 /*
828 * Get a whitespace delimited base 16 number from a string (not file) into buf
829 * update the start pointer to point after the number in the string.
830 */
831 static int
832 getnum_str(u_char **startpp, u_char *endp) {
833 int c, n;
834 int seendigit = 0;
835 int m = 0;
836
837 for (n = 0; *startpp <= endp; ) {
838 c = **startpp;
839 if (isspace(c) || c == '\0') {
840 if (seendigit) /* trailing whitespace */
841 break;
842 else { /* leading whitespace */
843 (*startpp)++;
844 continue;
845 }
846 }
847 if (c == ';') {
848 while ((*startpp <= endp) &&
849 ((c = **startpp) != '\n'))
850 (*startpp)++;
851 if (seendigit)
852 break;
853 continue;
854 }
855 if (!isdigit(c)) {
856 if (c == ')' && seendigit) {
857 (*startpp)--;
858 break;
859 }
860 return (-1);
861 }
862 (*startpp)++;
863 n = n * 10 + (c - '0');
864 seendigit = 1;
865 }
866 return (n + m);
867 }
868
869 /*
870 * Allocate a resource record buffer & save rr info.
871 */
872 ns_updrec *
873 res_mkupdrec(int section, const char *dname,
874 u_int class, u_int type, u_long ttl) {
875 ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
876
877 if (!rrecp || !(rrecp->r_dname = strdup(dname))) {
878 if (rrecp)
879 free((char *)rrecp);
880 return (NULL);
881 }
882 INIT_LINK(rrecp, r_link);
883 INIT_LINK(rrecp, r_glink);
884 rrecp->r_class = class;
885 rrecp->r_type = type;
886 rrecp->r_ttl = ttl;
887 rrecp->r_section = section;
888 return (rrecp);
889 }
890
891 /*
892 * Free a resource record buffer created by res_mkupdrec.
893 */
894 void
895 res_freeupdrec(ns_updrec *rrecp) {
896 /* Note: freeing r_dp is the caller's responsibility. */
897 if (rrecp->r_dname != NULL)
898 free(rrecp->r_dname);
899 free(rrecp);
900 }
901
902 struct valuelist {
903 struct valuelist * next;
904 struct valuelist * prev;
905 char * name;
906 char * proto;
907 int port;
908 };
909 static struct valuelist *servicelist, *protolist;
910
911 static void
912 res_buildservicelist() {
913 struct servent *sp;
914 struct valuelist *slp;
915
916 #ifdef MAYBE_HESIOD
917 setservent(0);
918 #else
919 setservent(1);
920 #endif
921 while ((sp = getservent()) != NULL) {
922 slp = (struct valuelist *)malloc(sizeof(struct valuelist));
923 if (!slp)
924 break;
925 slp->name = strdup(sp->s_name);
926 slp->proto = strdup(sp->s_proto);
927 if ((slp->name == NULL) || (slp->proto == NULL)) {
928 if (slp->name) free(slp->name);
929 if (slp->proto) free(slp->proto);
930 free(slp);
931 break;
932 }
933 slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */
934 slp->next = servicelist;
935 slp->prev = NULL;
936 if (servicelist)
937 servicelist->prev = slp;
938 servicelist = slp;
939 }
940 endservent();
941 }
942
943 void
944 res_destroyservicelist() {
945 struct valuelist *slp, *slp_next;
946
947 for (slp = servicelist; slp != NULL; slp = slp_next) {
948 slp_next = slp->next;
949 free(slp->name);
950 free(slp->proto);
951 free(slp);
952 }
953 servicelist = (struct valuelist *)0;
954 }
955
956 void
957 res_buildprotolist(void) {
958 struct protoent *pp;
959 struct valuelist *slp;
960
961 #ifdef MAYBE_HESIOD
962 setprotoent(0);
963 #else
964 setprotoent(1);
965 #endif
966 while ((pp = getprotoent()) != NULL) {
967 slp = (struct valuelist *)malloc(sizeof(struct valuelist));
968 if (!slp)
969 break;
970 slp->name = strdup(pp->p_name);
971 if (slp->name == NULL) {
972 free(slp);
973 break;
974 }
975 slp->port = pp->p_proto; /* host byte order */
976 slp->next = protolist;
977 slp->prev = NULL;
978 if (protolist)
979 protolist->prev = slp;
980 protolist = slp;
981 }
982 endprotoent();
983 }
984
985 void
986 res_destroyprotolist(void) {
987 struct valuelist *plp, *plp_next;
988
989 for (plp = protolist; plp != NULL; plp = plp_next) {
990 plp_next = plp->next;
991 free(plp->name);
992 free(plp);
993 }
994 protolist = (struct valuelist *)0;
995 }
996
997 static int
998 findservice(const char *s, struct valuelist **list) {
999 struct valuelist *lp = *list;
1000 int n;
1001
1002 for (; lp != NULL; lp = lp->next)
1003 if (strcasecmp(lp->name, s) == 0) {
1004 if (lp != *list) {
1005 lp->prev->next = lp->next;
1006 if (lp->next)
1007 lp->next->prev = lp->prev;
1008 (*list)->prev = lp;
1009 lp->next = *list;
1010 *list = lp;
1011 }
1012 return (lp->port); /* host byte order */
1013 }
1014 if (sscanf(s, "%d", &n) != 1 || n <= 0)
1015 n = -1;
1016 return (n);
1017 }
1018
1019 /*
1020 * Convert service name or (ascii) number to int.
1021 */
1022 #ifdef __APPLE__
1023 static
1024 #endif
1025 int
1026 res_servicenumber(const char *p) {
1027 if (servicelist == (struct valuelist *)0)
1028 res_buildservicelist();
1029 return (findservice(p, &servicelist));
1030 }
1031
1032 /*
1033 * Convert protocol name or (ascii) number to int.
1034 */
1035 #ifdef __APPLE__
1036 static
1037 #endif
1038 int
1039 res_protocolnumber(const char *p) {
1040 if (protolist == (struct valuelist *)0)
1041 res_buildprotolist();
1042 return (findservice(p, &protolist));
1043 }
1044
1045 static struct servent *
1046 cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */
1047 struct valuelist **list = &servicelist;
1048 struct valuelist *lp = *list;
1049 static struct servent serv;
1050
1051 port = ntohs(port);
1052 for (; lp != NULL; lp = lp->next) {
1053 if (port != (u_int16_t)lp->port) /* Host byte order. */
1054 continue;
1055 if (strcasecmp(lp->proto, proto) == 0) {
1056 if (lp != *list) {
1057 lp->prev->next = lp->next;
1058 if (lp->next)
1059 lp->next->prev = lp->prev;
1060 (*list)->prev = lp;
1061 lp->next = *list;
1062 *list = lp;
1063 }
1064 serv.s_name = lp->name;
1065 serv.s_port = htons((u_int16_t)lp->port);
1066 serv.s_proto = lp->proto;
1067 return (&serv);
1068 }
1069 }
1070 return (0);
1071 }
1072
1073 static struct protoent *
1074 cgetprotobynumber(int proto) { /* Host byte order. */
1075 struct valuelist **list = &protolist;
1076 struct valuelist *lp = *list;
1077 static struct protoent prot;
1078
1079 for (; lp != NULL; lp = lp->next)
1080 if (lp->port == proto) { /* Host byte order. */
1081 if (lp != *list) {
1082 lp->prev->next = lp->next;
1083 if (lp->next)
1084 lp->next->prev = lp->prev;
1085 (*list)->prev = lp;
1086 lp->next = *list;
1087 *list = lp;
1088 }
1089 prot.p_name = lp->name;
1090 prot.p_proto = lp->port; /* Host byte order. */
1091 return (&prot);
1092 }
1093 return (0);
1094 }
1095
1096 const char *
1097 res_protocolname(int num) {
1098 static char number[8];
1099 struct protoent *pp;
1100
1101 if (protolist == (struct valuelist *)0)
1102 res_buildprotolist();
1103 pp = cgetprotobynumber(num);
1104 if (pp == 0) {
1105 (void) sprintf(number, "%d", num);
1106 return (number);
1107 }
1108 return (pp->p_name);
1109 }
1110
1111 const char *
1112 res_servicename(u_int16_t port, const char *proto) { /* Host byte order. */
1113 static char number[8];
1114 struct servent *ss;
1115
1116 if (servicelist == (struct valuelist *)0)
1117 res_buildservicelist();
1118 ss = cgetservbyport(htons(port), proto);
1119 if (ss == 0) {
1120 (void) sprintf(number, "%d", port);
1121 return (number);
1122 }
1123 return (ss->s_name);
1124 }