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