File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / minires / res_mkupdate.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 8 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    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.1.1.1 2012/10/09 09:06:54 misho 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, *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: 	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>