1 #include <u.h> 2 #include <libc.h> 3 #include <ip.h> 4 5 char* 6 v4parseip(uchar *to, char *from) 7 { 8 int i; 9 char *p; 10 11 p = from; 12 for(i = 0; i < 4 && *p; i++){ 13 to[i] = strtoul(p, &p, 0); 14 if(*p == '.') 15 p++; 16 } 17 switch(CLASS(to)){ 18 case 0: /* class A - 1 uchar net */ 19 case 1: 20 if(i == 3){ 21 to[3] = to[2]; 22 to[2] = to[1]; 23 to[1] = 0; 24 } else if (i == 2){ 25 to[3] = to[1]; 26 to[1] = 0; 27 } 28 break; 29 case 2: /* class B - 2 uchar net */ 30 if(i == 3){ 31 to[3] = to[2]; 32 to[2] = 0; 33 } 34 break; 35 } 36 return p; 37 } 38 39 ulong 40 parseip(uchar *to, char *from) 41 { 42 int i, elipsis = 0, v4 = 1; 43 ulong x; 44 char *p, *op; 45 46 memset(to, 0, IPaddrlen); 47 p = from; 48 for(i = 0; i < 16 && *p; i+=2){ 49 op = p; 50 x = strtoul(p, &p, 16); 51 if(*p == '.' || (*p == 0 && i == 0)){ 52 p = v4parseip(to+i, op); 53 i += 4; 54 break; 55 } 56 to[i] = x>>8; 57 to[i+1] = x; 58 if(*p == ':'){ 59 v4 = 0; 60 if(*++p == ':'){ 61 elipsis = i+2; 62 p++; 63 } 64 } 65 } 66 if(i < 16){ 67 memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis); 68 memset(&to[elipsis], 0, 16-i); 69 } 70 if(v4){ 71 to[10] = to[11] = 0xff; 72 return nhgetl(to+12); 73 } else 74 return 6; 75 } 76 77 /* 78 * hack to allow ip v4 masks to be entered in the old 79 * style 80 */ 81 ulong 82 parseipmask(uchar *to, char *from) 83 { 84 ulong x; 85 int i, w; 86 uchar *p; 87 88 if(*from == '/'){ 89 /* as a number of prefix bits */ 90 i = atoi(from+1); 91 if(i < 0) 92 i = 0; 93 if(i > 128) 94 i = 128; 95 w = i; 96 memset(to, 0, IPaddrlen); 97 for(p = to; i >= 8; i -= 8) 98 *p++ = 0xff; 99 if(i > 0) 100 *p = ~((1<<(8-i))-1); 101 x = nhgetl(to+IPv4off); 102 /* 103 * identify as ipv6 if the mask is inexpressible as a v4 mask 104 * (because it has too few mask bits) or indistinguishable 105 * from the error value (all ones, -1)? Arguably, we could 106 * always return 6 here. 107 */ 108 if (w < 8*(IPaddrlen-IPv4addrlen) || w == 128) 109 return 6; 110 } else { 111 /* as a straight bit mask */ 112 x = parseip(to, from); 113 if(memcmp(to, v4prefix, IPv4off) == 0) 114 memset(to, 0xff, IPv4off); 115 } 116 return x; 117 } 118 119 /* 120 * parse a v4 ip address/mask in cidr format 121 */ 122 char* 123 v4parsecidr(uchar *addr, uchar *mask, char *from) 124 { 125 int i; 126 char *p; 127 uchar *a; 128 129 p = v4parseip(addr, from); 130 131 if(*p == '/'){ 132 /* as a number of prefix bits */ 133 i = strtoul(p+1, &p, 0); 134 if(i > 32) 135 i = 32; 136 memset(mask, 0, IPv4addrlen); 137 for(a = mask; i >= 8; i -= 8) 138 *a++ = 0xff; 139 if(i > 0) 140 *a = ~((1<<(8-i))-1); 141 } else 142 memcpy(mask, defmask(addr), IPv4addrlen); 143 return p; 144 } 145