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