xref: /onnv-gate/usr/src/lib/libast/common/string/strtoip4.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin 
244887Schin #include <ast.h>
254887Schin #include <ctype.h>
264887Schin 
274887Schin /*
284887Schin  * convert string to 4 byte local byte order ip address
294887Schin  * with optional prefix bits
304887Schin  * pointer to first unused char placed in *e, even on error
314887Schin  * return 0:ok <0:error
324887Schin  *
334887Schin  * valid addresses match the egrep RE:
344887Schin  *
354887Schin  *	[0-9]{1,3}(\.[0-9]{1,3})*|0[xX][0-9a-fA-Z]+
364887Schin  *
374887Schin  * valid bits/masks match the egrep RE:
384887Schin  *
394887Schin  *	(/([0-9]+|[0-9]{1,3}(\.[0-9]{1,3})*))?
404887Schin  *
414887Schin  * if pbits!=0 and no bits/mask specified then trailing 0's in addr
424887Schin  * are used to compute the mask
434887Schin  */
444887Schin 
454887Schin int
strtoip4(register const char * s,char ** e,uint32_t * paddr,unsigned char * pbits)464887Schin strtoip4(register const char* s, char** e, uint32_t* paddr, unsigned char* pbits)
474887Schin {
484887Schin 	register int		c;
494887Schin 	register unsigned int	n;
504887Schin 	register uint32_t	addr;
514887Schin 	register int		part;
524887Schin 	register unsigned char	bits;
534887Schin 	uint32_t		z;
544887Schin 	int			old;
554887Schin 	int			r;
564887Schin 	const char*		b;
574887Schin 
584887Schin 	r = -1;
594887Schin 	while (isspace(*s))
604887Schin 		s++;
614887Schin 	b = s;
624887Schin 	addr = 0;
634887Schin 	bits = 0;
644887Schin 	part = 0;
654887Schin 	do
664887Schin 	{
674887Schin 		n = 0;
684887Schin 		while ((c = *s++) >= '0' && c <= '9')
694887Schin 			n = n * 10 + (c - '0');
704887Schin 		if ((c == 'x' || c == 'X') && !part)
714887Schin 		{
724887Schin 			addr = n;
734887Schin 			for (;;)
744887Schin 			{
754887Schin 				if ((c = *s++) >= '0' && c <= '9')
764887Schin 					c -= '0';
774887Schin 				else if (c >= 'a' && c <= 'f')
784887Schin 					c -= 'a' - 10;
794887Schin 				else if (c >= 'A' && c <= 'F')
804887Schin 					c -= 'F' - 10;
814887Schin 				else
824887Schin 					break;
834887Schin 				addr = addr * 16 + c;
844887Schin 			}
854887Schin 			part = 4;
864887Schin 			break;
874887Schin 		}
884887Schin 		if (n > 0xff)
894887Schin 			goto done;
904887Schin 		addr = (addr << 8) | n;
914887Schin 		part++;
924887Schin 	} while (c == '.');
934887Schin 	if ((s - b) == 1 && c != '/' || part > 4)
944887Schin 		goto done;
954887Schin 	if (old = part < 4)
964887Schin 		while (part++ < 4)
974887Schin 			addr <<= 8;
984887Schin 	if (pbits)
994887Schin 	{
1004887Schin 		if (c == '/')
1014887Schin 		{
1024887Schin 			part = 0;
1034887Schin 			z = 0;
1044887Schin 			for (;;)
1054887Schin 			{
1064887Schin 				n = 0;
1074887Schin 				while ((c = *s++) >= '0' && c <= '9')
1084887Schin 					n = n * 10 + (c - '0');
1094887Schin 				z = (z << 8) | n;
1104887Schin 				part++;
1114887Schin 				if (c != '.')
1124887Schin 					break;
1134887Schin 				old = 1;
1144887Schin 			}
1154887Schin 			if (part > 4)
1164887Schin 				goto done;
1174887Schin 			if (z <= 32 && (!old || part < 2))
1184887Schin 				bits = z;
1194887Schin 			else if (z)
1204887Schin 			{
1214887Schin 				if (part == 4 && (z & 0x8000001) == 1)
1224887Schin 					z = ~z;
1234887Schin 				while (!(z & 1))
1244887Schin 					z >>= 1;
1254887Schin 				while (z & 1)
1264887Schin 				{
1274887Schin 					z >>= 1;
1284887Schin 					bits++;
1294887Schin 				}
1304887Schin 			}
1314887Schin 		}
1324887Schin 		else if ((z = (addr >> 24)) < 128)
1334887Schin 			bits = 8;
1344887Schin 		else if (z < 192)
1354887Schin 			bits = 16;
1364887Schin 		else
1374887Schin 			bits = 24;
1384887Schin 		if (*pbits = bits)
1394887Schin 			addr &= ~((((uint32_t)1)<<(32-bits))-1);
1404887Schin 		else
1414887Schin 			addr = 0;
1424887Schin 	}
1434887Schin 	if (paddr)
1444887Schin 		*paddr = addr;
1454887Schin 	r = 0;
1464887Schin  done:
1474887Schin 	if (e)
1484887Schin 		*e = (char*)(s - 1);
1494887Schin 	return r;
1504887Schin }
151