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*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
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
45int
46strtoip4(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