xref: /illumos-gate/usr/src/contrib/ast/src/lib/libast/string/strtoip4.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 
24 #include <ast.h>
25 #include <ctype.h>
26 
27 /*
28  * convert string to 4 byte local byte order ip address
29  * with optional prefix bits
30  * pointer to first unused char placed in *e, even on error
31  * return 0:ok <0:error
32  *
33  * valid addresses match the egrep RE:
34  *
35  *	[0-9]{1,3}(\.[0-9]{1,3})*|0[xX][0-9a-fA-Z]+
36  *
37  * valid bits/masks match the egrep RE:
38  *
39  *	(/([0-9]+|[0-9]{1,3}(\.[0-9]{1,3})*))?
40  *
41  * if pbits!=0 and no bits/mask specified then trailing 0's in addr
42  * are used to compute the mask
43  */
44 
45 int
strtoip4(register const char * s,char ** e,uint32_t * paddr,unsigned char * pbits)46 strtoip4(register const char* s, char** e, uint32_t* paddr, unsigned char* pbits)
47 {
48 	register int		c;
49 	register unsigned int	n;
50 	register uint32_t	addr;
51 	register int		part;
52 	register unsigned char	bits;
53 	uint32_t		z;
54 	int			old;
55 	int			r;
56 	const char*		b;
57 
58 	r = -1;
59 	while (isspace(*s))
60 		s++;
61 	b = s;
62 	addr = 0;
63 	bits = 0;
64 	part = 0;
65 	do
66 	{
67 		n = 0;
68 		while ((c = *s++) >= '0' && c <= '9')
69 			n = n * 10 + (c - '0');
70 		if ((c == 'x' || c == 'X') && !part)
71 		{
72 			addr = n;
73 			for (;;)
74 			{
75 				if ((c = *s++) >= '0' && c <= '9')
76 					c -= '0';
77 				else if (c >= 'a' && c <= 'f')
78 					c -= 'a' - 10;
79 				else if (c >= 'A' && c <= 'F')
80 					c -= 'F' - 10;
81 				else
82 					break;
83 				addr = addr * 16 + c;
84 			}
85 			part = 4;
86 			break;
87 		}
88 		if (n > 0xff)
89 			goto done;
90 		addr = (addr << 8) | n;
91 		part++;
92 	} while (c == '.');
93 	if ((s - b) == 1 && c != '/' || part > 4)
94 		goto done;
95 	if (old = part < 4)
96 		while (part++ < 4)
97 			addr <<= 8;
98 	if (pbits)
99 	{
100 		if (c == '/')
101 		{
102 			part = 0;
103 			z = 0;
104 			for (;;)
105 			{
106 				n = 0;
107 				while ((c = *s++) >= '0' && c <= '9')
108 					n = n * 10 + (c - '0');
109 				z = (z << 8) | n;
110 				part++;
111 				if (c != '.')
112 					break;
113 				old = 1;
114 			}
115 			if (part > 4)
116 				goto done;
117 			if (z <= 32 && (!old || part < 2))
118 				bits = z;
119 			else if (z)
120 			{
121 				if (part == 4 && (z & 0x8000001) == 1)
122 					z = ~z;
123 				while (!(z & 1))
124 					z >>= 1;
125 				while (z & 1)
126 				{
127 					z >>= 1;
128 					bits++;
129 				}
130 			}
131 		}
132 		else if ((z = (addr >> 24)) < 128)
133 			bits = 8;
134 		else if (z < 192)
135 			bits = 16;
136 		else
137 			bits = 24;
138 		if (*pbits = bits)
139 			addr &= ~((((uint32_t)1)<<(32-bits))-1);
140 		else
141 			addr = 0;
142 	}
143 	if (paddr)
144 		*paddr = addr;
145 	r = 0;
146  done:
147 	if (e)
148 		*e = (char*)(s - 1);
149 	return r;
150 }
151