experimental socket address conversion function
This commit is contained in:
		| @ -486,7 +486,7 @@ static int rtx_err_uchars (hawk_fmtout_t* fmtout, const hawk_uch_t* ptr, hawk_oo | ||||
| 	rtx->errmsg_len += len; | ||||
| #else | ||||
| 	if (max <= 0) return 1; | ||||
| 	hawk_conv_uchars_to_bchars_with_cmgr (ptr, &len, &rtx->_gem.errmsg[rtx->errmsg_len], &max, hawk_getcmgr(hawk)); | ||||
| 	hawk_conv_uchars_to_bchars_with_cmgr (ptr, &len, &rtx->_gem.errmsg[rtx->errmsg_len], &max, hawk_rtx_getcmgr(rtx)); | ||||
| 	rtx->errmsg_len += max; | ||||
| #endif | ||||
| 	rtx->_gem.errmsg[rtx->errmsg_len] = '\0'; | ||||
| @ -572,3 +572,94 @@ void hawk_gem_seterrnum (hawk_gem_t* gem, const hawk_loc_t* errloc, hawk_errnum_ | ||||
| 	gem->errmsg[0] = '\0'; | ||||
| 	gem->errloc = (errloc? *errloc: _nullloc); | ||||
| } | ||||
|  | ||||
|  | ||||
| static int gem_err_bchars (hawk_fmtout_t* fmtout, const hawk_bch_t* ptr, hawk_oow_t len) | ||||
| { | ||||
| 	hawk_gem_t* gem = (hawk_gem_t*)fmtout->ctx; | ||||
| 	hawk_oow_t max; | ||||
|  | ||||
| 	max = HAWK_COUNTOF(gem->errmsg) - gem->errmsg_len - 1; | ||||
|  | ||||
| #if defined(HAWK_OOCH_IS_UCH) | ||||
| 	if (max <= 0) return 1; | ||||
| 	hawk_conv_bchars_to_uchars_with_cmgr (ptr, &len, &gem->errmsg[gem->errmsg_len], &max, gem->cmgr, 1); | ||||
| 	gem->errmsg_len += max; | ||||
| #else | ||||
| 	if (len > max) len = max; | ||||
| 	if (len <= 0) return 1; | ||||
| 	HAWK_MEMCPY (&gem->errinf.msg[gem->errmsg_len], ptr, len * HAWK_SIZEOF(*ptr)); | ||||
| 	gem->errmsg_len += len; | ||||
| #endif | ||||
|  | ||||
| 	gem->errmsg[gem->errmsg_len] = '\0'; | ||||
|  | ||||
| 	return 1; /* success */ | ||||
| } | ||||
|  | ||||
| static int gem_err_uchars (hawk_fmtout_t* fmtout, const hawk_uch_t* ptr, hawk_oow_t len) | ||||
| { | ||||
| 	hawk_gem_t* gem = (hawk_gem_t*)fmtout->ctx; | ||||
| 	hawk_oow_t max; | ||||
|  | ||||
| 	max = HAWK_COUNTOF(gem->errmsg) - gem->errmsg_len - 1; | ||||
|  | ||||
| #if defined(HAWK_OOCH_IS_UCH) | ||||
| 	if (len > max) len = max; | ||||
| 	if (len <= 0) return 1; | ||||
| 	HAWK_MEMCPY (&gem->errmsg[gem->errmsg_len], ptr, len * HAWK_SIZEOF(*ptr)); | ||||
| 	gem->errmsg_len += len; | ||||
| #else | ||||
| 	if (max <= 0) return 1; | ||||
| 	hawk_conv_uchars_to_bchars_with_cmgr (ptr, &len, &gem->errmsg[gem->errmsg_len], &max, gem->cmgr); | ||||
| 	gem->errmsg_len += max; | ||||
| #endif | ||||
| 	gem->errmsg[gem->errmsg_len] = '\0'; | ||||
| 	return 1; /* success */ | ||||
| } | ||||
|  | ||||
| void hawk_gem_seterrbfmt (hawk_gem_t* gem, const hawk_loc_t* errloc, hawk_errnum_t errnum, const hawk_bch_t* errfmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	hawk_fmtout_t fo; | ||||
|  | ||||
| 	/*if (hawk->shuterr) return;*/ | ||||
| 	gem->errmsg_len = 0; | ||||
| 	gem->errmsg[0] = '\0'; | ||||
|  | ||||
| 	HAWK_MEMSET (&fo, 0, HAWK_SIZEOF(fo)); | ||||
| 	fo.mmgr = hawk_gem_getmmgr(gem); | ||||
| 	fo.putbchars = gem_err_bchars; | ||||
| 	fo.putuchars = gem_err_uchars; | ||||
| 	fo.ctx = gem; | ||||
|  | ||||
| 	va_start (ap, errfmt); | ||||
| 	hawk_bfmt_outv (&fo, errfmt, ap); | ||||
| 	va_end (ap); | ||||
|  | ||||
| 	gem->errnum = errnum; | ||||
| 	gem->errloc = (errloc? *errloc: _nullloc); | ||||
| } | ||||
|  | ||||
| void hawk_gem_seterrufmt (hawk_gem_t* gem, const hawk_loc_t* errloc, hawk_errnum_t errnum, const hawk_uch_t* errfmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	hawk_fmtout_t fo; | ||||
|  | ||||
| 	/*if (hawk->shuterr) return;*/ | ||||
| 	gem->errmsg_len = 0; | ||||
| 	gem->errmsg[0] = '\0'; | ||||
|  | ||||
| 	HAWK_MEMSET (&fo, 0, HAWK_SIZEOF(fo)); | ||||
| 	fo.mmgr = hawk_gem_getmmgr(gem); | ||||
| 	fo.putbchars = gem_err_bchars; | ||||
| 	fo.putuchars = gem_err_uchars; | ||||
| 	fo.ctx = gem; | ||||
|  | ||||
| 	va_start (ap, errfmt); | ||||
| 	hawk_ufmt_outv (&fo, errfmt, ap); | ||||
| 	va_end (ap); | ||||
|  | ||||
| 	gem->errnum = errnum; | ||||
| 	gem->errloc =  (errloc? *errloc: _nullloc); | ||||
| } | ||||
|  | ||||
| @ -927,13 +927,6 @@ struct hawk_loc_t | ||||
| }; | ||||
| typedef struct hawk_loc_t hawk_loc_t; | ||||
|  | ||||
| typedef void (*hawk_assertfail_t) ( | ||||
| 	hawk_gem_t*        gem, | ||||
| 	const hawk_bch_t*   expr, | ||||
| 	const hawk_bch_t*   file, | ||||
| 	hawk_oow_t          line | ||||
| ); | ||||
|  | ||||
| struct hawk_gem_t | ||||
| { | ||||
| 	hawk_mmgr_t*  mmgr; | ||||
| @ -941,9 +934,6 @@ struct hawk_gem_t | ||||
| 	hawk_errnum_t errnum; | ||||
| 	hawk_ooch_t   errmsg[HAWK_ERRMSG_CAPA]; | ||||
| 	hawk_loc_t    errloc; | ||||
| #if defined(HAWK_BUILD_DEBUG) | ||||
| 	hawk_assertfail_t assertfail; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| enum hawk_log_mask_t | ||||
|  | ||||
| @ -354,6 +354,33 @@ typedef int (*hawk_sort_comperx_t) ( | ||||
| ); | ||||
|  | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * SOCKET ADDRESS | ||||
|  * ========================================================================= */ | ||||
| #define HAWK_SIZEOF_SKAD_T 1 | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN > HAWK_SIZEOF_SKAD_T) | ||||
| #	undef HAWK_SIZEOF_SKAD_T | ||||
| #	define HAWK_SIZEOF_SKAD_T HAWK_SIZEOF_STRUCT_SOCKADDR_IN | ||||
| #endif | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) | ||||
| #	undef HAWK_SIZEOF_SKAD_T | ||||
| #	define HAWK_SIZEOF_SKAD_T HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 | ||||
| #endif | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_LL > 0) | ||||
| #	undef HAWK_SIZEOF_SKAD_T | ||||
| #	define HAWK_SIZEOF_SKAD_T HAWK_SIZEOF_STRUCT_SOCKADDR_LL | ||||
| #endif | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_UN > 0) | ||||
| #	undef HAWK_SIZEOF_SKAD_T | ||||
| #	define HAWK_SIZEOF_SKAD_T HAWK_SIZEOF_STRUCT_SOCKADDR_UN | ||||
| #endif | ||||
|  | ||||
| struct hawk_skad_t | ||||
| { | ||||
| 	hawk_uint8_t data[HAWK_SIZEOF_SKAD_T]; | ||||
| }; | ||||
| typedef struct hawk_skad_t hawk_skad_t; | ||||
|  | ||||
| #if defined(__cplusplus) | ||||
| extern "C" { | ||||
| #endif | ||||
| @ -1542,6 +1569,16 @@ HAWK_EXPORT void hawk_sub_time ( | ||||
| ); | ||||
|  | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * SOCKET ADDRESS | ||||
|  * ========================================================================= */ | ||||
| HAWK_EXPORT int hawk_oochars_to_skad ( | ||||
| 	hawk_t*            hawk, | ||||
| 	const hawk_ooch_t* str, | ||||
| 	hawk_oow_t         len, | ||||
| 	hawk_skad_t*       skad | ||||
| ); | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * ASSERTION | ||||
|  * ========================================================================= */ | ||||
|  | ||||
							
								
								
									
										442
									
								
								hawk/lib/utl-skad.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										442
									
								
								hawk/lib/utl-skad.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,442 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2019 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #include <hawk-utl.h> | ||||
| #include "hawk-prv.h" | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #if defined(HAVE_NETINET_IN_H) | ||||
| #	include <netinet/in.h> | ||||
| #endif | ||||
| #if defined(HAVE_SYS_UN_H) | ||||
| #	include <sys/un.h> | ||||
| #endif | ||||
| #if defined(HAVE_NETPACKET_PACKET_H) | ||||
| #	include <netpacket/packet.h> | ||||
| #endif | ||||
| #if defined(HAVE_NET_IF_DL_H) | ||||
| #	include <net/if_dl.h> | ||||
| #endif | ||||
|  | ||||
| union hawk_skad_alt_t | ||||
| { | ||||
| 	struct sockaddr    sa; | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN > 0) | ||||
| 	struct sockaddr_in in4; | ||||
| #endif | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) | ||||
| 	struct sockaddr_in6 in6; | ||||
| #endif | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_LL > 0) | ||||
| 	struct sockaddr_ll ll; | ||||
| #endif | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_UN > 0) | ||||
| 	struct sockaddr_un un; | ||||
| #endif | ||||
| }; | ||||
| typedef union hawk_skad_alt_t hawk_skad_alt_t; | ||||
|  | ||||
| static int str_to_ipv4 (const hawk_ooch_t* str, hawk_oow_t len, struct in_addr* inaddr) | ||||
| { | ||||
| 	const hawk_ooch_t* end; | ||||
| 	int dots = 0, digits = 0; | ||||
| 	hawk_uint32_t acc = 0, addr = 0; | ||||
| 	hawk_ooch_t c; | ||||
|  | ||||
| 	end = str + len; | ||||
|  | ||||
| 	do | ||||
| 	{ | ||||
| 		if (str >= end) | ||||
| 		{ | ||||
| 			if (dots < 3 || digits == 0) return -1; | ||||
| 			addr = (addr << 8) | acc; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		c = *str++; | ||||
|  | ||||
| 		if (c >= '0' && c <= '9')  | ||||
| 		{ | ||||
| 			if (digits > 0 && acc == 0) return -1; | ||||
| 			acc = acc * 10 + (c - '0'); | ||||
| 			if (acc > 255) return -1; | ||||
| 			digits++; | ||||
| 		} | ||||
| 		else if (c == '.')  | ||||
| 		{ | ||||
| 			if (dots >= 3 || digits == 0) return -1; | ||||
| 			addr = (addr << 8) | acc; | ||||
| 			dots++; acc = 0; digits = 0; | ||||
| 		} | ||||
| 		else return -1; | ||||
| 	} | ||||
| 	while (1); | ||||
|  | ||||
| 	inaddr->s_addr = hawk_hton32(addr); | ||||
| 	return 0; | ||||
|  | ||||
| } | ||||
|  | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) | ||||
| static int str_to_ipv6 (const hawk_ooch_t* src, hawk_oow_t len, struct in6_addr* inaddr) | ||||
| { | ||||
| 	hawk_uint8_t* tp, * endp, * colonp; | ||||
| 	const hawk_ooch_t* curtok; | ||||
| 	hawk_ooch_t ch; | ||||
| 	int saw_xdigit; | ||||
| 	unsigned int val; | ||||
| 	const hawk_ooch_t* src_end; | ||||
|  | ||||
| 	src_end = src + len; | ||||
|  | ||||
| 	HAWK_MEMSET (inaddr, 0, HAWK_SIZEOF(*inaddr)); | ||||
| 	tp = &inaddr->s6_addr[0]; | ||||
| 	endp = &inaddr->s6_addr[HAWK_COUNTOF(inaddr->s6_addr)]; | ||||
| 	colonp = HAWK_NULL; | ||||
|  | ||||
| 	/* Leading :: requires some special handling. */ | ||||
| 	if (src < src_end && *src == ':') | ||||
| 	{ | ||||
| 		src++; | ||||
| 		if (src >= src_end || *src != ':') return -1; | ||||
| 	} | ||||
|  | ||||
| 	curtok = src; | ||||
| 	saw_xdigit = 0; | ||||
| 	val = 0; | ||||
|  | ||||
| 	while (src < src_end) | ||||
| 	{ | ||||
| 		int v1; | ||||
|  | ||||
| 		ch = *src++; | ||||
|  | ||||
| 		if (ch >= '0' && ch <= '9') | ||||
| 			v1 = ch - '0'; | ||||
| 		else if (ch >= 'A' && ch <= 'F') | ||||
| 			v1 = ch - 'A' + 10; | ||||
| 		else if (ch >= 'a' && ch <= 'f') | ||||
| 			v1 = ch - 'a' + 10; | ||||
| 		else v1 = -1; | ||||
| 		if (v1 >= 0) | ||||
| 		{ | ||||
| 			val <<= 4; | ||||
| 			val |= v1; | ||||
| 			if (val > 0xffff) return -1; | ||||
| 			saw_xdigit = 1; | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (ch == ':')  | ||||
| 		{ | ||||
| 			curtok = src; | ||||
| 			if (!saw_xdigit)  | ||||
| 			{ | ||||
| 				if (colonp) return -1; | ||||
| 				colonp = tp; | ||||
| 				continue; | ||||
| 			} | ||||
| 			else if (src >= src_end) | ||||
| 			{ | ||||
| 				/* a colon can't be the last character */ | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			*tp++ = (hawk_uint8_t)(val >> 8) & 0xff; | ||||
| 			*tp++ = (hawk_uint8_t)val & 0xff; | ||||
| 			saw_xdigit = 0; | ||||
| 			val = 0; | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (ch == '.' && ((tp + HAWK_SIZEOF(struct in_addr)) <= endp) && | ||||
| 		    str_to_ipv4(curtok, src_end - curtok, (struct in_addr*)tp) == 0)  | ||||
| 		{ | ||||
| 			tp += HAWK_SIZEOF(struct in_addr*); | ||||
| 			saw_xdigit = 0; | ||||
| 			break;  | ||||
| 		} | ||||
|  | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (saw_xdigit)  | ||||
| 	{ | ||||
| 		if (tp + HAWK_SIZEOF(hawk_uint16_t) > endp) return -1; | ||||
| 		*tp++ = (hawk_uint8_t)(val >> 8) & 0xff; | ||||
| 		*tp++ = (hawk_uint8_t)val & 0xff; | ||||
| 	} | ||||
| 	if (colonp != HAWK_NULL)  | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * Since some memmove()'s erroneously fail to handle | ||||
| 		 * overlapping regions, we'll do the shift by hand. | ||||
| 		 */ | ||||
| 		hawk_oow_t n = tp - colonp; | ||||
| 		hawk_oow_t i; | ||||
|   | ||||
| 		for (i = 1; i <= n; i++)  | ||||
| 		{ | ||||
| 			endp[-i] = colonp[n - i]; | ||||
| 			colonp[n - i] = 0; | ||||
| 		} | ||||
| 		tp = endp; | ||||
| 	} | ||||
|  | ||||
| 	if (tp != endp) return -1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| int hawk_oochars_to_skad (hawk_t* hawk, const hawk_ooch_t* str, hawk_oow_t len, hawk_skad_t* _skad) | ||||
| { | ||||
| 	hawk_skad_alt_t* skad = (hawk_skad_alt_t*)_skad; | ||||
| 	const hawk_ooch_t* p; | ||||
| 	const hawk_ooch_t* end; | ||||
| 	hawk_oocs_t tmp; | ||||
|  | ||||
| 	p = str; | ||||
| 	end = str + len; | ||||
|  | ||||
| 	if (p >= end)  | ||||
| 	{ | ||||
| 		hawk_seterrbfmt (hawk, HAWK_EINVAL, "blank address"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	HAWK_MEMSET (skad, 0, HAWK_SIZEOF(*skad)); | ||||
|  | ||||
| #if defined(AF_UNIX) | ||||
| 	if (*p == '/' && len >= 2) | ||||
| 	{ | ||||
| 	#if defined(HAWK_OOCH_IS_BCH) | ||||
| 		hawk_copy_bcstr (skad->un.sun_path, HAWK_COUNTOF(skad->un.sun_path), str); | ||||
| 	#else | ||||
| 		hawk_oow_t dstlen; | ||||
|  | ||||
| 		dstlen = HAWK_COUNTOF(skad->un.sun_path) - 1; | ||||
| 		if (hawk_convutobchars(hawk, p, &len, skad->un.sun_path, &dstlen) <= -1)  | ||||
| 		{ | ||||
| 			hawk_seterrbfmt (hawk, HAWK_EINVAL, "unable to convert encoding"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		skad->un.sun_path[dstlen] = '\0'; | ||||
| 	#endif | ||||
| 		skad->un.sun_family = AF_UNIX; | ||||
| 		return 0; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) | ||||
| 	if (*p == '[') | ||||
| 	{ | ||||
| 		/* IPv6 address */ | ||||
| 		tmp.ptr = (hawk_ooch_t*)++p; /* skip [ and remember the position */ | ||||
| 		while (p < end && *p != '%' && *p != ']') p++; | ||||
|  | ||||
| 		if (p >= end) goto no_rbrack; | ||||
|  | ||||
| 		tmp.len = p - tmp.ptr; | ||||
| 		if (*p == '%') | ||||
| 		{ | ||||
| 			/* handle scope id */ | ||||
| 			hawk_uint32_t x; | ||||
|  | ||||
| 			p++; /* skip % */ | ||||
|  | ||||
| 			if (p >= end) | ||||
| 			{ | ||||
| 				/* premature end */ | ||||
| 				hawk_seterrbfmt (hawk, HAWK_EINVAL, "scope id blank"); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			if (*p >= '0' && *p <= '9')  | ||||
| 			{ | ||||
| 				/* numeric scope id */ | ||||
| 				skad->in6.sin6_scope_id = 0; | ||||
| 				do | ||||
| 				{ | ||||
| 					x = skad->in6.sin6_scope_id * 10 + (*p - '0'); | ||||
| 					if (x < skad->in6.sin6_scope_id)  | ||||
| 					{ | ||||
| 						hawk_seterrbfmt (hawk, HAWK_EINVAL, "scope id too large"); | ||||
| 						return -1; /* overflow */ | ||||
| 					} | ||||
| 					skad->in6.sin6_scope_id = x; | ||||
| 					p++; | ||||
| 				} | ||||
| 				while (p < end && *p >= '0' && *p <= '9'); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| #if 0 | ||||
| TODO: | ||||
| 				/* interface name as a scope id? */ | ||||
| 				const hawk_ooch_t* stmp = p; | ||||
| 				unsigned int index; | ||||
| 				do p++; while (p < end && *p != ']'); | ||||
| 				if (hawk_nwifwcsntoindex(stmp, p - stmp, &index) <= -1) return -1; | ||||
| 				tmpad.u.in6.scope = index; | ||||
| #endif | ||||
| 			} | ||||
|  | ||||
| 			if (p >= end || *p != ']') goto no_rbrack; | ||||
| 		} | ||||
| 		p++; /* skip ] */ | ||||
|  | ||||
| 		if (str_to_ipv6(tmp.ptr, tmp.len, &skad->in6.sin6_addr) <= -1) goto unrecog; | ||||
| 		skad->in6.sin6_family = AF_INET6; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| #endif | ||||
| 		/* IPv4 address */ | ||||
| 		tmp.ptr = (hawk_ooch_t*)p; | ||||
| 		while (p < end && *p != ':') p++; | ||||
| 		tmp.len = p - tmp.ptr; | ||||
|  | ||||
| 		if (str_to_ipv4(tmp.ptr, tmp.len, &skad->in4.sin_addr) <= -1) | ||||
| 		{ | ||||
| 		#if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) | ||||
| 			/* check if it is an IPv6 address not enclosed in [].  | ||||
| 			 * the port number can't be specified in this format. */ | ||||
| 			if (p >= end || *p != ':')  | ||||
| 			{ | ||||
| 				/* without :, it can't be an ipv6 address */ | ||||
| 				goto unrecog; | ||||
| 			} | ||||
|  | ||||
|  | ||||
| 			while (p < end && *p != '%') p++; | ||||
| 			tmp.len = p - tmp.ptr; | ||||
|  | ||||
| 			if (str_to_ipv6(tmp.ptr, tmp.len, &skad->in6.sin6_addr) <= -1) goto unrecog; | ||||
|  | ||||
| 			if (p < end && *p == '%') | ||||
| 			{ | ||||
| 				/* handle scope id */ | ||||
| 				hawk_uint32_t x; | ||||
|  | ||||
| 				p++; /* skip % */ | ||||
|  | ||||
| 				if (p >= end) | ||||
| 				{ | ||||
| 					/* premature end */ | ||||
| 					hawk_seterrbfmt (hawk, HAWK_EINVAL, "scope id blank"); | ||||
| 					return -1; | ||||
| 				} | ||||
|  | ||||
| 				if (*p >= '0' && *p <= '9')  | ||||
| 				{ | ||||
| 					/* numeric scope id */ | ||||
| 					skad->in6.sin6_scope_id = 0; | ||||
| 					do | ||||
| 					{ | ||||
| 						x = skad->in6.sin6_scope_id * 10 + (*p - '0'); | ||||
| 						if (x < skad->in6.sin6_scope_id)  | ||||
| 						{ | ||||
| 							hawk_seterrbfmt (hawk, HAWK_EINVAL, "scope id too large"); | ||||
| 							return -1; /* overflow */ | ||||
| 						} | ||||
| 						skad->in6.sin6_scope_id = x; | ||||
| 						p++; | ||||
| 					} | ||||
| 					while (p < end && *p >= '0' && *p <= '9'); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| #if 0 | ||||
| TODO | ||||
| 					/* interface name as a scope id? */ | ||||
| 					const hawk_ooch_t* stmp = p; | ||||
| 					unsigned int index; | ||||
| 					do p++; while (p < end); | ||||
| 					if (hawk_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1; | ||||
| 					skad->in6.sin6_scope_id = index; | ||||
| #endif | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (p < end) goto unrecog; /* some gargage after the end? */ | ||||
|  | ||||
| 			skad->in6.sin6_family = AF_INET6; | ||||
| 			return 0; | ||||
| 		#else | ||||
| 			goto unrecog; | ||||
| 		#endif | ||||
| 		} | ||||
|  | ||||
| 		skad->in4.sin_family = AF_INET; | ||||
| #if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	if (p < end && *p == ':')  | ||||
| 	{ | ||||
| 		/* port number */ | ||||
| 		hawk_uint32_t port = 0; | ||||
|  | ||||
| 		p++; /* skip : */ | ||||
|  | ||||
| 		tmp.ptr = (hawk_ooch_t*)p; | ||||
| 		while (p < end && *p >= '0' && *p <= '9') | ||||
| 		{ | ||||
| 			port = port * 10 + (*p - '0'); | ||||
| 			p++; | ||||
| 		} | ||||
|  | ||||
| 		tmp.len = p - tmp.ptr; | ||||
| 		if (tmp.len <= 0 || tmp.len >= 6 ||  | ||||
| 		    port > HAWK_TYPE_MAX(hawk_uint16_t))  | ||||
| 		{ | ||||
| 			hawk_seterrbfmt (hawk, HAWK_EINVAL, "port number blank or too large"); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 	#if (HAWK_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) | ||||
| 		if (skad->in4.sin_family == AF_INET) | ||||
| 			skad->in4.sin_port = hawk_hton16(port); | ||||
| 		else | ||||
| 			skad->in6.sin6_port = hawk_hton16(port); | ||||
| 	#else | ||||
| 		skad->in4.sin_port = hawk_hton16(port); | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| unrecog: | ||||
| 	hawk_seterrbfmt (hawk, HAWK_EINVAL, "unrecognized address"); | ||||
| 	return -1; | ||||
| 	 | ||||
| no_rbrack: | ||||
| 	hawk_seterrbfmt (hawk, HAWK_EINVAL, "missing right bracket"); | ||||
| 	return -1; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user