1 #ifndef __ip6_h
2 #define __ip6_h
3 
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <sys/param.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 
13 #include "mem.h"
14 #include "str.h"
15 
16 #ifndef IP_LEN
17 #define IP_LEN	16
18 #endif
19 
ipv6_null(unsigned char * ip)20 static int inline ipv6_null(unsigned char *ip)
21 {
22 	int i;
23 	for (i = 0; ip[i] == 0 && i < 16; i++);
24 	return i == 16 ? 1 : 0;
25 }
ipv6_helper(const char * str,unsigned char ip[16],unsigned char * sub)26 static int inline ipv6_helper(const char *str, unsigned char ip[16], unsigned char *sub)
27 {
28 	register int p, v, v4, v6, n;
29 	int x[8];
30 	int c, s, d, saw_colon;
31 
32 	/* and you thought ipv4 was bad... */
33 	saw_colon = 0;
34 	for (p = s = d = v4 = v6 = n = 0, c = -1; p < 8 && *str; str++) {
35 		switch (*str) {
36 		case '0':		v = 0; break;
37 		case '1':		v = 1; break;
38 		case '2':		v = 2; break;
39 		case '3':		v = 3; break;
40 		case '4':		v = 4; break;
41 		case '5':		v = 5; break;
42 		case '6':		v = 6; break;
43 		case '7':		v = 7; break;
44 		case '8':		v = 8; break;
45 		case '9':		v = 9; break;
46 		case 'a': case 'A':	v = 10; break;
47 		case 'b': case 'B':	v = 11; break;
48 		case 'c': case 'C':	v = 12; break;
49 		case 'd': case 'D':	v = 13; break;
50 		case 'e': case 'E':	v = 14; break;
51 		case 'f': case 'F':	v = 15; break;
52 		case '/':
53 			/* cidr */
54 			if (!sub) return 0;
55 			s = 1;
56 			if (d) {
57 				x[p] = v4;
58 			} else {
59 				x[p] = v6;
60 			}
61 			p++; v4 = v6 = n = 0;
62 			break;
63 		case ':':
64 			if (s || d) return 0;
65 			saw_colon = 1;
66 			x[p] = v6; p++; v4 = v6 = n = 0;
67 			if (str[1] == ':') {
68 				c = p;
69 				str++;
70 			}
71 			break;
72 
73 		case '.':
74 			if (s) return 0;
75 			x[p] = v4; p++; v4 = v6 = n = 0;
76 			d = 1;
77 			break;
78 		default:
79 			return 0;
80 		};
81 		v4 *= 10; v4 += v;
82 		v6 *= 16; v6 += v;
83 		n++;
84 	}
85 	if (!saw_colon) {
86 		/* could be ipv4... */
87 		return 0;
88 	}
89 	if (n) {
90 		if (s) {
91 			if (!sub) return 0;
92 
93 			/* last atom was subnet */
94 			if (v4 < 0 || v4 > 128) return 0;
95 
96 			/* invert */
97 			v4 = 128 - v4;
98 			for (v6 = v = 0; v6 < 16; v += 8, v6++) {
99 				if (v4 < v) {
100 					sub[v6] = (0xFF << v4) & 0xFF;
101 				} else {
102 					sub[v6] = 0xFF;
103 				}
104 			}
105 
106 		} else if (d) {
107 			x[p] = v4;
108 			p++;
109 		} else {
110 			x[p] = v6;
111 			p++;
112 		}
113 	}
114 
115 	for (v = v4 = 0; v < c; v++, v4++, v4++) {
116 		ip[v4] = (x[v] & 0xFF00) >> 8;
117 		ip[v4+1] = (x[v] & 0x00FF);
118 	}
119 	v6 = (16 - p) + v4;
120 	if (!sub && v6 != 0 && c == -1)
121 		return 0;
122 	for (; v4 < v6; v4++)
123 		ip[v4] = 0;
124 	for (v = (c == -1 ? 0 : c); v < p; v++, v4++, v4++) {
125 		ip[v4] = (x[v] & 0xFF00) >> 8;
126 		ip[v4+1] = (x[v] & 0x00FF);
127 	}
128 	for (; v4 < 32; v4++) {
129 		ip[v4] = 0; /* set the rest of the bits to 0 */
130 	}
131 	return 1;
132 }
ipv6_scan(const char * str,unsigned char ip[16])133 static int inline ipv6_scan(const char *str, unsigned char ip[16])
134 {
135 	return ipv6_helper(str, ip, 0) ? 16 : 0;
136 }
ipv6_cidr(const char * str,unsigned char ip[32])137 static int inline ipv6_cidr(const char *str, unsigned char ip[32])
138 {
139 	return ipv6_helper(str, ip, ip+16) ? 32 : 0;
140 }
ipv6_in_subnet(unsigned char cidr[32],unsigned char ip[16])141 static int inline ipv6_in_subnet(unsigned char cidr[32], unsigned char ip[16])
142 {
143 	register int i;
144 	for (i = 0; i < 16 && cidr[i] == 0; i++);
145 	if (i == 16) return 1;
146 	for (i = 0; i < 16; i++) {
147 		if (cidr[i] != (ip[i] & cidr[16+i]))
148 			return 0;
149 	}
150 	return 1;
151 }
socket_bind6(int fd,unsigned char ip[16],int port)152 static int inline socket_bind6(int fd, unsigned char ip[16], int port)
153 {
154 	struct sockaddr_in6 sin;
155 
156 	memzero(&sin, sizeof(sin));
157 
158 	sin.sin6_family = PF_INET6;
159 	sin.sin6_port = htons(port);
160 	memcpy(&sin.sin6_addr, ip, 16);
161 
162 	return bind(fd, (struct sockaddr *)&sin, sizeof(sin));
163 }
socket_bind6_reuse(int fd,unsigned char ip[16],int port)164 static int inline socket_bind6_reuse(int fd, unsigned char ip[16], int port)
165 {
166 	int opt = 1;
167 	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
168 	return socket_bind6(fd, ip, port);
169 }
socket_peer6(int fd,unsigned char ip[16],int * port)170 static int inline socket_peer6(int fd, unsigned char ip[16], int *port)
171 {
172 	struct sockaddr_in6 sin;
173 	int silen;
174 
175 	memzero(&sin, sizeof(sin));
176 
177 	silen = sizeof(sin);
178 	sin.sin6_family = PF_INET6;
179 	if (getpeername(fd, (struct sockaddr *)&sin, (int *)&silen) == -1) {
180 		return 0;
181 	}
182 
183 	if (sin.sin6_family != PF_INET6)
184 		return 0;
185 
186 	/* Clib */
187 	memcpy(ip, &sin.sin6_addr, 16);
188 	*port = ntohs(sin.sin6_port);
189 	return 1;
190 }
191 
socket_local6(int fd,unsigned char ip[16],int * port)192 static int inline socket_local6(int fd, unsigned char ip[16], int *port)
193 {
194 	struct sockaddr_in6 sin;
195 	int silen;
196 
197 	memzero(&sin, sizeof(sin));
198 
199 	silen = sizeof(sin);
200 	sin.sin6_family = PF_INET6;
201 	if (getsockname(fd, (struct sockaddr *)&sin, (int *)&silen) == -1) {
202 		return 0;
203 	}
204 
205 	if (sin.sin6_family != PF_INET6)
206 		return 0;
207 
208 	/* Clib */
209 	memcpy(ip, &sin.sin6_addr, 16);
210 	*port = ntohs(sin.sin6_port);
211 	return 1;
212 }
213 
socket_tcp6(void)214 static int inline socket_tcp6(void)
215 {
216 	int fd;
217 
218 	fd = socket(PF_INET6, SOCK_STREAM, 0);
219 	if (fd == -1) return -1;
220 	if (ndelay_on(fd) == -1) { close(fd); return -1; }
221 	return fd;
222 }
socket_udp6(void)223 static int inline socket_udp6(void)
224 {
225 	int fd;
226 
227 	fd = socket(PF_INET6, SOCK_DGRAM, 0);
228 	if (fd == -1) return -1;
229 	if (ndelay_on(fd) == -1) { close(fd); return -1; }
230 	return fd;
231 }
socket_accept6(int s,unsigned char ip[16],int * port)232 static int inline socket_accept6(int s, unsigned char ip[16], int *port)
233 {
234 	struct sockaddr_in6 sa;
235 	int dummy = sizeof sa;
236 	int r;
237 
238 	memzero(&sa, sizeof(sa));
239 	r = accept(s, (struct sockaddr *)&sa, &dummy);
240 	if (r == -1) return -1;
241 
242 	/* Clib */
243 	memcpy(ip, &sa.sin6_addr, 16);
244 	*port = ntohs(sa.sin6_port);
245 
246 	return r;
247 }
socket_recv6(int s,char * buf,int len,unsigned char ip[16],int * port)248 static int inline socket_recv6(int s, char *buf, int len, unsigned char ip[16], int *port)
249 {
250 	struct sockaddr_in6 sa;
251 	int dummy = sizeof sa;
252 	int r;
253 
254 	memzero(&sa, sizeof(sa));
255 	r = recvfrom(s, buf, len, 0, (struct sockaddr *)&sa, &dummy);
256 	if (r == -1) return -1;
257 
258 	/* Clib */
259 	memcpy(ip, &sa.sin6_addr, 16);
260 	*port = ntohs(sa.sin6_port);
261 
262 	return r;
263 }
socket_send6(int s,const char * buf,int len,const unsigned char ip[16],int port)264 static int inline socket_send6(int s, const char *buf, int len, const unsigned char ip[16], int port)
265 {
266 	struct sockaddr_in6 sa;
267 
268 	memzero(&sa, sizeof(sa));
269 	sa.sin6_family = PF_INET6;
270 	/* Clib */
271 	sa.sin6_port = htons(port);
272 	memcpy(&sa.sin6_addr, ip, 16);
273 
274 	return sendto(s, buf, len, 0, (struct sockaddr *)&sa, sizeof(sa));
275 }
276 
277 #endif
278