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