1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 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
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