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