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