⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ns_name.c

📁 DHCP服务器源码
💻 C
字号:
/* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1996-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *   Internet Systems Consortium, Inc. *   950 Charter Street *   Redwood City, CA 94063 *   <info@isc.org> *   http://www.isc.org/ */#ifndef lintstatic const char rcsid[] = "$Id: ns_name.c,v 1.1.2.5 2004/06/10 17:59:40 dhankins Exp $";#endif#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <errno.h>#include <string.h>#include <ctype.h>#include "minires/minires.h"#include "arpa/nameser.h"/* Data. */static const char	digits[] = "0123456789";/* Forward. */static int		special(int);static int		printable(int);static int		dn_find(const u_char *, const u_char *,				const u_char * const *,				const u_char * const *);/* Public. *//* * ns_name_ntop(src, dst, dstsiz) *	Convert an encoded domain name to printable ascii as per RFC1035. * return: *	Number of bytes written to buffer, or -1 (with errno set) * notes: *	The root is returned as "." *	All other domains are returned in non absolute form */intns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {	const u_char *cp;	char *dn, *eom;	u_char c;	u_int n;	cp = src;	dn = dst;	eom = dst + dstsiz;	while ((n = *cp++) != 0) {		if ((n & NS_CMPRSFLGS) != 0) {			/* Some kind of compression pointer. */			errno = EMSGSIZE;			return (-1);		}		if (dn != dst) {			if (dn >= eom) {				errno = EMSGSIZE;				return (-1);			}			*dn++ = '.';		}		if (dn + n >= eom) {			errno = EMSGSIZE;			return (-1);		}		for ((void)NULL; n > 0; n--) {			c = *cp++;			if (special(c)) {				if (dn + 1 >= eom) {					errno = EMSGSIZE;					return (-1);				}				*dn++ = '\\';				*dn++ = (char)c;			} else if (!printable(c)) {				if (dn + 3 >= eom) {					errno = EMSGSIZE;					return (-1);				}				*dn++ = '\\';				*dn++ = digits[c / 100];				*dn++ = digits[(c % 100) / 10];				*dn++ = digits[c % 10];			} else {				if (dn >= eom) {					errno = EMSGSIZE;					return (-1);				}				*dn++ = (char)c;			}		}	}	if (dn == dst) {		if (dn >= eom) {			errno = EMSGSIZE;			return (-1);		}		*dn++ = '.';	}	if (dn >= eom) {		errno = EMSGSIZE;		return (-1);	}	*dn++ = '\0';	return (dn - dst);}/* * ns_name_pton(src, dst, dstsiz) *	Convert a ascii string into an encoded domain name as per RFC1035. * return: *	-1 if it fails *	1 if string was fully qualified *	0 is string was not fully qualified * notes: *	Enforces label and domain length limits. */intns_name_pton(const char *src, u_char *dst, size_t dstsiz) {	u_char *label, *bp, *eom;	int c, n, escaped;	char *cp;	escaped = 0;	bp = dst;	eom = dst + dstsiz;	label = bp++;	while ((c = *src++) != 0) {		if (escaped) {			if ((cp = strchr(digits, c)) != NULL) {				n = (cp - digits) * 100;				if ((c = *src++) == 0 ||				    (cp = strchr(digits, c)) == NULL) {					errno = EMSGSIZE;					return (-1);				}				n += (cp - digits) * 10;				if ((c = *src++) == 0 ||				    (cp = strchr(digits, c)) == NULL) {					errno = EMSGSIZE;					return (-1);				}				n += (cp - digits);				if (n > 255) {					errno = EMSGSIZE;					return (-1);				}				c = n;			}			escaped = 0;		} else if (c == '\\') {			escaped = 1;			continue;		} else if (c == '.') {			c = (bp - label - 1);			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */				errno = EMSGSIZE;				return (-1);			}			if (label >= eom) {				errno = EMSGSIZE;				return (-1);			}			*label = c;			/* Fully qualified ? */			if (*src == '\0') {				if (c != 0) {					if (bp >= eom) {						errno = EMSGSIZE;						return (-1);					}					*bp++ = '\0';				}				if ((bp - dst) > MAXCDNAME) {					errno = EMSGSIZE;					return (-1);				}				return (1);			}			if (c == 0 || *src == '.') {				errno = EMSGSIZE;				return (-1);			}			label = bp++;			continue;		}		if (bp >= eom) {			errno = EMSGSIZE;			return (-1);		}		*bp++ = (u_char)c;	}	c = (bp - label - 1);	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */		errno = EMSGSIZE;		return (-1);	}	if (label >= eom) {		errno = EMSGSIZE;		return (-1);	}	*label = c;	if (c != 0) {		if (bp >= eom) {			errno = EMSGSIZE;			return (-1);		}		*bp++ = 0;	}	if ((bp - dst) > MAXCDNAME) {	/* src too big */		errno = EMSGSIZE;		return (-1);	}	return (0);}/* * ns_name_ntol(src, dst, dstsiz) *	Convert a network strings labels into all lowercase. * return: *	Number of bytes written to buffer, or -1 (with errno set) * notes: *	Enforces label and domain length limits. */intns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {	const u_char *cp;	u_char *dn, *eom;	u_char c;	u_int n;	cp = src;	dn = dst;	eom = dst + dstsiz;	if (dn >= eom) {		errno = EMSGSIZE;		return (-1);	}	while ((n = *cp++) != 0) {		if ((n & NS_CMPRSFLGS) != 0) {			/* Some kind of compression pointer. */			errno = EMSGSIZE;			return (-1);		}		*dn++ = n;		if (dn + n >= eom) {			errno = EMSGSIZE;			return (-1);		}		for ((void)NULL; n > 0; n--) {			c = *cp++;			if (isupper(c))				*dn++ = tolower(c);			else				*dn++ = c;		}	}	*dn++ = '\0';	return (dn - dst);}/* * ns_name_unpack(msg, eom, src, dst, dstsiz) *	Unpack a domain name from a message, source may be compressed. * return: *	-1 if it fails, or consumed octets if it succeeds. */intns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,	       u_char *dst, size_t dstsiz){	const u_char *srcp, *dstlim;	u_char *dstp;	unsigned n;	int len;	int checked;	len = -1;	checked = 0;	dstp = dst;	srcp = src;	dstlim = dst + dstsiz;	if (srcp < msg || srcp >= eom) {		errno = EMSGSIZE;		return (-1);	}	/* Fetch next label in domain name. */	while ((n = *srcp++) != 0) {		/* Check for indirection. */		switch (n & NS_CMPRSFLGS) {		case 0:			/* Limit checks. */			if (dstp + n + 1 >= dstlim || srcp + n >= eom) {				errno = EMSGSIZE;				return (-1);			}			checked += n + 1;			*dstp++ = n;			memcpy(dstp, srcp, n);			dstp += n;			srcp += n;			break;		case NS_CMPRSFLGS:			if (srcp >= eom) {				errno = EMSGSIZE;				return (-1);			}			if (len < 0)				len = srcp - src + 1;			srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));			if (srcp < msg || srcp >= eom) {  /* Out of range. */				errno = EMSGSIZE;				return (-1);			}			checked += 2;			/*			 * Check for loops in the compressed name;			 * if we've looked at the whole message,			 * there must be a loop.			 */			if (checked >= eom - msg) {				errno = EMSGSIZE;				return (-1);			}			break;		default:			errno = EMSGSIZE;			return (-1);			/* flag error */		}	}	*dstp = '\0';	if (len < 0)		len = srcp - src;	return (len);}/* * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) *	Pack domain name 'domain' into 'comp_dn'. * return: *	Size of the compressed name, or -1. * notes: *	'dnptrs' is an array of pointers to previous compressed names. *	dnptrs[0] is a pointer to the beginning of the message. The array *	ends with NULL. *	'lastdnptr' is a pointer to the end of the array pointed to *	by 'dnptrs'. * Side effects: *	The list of pointers in dnptrs is updated for labels inserted into *	the message as we compress the name.  If 'dnptr' is NULL, we don't *	try to compress names. If 'lastdnptr' is NULL, we don't update the *	list. */intns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz,	     const u_char **dnptrs, const u_char **lastdnptr){	u_char *dstp;	const u_char **cpp, **lpp, *eob, *msg;	const u_char *srcp;	unsigned n;	int l;	srcp = src;	dstp = dst;	eob = dstp + dstsiz;	lpp = cpp = NULL;	if (dnptrs != NULL) {		if ((msg = *dnptrs++) != NULL) {			for (cpp = dnptrs; *cpp != NULL; cpp++)				(void)NULL;			lpp = cpp;	/* end of list to search */		}	} else		msg = NULL;	/* make sure the domain we are about to add is legal */	l = 0;	do {		n = *srcp;		if ((n & NS_CMPRSFLGS) != 0) {			errno = EMSGSIZE;			return (-1);		}		l += n + 1;		if (l > MAXCDNAME) {			errno = EMSGSIZE;			return (-1);		}		srcp += n + 1;	} while (n != 0);	/* from here on we need to reset compression pointer array on error */	srcp = src;	do {		/* Look to see if we can use pointers. */		n = *srcp;		if (n != 0 && msg != NULL) {			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,				    (const u_char * const *)lpp);			if (l >= 0) {				if (dstp + 1 >= eob) {					goto cleanup;				}				*dstp++ = (l >> 8) | NS_CMPRSFLGS;				*dstp++ = l % 256;				return (dstp - dst);			}			/* Not found, save it. */			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&			    (dstp - msg) < 0x4000) {				*cpp++ = dstp;				*cpp = NULL;			}		}		/* copy label to buffer */		if (n & NS_CMPRSFLGS) {		/* Should not happen. */			goto cleanup;		}		if (dstp + 1 + n >= eob) {			goto cleanup;		}		memcpy(dstp, srcp, n + 1);		srcp += n + 1;		dstp += n + 1;	} while (n != 0);	if (dstp > eob) {cleanup:		if (msg != NULL)			*lpp = NULL;		errno = EMSGSIZE;		return (-1);	} 	return (dstp - dst);}/* * ns_name_uncompress(msg, eom, src, dst, dstsiz) *	Expand compressed domain name to presentation format. * return: *	Number of bytes read out of `src', or -1 (with errno set). * note: *	Root domain returns as "." not "". */intns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,		   char *dst, size_t dstsiz){	u_char tmp[NS_MAXCDNAME];	int n;		if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)		return (-1);	if (ns_name_ntop(tmp, dst, dstsiz) == -1)		return (-1);	return (n);}/* * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) *	Compress a domain name into wire format, using compression pointers. * return: *	Number of bytes consumed in `dst' or -1 (with errno set). * notes: *	'dnptrs' is an array of pointers to previous compressed names. *	dnptrs[0] is a pointer to the beginning of the message. *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the *	array pointed to by 'dnptrs'. Side effect is to update the list of *	pointers for labels inserted into the message as we compress the name. *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' *	is NULL, we don't update the list. */intns_name_compress(const char *src, u_char *dst, size_t dstsiz,		 const u_char **dnptrs, const u_char **lastdnptr){	u_char tmp[NS_MAXCDNAME];	if (ns_name_pton(src, tmp, sizeof tmp) == -1)		return (-1);	return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));}/* * ns_name_skip(ptrptr, eom) *	Advance *ptrptr to skip over the compressed name it points at. * return: *	0 on success, -1 (with errno set) on failure. */intns_name_skip(const u_char **ptrptr, const u_char *eom) {	const u_char *cp;	u_int n;	cp = *ptrptr;	while (cp < eom && (n = *cp++) != 0) {		/* Check for indirection. */		switch (n & NS_CMPRSFLGS) {		case 0:			/* normal case, n == len */			cp += n;			continue;		case NS_CMPRSFLGS:	/* indirection */			cp++;			break;		default:		/* illegal type */			errno = EMSGSIZE;			return (-1);		}		break;	}	if (cp > eom) {		errno = EMSGSIZE;		return (-1);	}	*ptrptr = cp;	return (0);}/* Private. *//* * special(ch) *	Thinking in noninternationalized USASCII (per the DNS spec), *	is this characted special ("in need of quoting") ? * return: *	boolean. */static intspecial(int ch) {	switch (ch) {	case 0x22: /* '"' */	case 0x2E: /* '.' */	case 0x3B: /* ';' */	case 0x5C: /* '\\' */	/* Special modifiers in zone files. */	case 0x40: /* '@' */	case 0x24: /* '$' */		return (1);	default:		return (0);	}}/* * printable(ch) *	Thinking in noninternationalized USASCII (per the DNS spec), *	is this character visible and not a space when printed ? * return: *	boolean. */static intprintable(int ch) {	return (ch > 0x20 && ch < 0x7f);}/* *	Thinking in noninternationalized USASCII (per the DNS spec), *	convert this character to lower case if it's upper case. */static intmklower(int ch) {	if (ch >= 0x41 && ch <= 0x5A)		return (ch + 0x20);	return (ch);}/* * dn_find(domain, msg, dnptrs, lastdnptr) *	Search for the counted-label name in an array of compressed names. * return: *	offset from msg if found, or -1. * notes: *	dnptrs is the pointer to the first name on the list, *	not the pointer to the start of the message. */static intdn_find(const u_char *domain, const u_char *msg,	const u_char * const *dnptrs,	const u_char * const *lastdnptr){	const u_char *dn, *cp, *sp;	const u_char * const *cpp;	u_int n;	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {		dn = domain;		sp = cp = *cpp;		while ((n = *cp++) != 0) {			/*			 * check for indirection			 */			switch (n & NS_CMPRSFLGS) {			case 0:			/* normal case, n == len */				if (n != *dn++)					goto next;				for ((void)NULL; n > 0; n--)					if (mklower(*dn++) != mklower(*cp++))						goto next;				/* Is next root for both ? */				if (*dn == '\0' && *cp == '\0')					return (sp - msg);				if (*dn)					continue;				goto next;			case NS_CMPRSFLGS:	/* indirection */				cp = msg + (((n & 0x3f) << 8) | *cp);				break;			default:	/* illegal type */				errno = EMSGSIZE;				return (-1);			}		} next: ;	}	errno = ENOENT;	return (-1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -