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

📄 ttoaddr.c

📁 This a good VPN source
💻 C
字号:
/* * conversion from text forms of addresses to internal ones * Copyright (C) 2000  Henry Spencer. *  * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>. *  * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public * License for more details. * * RCSID $Id: ttoaddr.c,v 1.11 2004/04/09 18:00:37 mcr Exp $ */#include "internal.h"#include "openswan.h"/* * Legal ASCII characters in a domain name.  Underscore technically is not, * but is a common misunderstanding.  Non-ASCII characters are simply * exempted from checking at the moment, to allow for UTF-8 encoded stuff; * the purpose of this check is merely to catch blatant errors. */static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"				"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";#define	ISASCII(c)	(((c) & 0x80) == 0)static err_t tryname(const char *, size_t, int, int, ip_address *);static err_t tryhex(const char *, size_t, int, ip_address *);static err_t trydotted(const char *, size_t, ip_address *);static err_t getbyte(const char **, const char *, int *);static err_t colon(const char *, size_t, ip_address *);static err_t getpiece(const char **, const char *, unsigned *);/* - ttoaddr - convert text name or dotted-decimal address to binary address */err_t				/* NULL for success, else string literal */ttoaddr(src, srclen, af, dst)const char *src;size_t srclen;			/* 0 means "apply strlen" */int af;				/* address family */ip_address *dst;{	err_t oops;#	define	HEXLEN	10	/* strlen("0x11223344") */	int nultermd;	if (srclen == 0) {		srclen = strlen(src);		if (srclen == 0)			return "empty string";		nultermd = 1;	} else		nultermd = 0;	/* at least, not *known* to be terminated */	switch (af) {	case AF_INET:	case AF_INET6:	case 0:                  /* guess */		break;	    	default:		return "invalid address family";	}	if (af == AF_INET && srclen == HEXLEN && *src == '0') {		if (*(src+1) == 'x' || *(src+1) == 'X')			return tryhex(src+2, srclen-2, 'x', dst);		if (*(src+1) == 'h' || *(src+1) == 'H')			return tryhex(src+2, srclen-2, 'h', dst);	}	if (memchr(src, ':', srclen) != NULL) {	    if(af == 0)	    {		af = AF_INET6;	    }	    		if (af != AF_INET6)			return "non-ipv6 address may not contain `:'";		return colon(src, srclen, dst);	}	if (af == 0 || af == AF_INET) {		oops = trydotted(src, srclen, dst);		if (oops == NULL)			return NULL;		/* it worked */		if (*oops != '?')			return oops;		/* probably meant as d-d */	}	return tryname(src, srclen, nultermd, af, dst);}/* - tnatoaddr - convert text numeric address (only) to binary address */err_t				/* NULL for success, else string literal */tnatoaddr(src, srclen, af, dst)const char *src;size_t srclen;			/* 0 means "apply strlen" */int af;				/* address family */ip_address *dst;{	err_t oops;	if (srclen == 0) {		srclen = strlen(src);		if (srclen == 0)			return "empty string";	}	switch (af) {	case 0:  /* guess */	        oops = colon(src, srclen, dst);		if(oops == NULL)		{		    return NULL;		}		oops = trydotted(src, srclen, dst);		if(oops == NULL)		{		    return NULL;		}		return "does not appear to be either IPv4 or IPv6 numeric address";		break;	    	case AF_INET6:		return colon(src, srclen, dst);		break;	case AF_INET:		oops = trydotted(src, srclen, dst);		if (oops == NULL)			return NULL;		/* it worked */		if (*oops != '?')			return oops;		/* probably meant as d-d */		return "does not appear to be numeric address";		break;	default:		return "unknown address family in tnatoaddr";		break;	}}/* - tryname - try it as a name * Slightly complicated by lack of reliable NUL termination in source. */static err_ttryname(src, srclen, nultermd, af, dst)const char *src;size_t srclen;int nultermd;			/* is it known to be NUL-terminated? */int af;ip_address *dst;{	struct hostent *h;	struct netent *ne = NULL;	char namebuf[100];	/* enough for most DNS names */	const char *cp;	char *p = namebuf;	size_t n;	for (cp = src, n = srclen; n > 0; cp++, n--)		if (ISASCII(*cp) && strchr(namechars, *cp) == NULL)			return "illegal (non-DNS-name) character in name";	if (nultermd)		cp = src;	else {		if (srclen+1 > sizeof(namebuf)) {			p = (char *) MALLOC(srclen+1);			if (p == NULL)				return "unable to get temporary space for name";		}		p[0] = '\0';	/* strncpy semantics are wrong */		strncat(p, src, srclen);		cp = (const char *)p;	}	h = gethostbyname2(cp, af);	if (h == NULL && af == AF_INET)		ne = getnetbyname(cp);	if (p != namebuf)		FREE(p);	if (h == NULL && ne == NULL)		return "does not look numeric and name lookup failed";	if (h != NULL) {		if (h->h_addrtype != af)			return "address-type mismatch from gethostbyname2!!!";		return initaddr((unsigned char *)h->h_addr, h->h_length, af, dst);	} else {		if (ne->n_addrtype != af)			return "address-type mismatch from getnetbyname!!!";		ne->n_net = htonl(ne->n_net);		return initaddr((unsigned char *)&ne->n_net, sizeof(ne->n_net),								af, dst);	}}/* - tryhex - try conversion as an eight-digit hex number (AF_INET only) */static err_ttryhex(src, srclen, flavor, dst)const char *src;size_t srclen;			/* should be 8 */int flavor;			/* 'x' for network order, 'h' for host order */ip_address *dst;{	err_t oops;	unsigned long ul;	union {		uint32_t addr;		unsigned char buf[4];	} u;	if (srclen != 8)		return "internal error, tryhex called with bad length";	oops = ttoul(src, srclen, 16, &ul);	if (oops != NULL)		return oops;	u.addr = (flavor == 'h') ? ul : htonl(ul);	return initaddr(u.buf, sizeof(u.buf), AF_INET, dst);}/* - trydotted - try conversion as dotted decimal (AF_INET only) * * If the first char of a complaint is '?', that means "didn't look like * dotted decimal at all". */static err_ttrydotted(src, srclen, dst)const char *src;size_t srclen;ip_address *dst;{	const char *stop = src + srclen;	/* just past end */	int byte;	err_t oops;#	define	NBYTES	4	unsigned char buf[NBYTES];	int i;	memset(buf, 0, sizeof(buf));	for (i = 0; i < NBYTES && src < stop; i++) {		oops = getbyte(&src, stop, &byte);		if (oops != NULL) {			if (*oops != '?')				return oops;	/* bad number */			if (i > 1)				return oops+1;	/* failed number */			return oops;		/* with leading '?' */		}		buf[i] = byte;		if (i < 3 && src < stop && *src++ != '.') {			if (i == 0)				return "?syntax error in dotted-decimal address";			else				return "syntax error in dotted-decimal address";		}	}	if (src != stop)		return "extra garbage on end of dotted-decimal address";	return initaddr(buf, sizeof(buf), AF_INET, dst);}/* - getbyte - try to scan a byte in dotted decimal * A subtlety here is that all this arithmetic on ASCII digits really is * highly portable -- ANSI C guarantees that digits 0-9 are contiguous. * It's easier to just do it ourselves than set up for a call to ttoul(). * * If the first char of a complaint is '?', that means "didn't look like a * number at all". */err_tgetbyte(srcp, stop, retp)const char **srcp;		/* *srcp is updated */const char *stop;		/* first untouchable char */int *retp;			/* return-value pointer */{	char c;	const char *p;	int no;	if (*srcp >= stop)		return "?empty number in dotted-decimal address";	no = 0;	p = *srcp;	while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {		no = no*10 + (c - '0');		p++;	}	if (p == *srcp)		return "?non-numeric component in dotted-decimal address";	*srcp = p;	if (no > 255)		return "byte overflow in dotted-decimal address";	*retp = no;	return NULL;}/* - colon - convert IPv6 "numeric" address */static err_tcolon(src, srclen, dst)const char *src;size_t srclen;			/* known to be >0 */ip_address *dst;{	const char *stop = src + srclen;	/* just past end */	unsigned piece;	int gapat;		/* where was empty piece seen */	err_t oops;#	define	NPIECES	8	unsigned char buf[NPIECES*2];	/* short may have wrong byte order */	int i;	int j;#	define	IT	"IPv6 numeric address"	int naftergap;	/* leading or trailing :: becomes single empty field */	if (*src == ':') {		/* legal only if leading :: */		if (srclen == 1 || *(src+1) != ':')			return "illegal leading `:' in " IT;		if (srclen == 2) {			unspecaddr(AF_INET6, dst);			return NULL;		}		src++;		/* past first but not second */		srclen--;	}	if (*(stop-1) == ':') {		/* legal only if trailing :: */		if (srclen == 1 || *(stop-2) != ':')			return "illegal trailing `:' in " IT;		srclen--;		/* leave one */	}	gapat = -1;	for (i = 0; i < NPIECES && src < stop; i++) {		oops = getpiece(&src, stop, &piece);		if (oops != NULL && *oops == ':') {	/* empty field */			if (gapat >= 0)				return "more than one :: in " IT;			gapat = i;		} else if (oops != NULL)			return oops;		buf[2*i] = piece >> 8;		buf[2*i + 1] = piece & 0xff;		if (i < NPIECES-1) {	/* there should be more input */			if (src == stop && gapat < 0)				return IT " ends prematurely";			if (src != stop && *src++ != ':')				return "syntax error in " IT;		}	}	if (src != stop)		return "extra garbage on end of " IT;	if (gapat < 0 && i < NPIECES)	/* should have been caught earlier */		return "incomplete " IT " (internal error)";	if (gapat >= 0 && i == NPIECES)		return "non-abbreviating empty field in " IT;	if (gapat >= 0) {		naftergap = i - (gapat + 1);		for (i--, j = NPIECES-1; naftergap > 0; i--, j--, naftergap--) {			buf[2*j] = buf[2*i];			buf[2*j + 1] = buf[2*i + 1];		}		for (; j >= gapat; j--)			buf[2*j] = buf[2*j + 1] = 0;	}	return initaddr(buf, sizeof(buf), AF_INET6, dst);}/* - getpiece - try to scan one 16-bit piece of an IPv6 address */err_t				/* ":" means "empty field seen" */getpiece(srcp, stop, retp)const char **srcp;		/* *srcp is updated */const char *stop;		/* first untouchable char */unsigned *retp;			/* return-value pointer */{	const char *p;#	define	NDIG	4	int d;	unsigned long ret;	err_t oops;	if (*srcp >= stop || **srcp == ':') {	/* empty field */		*retp = 0;		return ":";	}	p = *srcp;	d = 0;	while (p < stop && d < NDIG && isxdigit(*p)) {		p++;		d++;	}	if (d == 0)		return "non-hex field in IPv6 numeric address";	if (p < stop && d == NDIG && isxdigit(*p))		return "field in IPv6 numeric address longer than 4 hex digits";	oops = ttoul(*srcp, d, 16, &ret);	if (oops != NULL)	/* shouldn't happen, really... */		return oops;	*srcp = p;	*retp = ret;	return NULL;}

⌨️ 快捷键说明

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