xref: /plan9/sys/src/libip/parseip.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
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;
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 		memset(to, 0, IPaddrlen);
96 		for(p = to; i >= 8; i -= 8)
97 			*p++ = 0xff;
98 		if(i > 0)
99 			*p = ~((1<<(8-i))-1);
100 		x = nhgetl(to+IPv4off);
101 	} else {
102 		/* as a straight bit mask */
103 		x = parseip(to, from);
104 		if(memcmp(to, v4prefix, IPv4off) == 0)
105 			memset(to, 0xff, IPv4off);
106 	}
107 	return x;
108 }
109 
110 /*
111  *  parse a v4 ip address/mask in cidr format
112  */
113 char*
114 v4parsecidr(uchar *addr, uchar *mask, char *from)
115 {
116 	int i;
117 	char *p;
118 	uchar *a;
119 
120 	p = v4parseip(addr, from);
121 
122 	if(*p == '/'){
123 		/* as a number of prefix bits */
124 		i = strtoul(p+1, &p, 0);
125 		if(i > 32)
126 			i = 32;
127 		memset(mask, 0, IPv4addrlen);
128 		for(a = mask; i >= 8; i -= 8)
129 			*a++ = 0xff;
130 		if(i > 0)
131 			*a = ~((1<<(8-i))-1);
132 	} else
133 		memcpy(mask, defmask(addr), IPv4addrlen);
134 	return p;
135 }
136