1 /*
2 pmacct (Promiscuous mode IP Accounting package)
3 pmacct is Copyright (C) 2003-2020 by Paolo Lucente
4 */
5
6 /*
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include "pmacct.h"
23 #include "addr.h"
24 #include "jhash.h"
25
26 static const char hex[] = "0123456789abcdef";
27
28 /*
29 * str_to_addr() converts a string into a supported family address
30 */
str_to_addr(const char * str,struct host_addr * a)31 unsigned int str_to_addr(const char *str, struct host_addr *a)
32 {
33 if (inet_aton(str, &a->address.ipv4)) {
34 a->family = AF_INET;
35 return a->family;
36 }
37
38 if (inet_pton(AF_INET6, str, &a->address.ipv6) > 0) {
39 a->family = AF_INET6;
40 return a->family;
41 }
42
43 return FALSE;
44 }
45
46 /*
47 * addr_to_str() converts a supported family address into a string
48 * 'str' length is not checked and assumed to be INET6_ADDRSTRLEN
49 */
addr_to_str(char * str,const struct host_addr * a)50 unsigned int addr_to_str(char *str, const struct host_addr *a)
51 {
52 if (a->family == AF_INET) {
53 inet_ntop(AF_INET, &a->address.ipv4, str, INET6_ADDRSTRLEN);
54 return a->family;
55 }
56
57 if (a->family == AF_INET6) {
58 inet_ntop(AF_INET6, &a->address.ipv6, str, INET6_ADDRSTRLEN);
59 return a->family;
60 }
61
62 #if defined ENABLE_PLABEL
63 if (a->family == AF_PLABEL) {
64 strlcpy(str, a->address.plabel, INET6_ADDRSTRLEN);
65 return a->family;
66 }
67 #endif
68
69 memset(str, 0, INET6_ADDRSTRLEN);
70
71 return FALSE;
72 }
73
74 /*
75 * addr_mask_to_str() converts a supported family address into a string
76 */
addr_mask_to_str(char * str,int len,const struct host_addr * a,const struct host_mask * m)77 unsigned int addr_mask_to_str(char *str, int len, const struct host_addr *a, const struct host_mask *m)
78 {
79 char buf[INET6_ADDRSTRLEN];
80
81 if (a->family == m->family) {
82 if (a->family == AF_INET) {
83 inet_ntop(AF_INET, &a->address.ipv4, buf, sizeof(buf));
84 snprintf(str, len, "%s/%u", buf, m->len);
85 return a->family;
86 }
87 else if (a->family == AF_INET6) {
88 inet_ntop(AF_INET6, &a->address.ipv6, buf, sizeof(buf));
89 snprintf(str, len, "%s/%u", buf, m->len);
90 return a->family;
91 }
92 }
93
94 memset(str, 0, len);
95
96 return FALSE;
97 }
98
99 /*
100 * str_to_addr_mask() converts a string into a supported family address
101 */
str_to_addr_mask(const char * str,struct host_addr * a,struct host_mask * m)102 unsigned int str_to_addr_mask(const char *str, struct host_addr *a, struct host_mask *m)
103 {
104 char *delim = NULL, *mask = NULL;
105 unsigned int family = 0, index = 0, j;
106
107 if (!str || !a || !m) return family;
108
109 delim = strchr(str, '/');
110 if (delim) {
111 *delim = '\0';
112 mask = delim+1;
113 }
114
115 family = str_to_addr(str, a);
116 if (delim) *delim = '/';
117
118 if (family) {
119 if (mask) {
120 index = atoi(mask);
121 m->len = index;
122
123 if (family == AF_INET) {
124 if (index > 32) goto error;
125 else {
126 m->mask.m4 = htonl((index == 32) ? 0xffffffffUL : ~(0xffffffffUL >> index));
127 a->address.ipv4.s_addr &= m->mask.m4;
128 }
129 }
130 else if (family == AF_INET6) {
131 if (index > 128) goto error;
132
133 for (j = 0; j < 16 && index >= 8; j++, index -= 8) m->mask.m6[j] = 0xffU;
134 if (j < 16 && index) m->mask.m6[j] = htonl(~(0xffU >> index));
135
136 for (j = 0; j < 16; j++) a->address.ipv6.s6_addr[j] &= m->mask.m6[j];
137 }
138 else goto error;
139 }
140 /* if no mask: set ipv4 mask to /32 and ipv6 mask to /128 */
141 else {
142 if (family == AF_INET) {
143 m->len = 32;
144 m->mask.m4 = 0xffffffffUL;
145 }
146 else if (family == AF_INET6) {
147 m->len = 128;
148 for (j = 0; j < 16; j++) m->mask.m6[j] = 0xffU;
149 }
150 else goto error;
151 }
152
153 m->family = family;
154 }
155
156 return family;
157
158 error:
159 a->family = 0;
160 m->family = 0;
161
162 return FALSE;
163 }
164
165 /*
166 * addr_to_sa() converts a supported family address into a sockaddr
167 * structure
168 */
addr_to_sa(struct sockaddr * sa,struct host_addr * a,u_int16_t port)169 unsigned int addr_to_sa(struct sockaddr *sa, struct host_addr *a, u_int16_t port)
170 {
171 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
172 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
173
174 if (a->family == AF_INET) {
175 sa->sa_family = AF_INET;
176 sa4->sin_addr.s_addr = a->address.ipv4.s_addr;
177 sa4->sin_port = htons(port);
178 return sizeof(struct sockaddr_in);
179 }
180
181 if (a->family == AF_INET6) {
182 sa->sa_family = AF_INET6;
183 ip6_addr_cpy(&sa6->sin6_addr, &a->address.ipv6);
184 sa6->sin6_port = htons(port);
185 return sizeof(struct sockaddr_in6);
186 }
187
188 memset(sa, 0, sizeof(struct sockaddr));
189
190 return FALSE;
191 }
192
193 /*
194 * sa_to_addr() converts a sockaddr structure into a supported family
195 * address
196 */
sa_to_addr(struct sockaddr * sa,struct host_addr * a,u_int16_t * port)197 unsigned int sa_to_addr(struct sockaddr *sa, struct host_addr *a, u_int16_t *port)
198 {
199 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
200 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
201
202 if (sa->sa_family == AF_INET) {
203 a->family = AF_INET;
204 a->address.ipv4.s_addr = sa4->sin_addr.s_addr;
205 *port = ntohs(sa4->sin_port);
206 return sizeof(struct sockaddr_in);
207 }
208
209 if (sa->sa_family == AF_INET6) {
210 a->family = AF_INET6;
211 ip6_addr_cpy(&a->address.ipv6, &sa6->sin6_addr);
212 *port = ntohs(sa6->sin6_port);
213 return sizeof(struct sockaddr_in6);
214 }
215
216 memset(a, 0, sizeof(struct host_addr));
217
218 return FALSE;
219 }
220
221 /*
222 * sa_addr_cmp(): compare two IP addresses: the first encapsulated
223 * into a 'struct sockaddr' and the second into a 'struct host_addr'.
224 * returns 0 if they match, 1 if a1 is found greater than a2; -1 on
225 * the contrary. -1 is also used to flag a generic error (ie. family
226 * not supported).
227 */
sa_addr_cmp(struct sockaddr * sa,struct host_addr * a)228 int sa_addr_cmp(struct sockaddr *sa, struct host_addr *a)
229 {
230 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
231 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
232 struct sockaddr_in6 sa6_local;
233
234 if (a->family == AF_INET && sa->sa_family == AF_INET) {
235 if (sa4->sin_addr.s_addr == a->address.ipv4.s_addr) return FALSE;
236 else if (sa4->sin_addr.s_addr > a->address.ipv4.s_addr) return TRUE;
237 else return ERR;
238 }
239
240 if (a->family == AF_INET6 && sa->sa_family == AF_INET6) {
241 return ip6_addr_cmp(&sa6->sin6_addr, &a->address.ipv6);
242 }
243 else if (a->family == AF_INET && sa->sa_family == AF_INET6) {
244 memset(&sa6_local, 0, sizeof(sa6_local));
245 memset((u_int8_t *)&sa6_local.sin6_addr+10, 0xff, 2);
246 memcpy((u_int8_t *)&sa6_local.sin6_addr+12, &a->address.ipv4.s_addr, 4);
247 return ip6_addr_cmp(&sa6->sin6_addr, &sa6_local.sin6_addr);
248 }
249 else if (a->family == AF_INET6 && sa->sa_family == AF_INET) {
250 memset(&sa6_local, 0, sizeof(sa6_local));
251 memset((u_int8_t *)&sa6_local.sin6_addr+10, 0xff, 2);
252 memcpy((u_int8_t *)&sa6_local.sin6_addr+12, &sa4->sin_addr, 4);
253 return ip6_addr_cmp(&sa6_local.sin6_addr, &a->address.ipv6);
254 }
255
256 return ERR;
257 }
258
259 /*
260 * sa_port_cmp(): compare two TCP/UDP ports: the first encapsulated in a
261 * 'struct sockaddr' and the second as a u_int16_t
262 * returns 0 if they match; 1 if they don't match; -1 to signal a generic
263 * error (e.g. unsupported family).
264 */
sa_port_cmp(struct sockaddr * sa,u_int16_t port)265 int sa_port_cmp(struct sockaddr *sa, u_int16_t port)
266 {
267 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
268 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
269
270 if (sa->sa_family == AF_INET) {
271 if (ntohs(sa4->sin_port) == port) return FALSE;
272 else return TRUE;
273 }
274
275 if (sa->sa_family == AF_INET6) {
276 if (ntohs(sa6->sin6_port) == port) return FALSE;
277 else return TRUE;
278 }
279
280 return ERR;
281 }
282
283 /*
284 * host_addr_cmp() compares two IP addresses in a host_addr structure
285 * returns 0 if they match, 1 if a1 is found greater than a2; -1 on
286 * the contrary. -1 is also used to flag a generic error (ie. family
287 * not supported).
288 */
host_addr_cmp(struct host_addr * a1,struct host_addr * a2)289 int host_addr_cmp(struct host_addr *a1, struct host_addr *a2)
290 {
291 struct host_addr ha_local;
292
293 if (a1->family == AF_INET && a2->family == AF_INET) {
294 if (a1->address.ipv4.s_addr == a2->address.ipv4.s_addr) return FALSE;
295 else if (a1->address.ipv4.s_addr > a2->address.ipv4.s_addr) return TRUE;
296 else return ERR;
297 }
298
299 if (a1->family == AF_INET6 && a2->family == AF_INET6) {
300 return ip6_addr_cmp(&a1->address.ipv6, &a2->address.ipv6);
301 }
302 else if (a1->family == AF_INET && a2->family == AF_INET6) {
303 memset(&ha_local, 0, sizeof(ha_local));
304 memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2);
305 memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a1->address.ipv4.s_addr, 4);
306 return ip6_addr_cmp(&a2->address.ipv6, &ha_local.address.ipv6);
307 }
308 else if (a1->family == AF_INET6 && a2->family == AF_INET) {
309 memset(&ha_local, 0, sizeof(ha_local));
310 memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2);
311 memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a2->address.ipv4.s_addr, 4);
312 return ip6_addr_cmp(&a1->address.ipv6, &ha_local.address.ipv6);
313 }
314
315 return ERR;
316 }
317
318 /*
319 * variant of host_addr_cmp(). In addition it returns FALSE if family
320 * is zero in both a1 and a2.
321 */
host_addr_cmp2(struct host_addr * a1,struct host_addr * a2)322 int host_addr_cmp2(struct host_addr *a1, struct host_addr *a2)
323 {
324 struct host_addr ha_local;
325
326 if (a1->family == AF_INET && a2->family == AF_INET) {
327 if (a1->address.ipv4.s_addr == a2->address.ipv4.s_addr) return FALSE;
328 else if (a1->address.ipv4.s_addr > a2->address.ipv4.s_addr) return TRUE;
329 else return ERR;
330 }
331
332 if (a1->family == AF_INET6 && a2->family == AF_INET6) {
333 return ip6_addr_cmp(&a1->address.ipv6, &a2->address.ipv6);
334 }
335 else if (a1->family == AF_INET && a2->family == AF_INET6) {
336 if (a2->address.ipv6.s6_addr[10] == 0xff && a2->address.ipv6.s6_addr[11] == 0xff) {
337 memset(&ha_local, 0, sizeof(ha_local));
338 memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2);
339 memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a1->address.ipv4.s_addr, 4);
340 return ip6_addr_cmp(&a2->address.ipv6, &ha_local.address.ipv6);
341 }
342 }
343 else if (a1->family == AF_INET6 && a2->family == AF_INET) {
344 if (a1->address.ipv6.s6_addr[10] == 0xff && a1->address.ipv6.s6_addr[11] == 0xff) {
345 memset(&ha_local, 0, sizeof(ha_local));
346 memset((u_int8_t *)&ha_local.address.ipv6.s6_addr[10], 0xff, 2);
347 memcpy((u_int8_t *)&ha_local.address.ipv6.s6_addr[12], &a2->address.ipv4.s_addr, 4);
348 return ip6_addr_cmp(&a1->address.ipv6, &ha_local.address.ipv6);
349 }
350 }
351
352 if (!a1->family && !a2->family) return FALSE;
353
354 return ERR;
355 }
356
357 /*
358 * host_addr_mask_sa_cmp() checks whether s1 falls in a1/m1
359 * returns 0 if positive; 1 if negative; -1 to signal a generic error
360 * (e.g. unsupported family).
361 */
host_addr_mask_sa_cmp(struct host_addr * a1,struct host_mask * m1,struct sockaddr * s1)362 int host_addr_mask_sa_cmp(struct host_addr *a1, struct host_mask *m1, struct sockaddr *s1)
363 {
364 struct sockaddr_in *sa4 = (struct sockaddr_in *)s1;
365 struct sockaddr_in6 sa6_local;
366 int ret, j;
367
368 if (!a1 || !m1 || !s1) return ERR;
369 if (a1->family != s1->sa_family || a1->family != m1->family) return ERR;
370
371 if (a1->family == AF_INET) {
372 if ((sa4->sin_addr.s_addr & m1->mask.m4) == a1->address.ipv4.s_addr) return FALSE;
373 else return TRUE;
374 }
375 else if (a1->family == AF_INET6) {
376 memcpy(&sa6_local, s1, sizeof(struct sockaddr));
377 for (j = 0; j < 16; j++) sa6_local.sin6_addr.s6_addr[j] &= m1->mask.m6[j];
378 ret = ip6_addr_cmp(a1, &sa6_local.sin6_addr);
379 if (!ret) return FALSE;
380 else return TRUE;
381 }
382
383 return ERR;
384 }
385
386 /*
387 * host_addr_mask_cmp() checks whether a2 falls in a1/m1
388 * returns 0 if positive; 1 if negative; -1 to signal a generic error
389 * (e.g. unsupported family).
390 */
host_addr_mask_cmp(struct host_addr * a1,struct host_mask * m1,struct host_addr * a2)391 int host_addr_mask_cmp(struct host_addr *a1, struct host_mask *m1, struct host_addr *a2)
392 {
393 struct host_addr ha_local;
394 int ret, j;
395
396 if (!a1 || !m1 || !a2) return ERR;
397 if (a1->family != a2->family || a1->family != m1->family) return ERR;
398
399 if (a1->family == AF_INET) {
400 if ((a2->address.ipv4.s_addr & m1->mask.m4) == a1->address.ipv4.s_addr) return FALSE;
401 else return TRUE;
402 }
403 else if (a1->family == AF_INET6) {
404 memcpy(&ha_local, a2, sizeof(struct host_addr));
405 for (j = 0; j < 16; j++) ha_local.address.ipv6.s6_addr[j] &= m1->mask.m6[j];
406 ret = ip6_addr_cmp(&a1->address.ipv6, &ha_local.address.ipv6);
407 if (!ret) return FALSE;
408 else return TRUE;
409 }
410
411 return ERR;
412 }
413
414 /*
415 * raw_to_sa() converts a supported family address into a sockaddr
416 * structure
417 */
raw_to_sa(struct sockaddr * sa,u_char * src,u_int16_t port,u_int8_t v4v6)418 unsigned int raw_to_sa(struct sockaddr *sa, u_char *src, u_int16_t port, u_int8_t v4v6)
419 {
420 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
421 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
422
423 if (v4v6 == AF_INET) {
424 sa->sa_family = AF_INET;
425 memcpy(&sa4->sin_addr.s_addr, src, 4);
426 sa4->sin_port = port;
427 return sizeof(struct sockaddr_in);
428 }
429
430 if (v4v6 == AF_INET6) {
431 sa->sa_family = AF_INET6;
432 ip6_addr_cpy(&sa6->sin6_addr, src);
433 sa6->sin6_port = port;
434 return sizeof(struct sockaddr_in6);
435 }
436
437 memset(sa, 0, sizeof(struct sockaddr));
438
439 return FALSE;
440 }
441
442 /*
443 * raw_to_addr() converts a supported family address into a host_addr
444 * structure
445 */
raw_to_addr(struct host_addr * ha,u_char * src,u_int8_t v4v6)446 unsigned int raw_to_addr(struct host_addr *ha, u_char *src, u_int8_t v4v6)
447 {
448 if (v4v6 == AF_INET) {
449 ha->family = AF_INET;
450 memcpy(&ha->address.ipv4, src, 4);
451 return ha->family;
452 }
453
454 if (v4v6 == AF_INET6) {
455 ha->family = AF_INET6;
456 ip6_addr_cpy(&ha->address.ipv6, src);
457 return ha->family;
458 }
459
460 memset(ha, 0, sizeof(struct host_addr));
461
462 return FALSE;
463 }
464
465 /*
466 * sa_to_str() converts a supported family address into a string
467 */
sa_to_str(char * str,int len,const struct sockaddr * sa)468 unsigned int sa_to_str(char *str, int len, const struct sockaddr *sa)
469 {
470 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
471 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
472 char sep[] = ":";
473 int off;
474
475 if (len >= INET6_ADDRSTRLEN) {
476 if (sa->sa_family == AF_INET) {
477 inet_ntop(AF_INET, &sa4->sin_addr.s_addr, str, INET6_ADDRSTRLEN);
478
479 if (len >= (INET6_ADDRSTRLEN + PORT_STRLEN + 1) && sa4->sin_port) {
480 off = strlen(str);
481 snprintf(str + off, len - off, "%s", sep);
482
483 off = strlen(str);
484 snprintf(str + off, len - off, "%u", ntohs(sa4->sin_port));
485 }
486
487 return sa->sa_family;
488 }
489
490 if (sa->sa_family == AF_INET6) {
491 inet_ntop(AF_INET6, &sa6->sin6_addr, str, INET6_ADDRSTRLEN);
492
493 if (sa6->sin6_port) {
494 off = strlen(str);
495 snprintf(str + off, len - off, "%s", sep);
496
497 off = strlen(str);
498 snprintf(str + off, len - off, "%u", ntohs(sa6->sin6_port));
499 }
500
501 return sa->sa_family;
502 }
503 }
504
505 memset(str, 0, len);
506
507 return FALSE;
508 }
509
sa_to_port(int * port,const struct sockaddr * sa)510 unsigned int sa_to_port(int *port, const struct sockaddr *sa)
511 {
512 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
513 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
514
515 if (!port) return FALSE;
516
517 if (sa->sa_family == AF_INET) {
518 (*port) = ntohs(sa4->sin_port);
519 return sa->sa_family;
520 }
521
522 if (sa->sa_family == AF_INET6) {
523 (*port) = ntohs(sa6->sin6_port);
524 return sa->sa_family;
525 }
526
527 (*port) = 0;
528
529 return FALSE;
530 }
531
532 /*
533 * pm_htonl6(): same as htonl() for IPv6 addresses; no checks are done
534 * on the length of the buffer.
535 */
pm_htonl6(void * addr)536 void *pm_htonl6(void *addr)
537 {
538 register u_int32_t *ptr = addr;
539 static u_int32_t buf[4];
540 u_int8_t chunk;
541
542 for (chunk = 0; chunk < 4; chunk++) buf[chunk] = htonl(ptr[chunk]);
543
544 return buf;
545 }
546
547 /*
548 * pm_ntohl6(): same as ntohl() for IPv6 addresses; no checks are done
549 * on the length of the buffer.
550 */
pm_ntohl6(void * addr)551 void *pm_ntohl6(void *addr)
552 {
553 register u_int32_t *ptr = addr;
554 static u_int32_t buf[4];
555 u_int8_t chunk;
556
557 for (chunk = 0; chunk < 4; chunk++) buf[chunk] = ntohl(ptr[chunk]);
558
559 return buf;
560 }
561
562 /*
563 * ip6_addr_cmp(): compare two IPv6 addresses; returns 0 if they match,
564 * 1 if the first not matching chunk of addr1 is found to be greater than
565 * addr2; -1 on the contrary.
566 */
ip6_addr_cmp(void * addr1,void * addr2)567 int ip6_addr_cmp(void *addr1, void *addr2)
568 {
569 register u_int32_t *ptr1 = addr1, *ptr2 = addr2;
570 int chunk;
571
572 for (chunk = 0; chunk < 4; chunk++) {
573 if (ptr1[chunk] == ptr2[chunk]) continue;
574 else {
575 if (ptr1[chunk] > ptr2[chunk]) return TRUE;
576 else return ERR;
577 }
578 }
579
580 return FALSE;
581 }
582
583 /*
584 * ip6_addr_cpy(): copy of a *src IPv6 address into a *dst buffer.
585 */
ip6_addr_cpy(void * dst,void * src)586 void ip6_addr_cpy(void *dst, void *src)
587 {
588 register u_int32_t *ptrs = src, *ptrd = dst;
589 int chunk;
590
591 for (chunk = 0; chunk < 4; chunk++)
592 ptrd[chunk] = ptrs[chunk];
593 }
594
595 /*
596 * ip6_addr_32bit_cpy(): copy of arbitrary 32bit IPv6 address chunks
597 */
ip6_addr_32bit_cpy(void * dst,void * src,int dstart,int sstart,int send)598 void ip6_addr_32bit_cpy(void *dst, void *src, int dstart, int sstart, int send)
599 {
600 register u_int32_t *ptrs = src, *ptrd = dst;
601 int schunk, dchunk;
602
603 for (schunk = sstart, dchunk = dstart; schunk <= send; schunk++, dchunk++)
604 ptrd[dchunk] = ptrs[schunk];
605 }
606
etheraddr_string(const u_char * ep,char * buf)607 void etheraddr_string(const u_char *ep, char *buf)
608 {
609 u_int i, j;
610 char *cp;
611
612 cp = buf;
613 if ((j = *ep >> 4) != 0)
614 *cp++ = hex[j];
615 else
616 *cp++ = '0';
617
618 *cp++ = hex[*ep++ & 0xf];
619
620 for (i = 5; (int)--i >= 0;) {
621 *cp++ = ':';
622 if ((j = *ep >> 4) != 0)
623 *cp++ = hex[j];
624 else
625 *cp++ = '0';
626
627 *cp++ = hex[*ep++ & 0xf];
628 }
629
630 *cp = '\0';
631 }
632
633 /*
634 * string_etheraddr() writes the content of *asc in *addr (which has
635 * to be ETH_ADDR_LEN long). TRUE is returned if any failure occurs;
636 * TRUE if the routine completes the job successfully
637 */
string_etheraddr(const char * asc,u_char * addr)638 int string_etheraddr(const char *asc, u_char *addr)
639 {
640 int cnt;
641
642 for (cnt = 0; cnt < 6; ++cnt) {
643 unsigned int number;
644 char ch;
645
646 ch = tolower (*asc++);
647 if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f'))
648 return TRUE;
649 number = isdigit (ch) ? (ch - '0') : (ch - 'a' + 10);
650
651 ch = tolower(*asc);
652 if ((cnt < 5 && ch != ':') || (cnt == 5 && ch != '\0' && !isspace (ch))) {
653 ++asc;
654 if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f'))
655 return TRUE;
656 number <<= 4;
657 number += isdigit (ch) ? (ch - '0') : (ch - 'a' + 10);
658 ch = *asc;
659 if (cnt < 5 && ch != ':')
660 return TRUE;
661 }
662
663 /* Store result. */
664 addr[cnt] = (unsigned char) number;
665
666 /* Skip ':'. */
667 ++asc;
668 }
669
670 return FALSE;
671 }
672
673 /*
674 * pm_htonll(): similar to htonl() for 64 bits integers; no checks are done
675 * on the length of the buffer.
676 */
pm_htonll(u_int64_t addr)677 u_int64_t pm_htonll(u_int64_t addr)
678 {
679 #if defined IM_LITTLE_ENDIAN
680 u_int64_t buf;
681
682 u_int32_t *x = (u_int32_t *)(void *) &addr;
683 u_int32_t *y = (u_int32_t *)(void *) &buf;
684
685 y[0] = htonl(x[1]);
686 y[1] = htonl(x[0]);
687
688 return buf;
689 #else
690 return addr;
691 #endif
692 }
693
694 /*
695 * pm_ntohll(): similar to ntohl() for 64 bits integers; no checks are done
696 * on the length of the buffer.
697 */
pm_ntohll(u_int64_t addr)698 u_int64_t pm_ntohll(u_int64_t addr)
699 {
700 #if defined IM_LITTLE_ENDIAN
701 static u_int64_t buf;
702
703 buf = ((u_int64_t) ntohl(addr & 0xFFFFFFFFLLU)) << 32;
704 buf |= ntohl((addr & 0xFFFFFFFF00000000LLU) >> 32);
705
706 return buf;
707 #else
708 return addr;
709 #endif
710 }
711
712 /*
713 * is_multicast(): determines whether the supplied IPv4/IPv6 address is a
714 * multicast address or not.
715 */
is_multicast(struct host_addr * a)716 int is_multicast(struct host_addr *a)
717 {
718 if (!a) return FALSE;
719
720 if (a->family == AF_INET) {
721 if (IS_IPV4_MULTICAST(a->address.ipv4.s_addr)) return a->family;
722 else return FALSE;
723 }
724
725 if (a->family == AF_INET6) {
726 if (IS_IPV6_MULTICAST(&a->address.ipv6)) return a->family;
727 else return FALSE;
728 }
729
730 return FALSE;
731 }
732
733 /*
734 * is_any(): determines whether the supplied IPv4/IPv6 address is a
735 * 0.0.0.0 IPv4 or :: IPv6 address or not.
736 */
is_any(struct host_addr * a)737 int is_any(struct host_addr *a)
738 {
739 struct host_addr empty_host_addr;
740
741 if (!a) return FALSE;
742
743 memset(&empty_host_addr, 0, sizeof(empty_host_addr));
744
745 if (a->family == AF_INET) {
746 if (!memcmp(&empty_host_addr.address.ipv4, &a->address.ipv4, 4)) return a->family;
747 else return FALSE;
748 }
749
750 if (a->family == AF_INET6) {
751 if (!memcmp(&empty_host_addr.address.ipv6, &a->address.ipv6, 16)) return a->family;
752 else return FALSE;
753 }
754
755 return FALSE;
756 }
757
758 /*
759 * clean_sin_addr(): cleans the IP address from the pointed sockaddr structure
760 */
clean_sin_addr(struct sockaddr * sa)761 void clean_sin_addr(struct sockaddr *sa)
762 {
763 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
764 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
765
766 if (sa->sa_family == AF_INET) sa4->sin_addr.s_addr = 0;
767 if (sa->sa_family == AF_INET6) memset(&sa6->sin6_addr, 0, 16);
768 }
769
770 #if defined ENABLE_PLABEL
771 /*
772 * label_to_addr() converts a label into a supported family address
773 */
label_to_addr(const char * label,struct host_addr * a,int len)774 unsigned int label_to_addr(const char *label, struct host_addr *a, int len)
775 {
776 strlcpy(a->address.plabel, label, len);
777 a->family = AF_PLABEL;
778
779 return FALSE;
780 }
781 #endif
782
783 /*
784 * ipv4_mapped_to_ipv4() converts a label into a supported family address
785 */
ipv4_mapped_to_ipv4(struct sockaddr_storage * sas)786 void ipv4_mapped_to_ipv4(struct sockaddr_storage *sas)
787 {
788 struct sockaddr_storage sas_local;
789 struct sockaddr *sa = (struct sockaddr *) sas;
790 struct sockaddr_in *sa4 = (struct sockaddr_in *) sas;
791 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sas;
792
793 if (sa->sa_family != AF_INET6 || !IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) return;
794
795 memcpy(&sas_local, sas, sizeof(struct sockaddr_storage));
796 memset(sas, 0, sizeof(struct sockaddr_storage));
797 sa6 = (struct sockaddr_in6 *) &sas_local;
798 sa->sa_family = AF_INET;
799 memcpy(&sa4->sin_addr, (u_int8_t *) &sa6->sin6_addr+12, 4);
800 sa4->sin_port = sa6->sin6_port;
801 }
802
ipv4_to_ipv4_mapped(struct sockaddr_storage * sas)803 void ipv4_to_ipv4_mapped(struct sockaddr_storage *sas)
804 {
805 struct sockaddr_storage sas_local;
806 struct sockaddr *sa = (struct sockaddr *) sas;
807 struct sockaddr_in *sa4 = (struct sockaddr_in *) sas;
808 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sas;
809 static u_int16_t ffff = 0xFFFF;
810
811 if (sa->sa_family != AF_INET) return;
812
813 memcpy(&sas_local, sas, sizeof(struct sockaddr_storage));
814 memset(sas, 0, sizeof(struct sockaddr_storage));
815 sa4 = (struct sockaddr_in *) &sas_local;
816 sa->sa_family = AF_INET6;
817 memcpy((u_int8_t *) &sa6->sin6_addr+10, &ffff, 2);
818 memcpy((u_int8_t *) &sa6->sin6_addr+12, &sa4->sin_addr, 4);
819 sa6->sin6_port = sa4->sin_port;
820 }
821
etype_to_af(u_int16_t etype)822 u_int8_t etype_to_af(u_int16_t etype)
823 {
824 if (etype == ETHERTYPE_IP) return AF_INET;
825 else if (etype == ETHERTYPE_IPV6) return AF_INET6;
826
827 return FALSE;
828 }
829
af_to_etype(u_int8_t af)830 u_int16_t af_to_etype(u_int8_t af)
831 {
832 if (af == AF_INET) return ETHERTYPE_IP;
833 else if (af == AF_INET6) return ETHERTYPE_IPV6;
834
835 return FALSE;
836 }
837
addr_hash(struct host_addr * ha,u_int32_t modulo)838 u_int32_t addr_hash(struct host_addr *ha, u_int32_t modulo)
839 {
840 u_int32_t val = 0;
841
842 if (ha->family == AF_INET) {
843 val = jhash_1word(ha->address.ipv4.s_addr, 0);
844 }
845 else if (ha->family == AF_INET6) {
846 u_int32_t a, b, c;
847
848 memcpy(&a, &ha->address.ipv6.s6_addr[4], 4);
849 memcpy(&b, &ha->address.ipv6.s6_addr[8], 4);
850 memcpy(&c, &ha->address.ipv6.s6_addr[12], 4);
851 val = jhash_3words(a, b, c, 0);
852 }
853
854 return (val % modulo);
855 }
856
857 // XXX: basic implementation, to be improved
addr_port_hash(struct host_addr * ha,u_int16_t port,u_int32_t modulo)858 u_int32_t addr_port_hash(struct host_addr *ha, u_int16_t port, u_int32_t modulo)
859 {
860 u_int32_t val = 0;
861
862 if (ha->family == AF_INET) {
863 val = jhash_2words(ha->address.ipv4.s_addr, port, 0);
864 }
865 else if (ha->family == AF_INET6) {
866 u_int32_t a, b;
867
868 memcpy(&a, &ha->address.ipv6.s6_addr[8], 4);
869 memcpy(&b, &ha->address.ipv6.s6_addr[12], 4);
870 val = jhash_3words(port, a, b, 0);
871 }
872
873 return (val % modulo);
874 }
875
sa_has_family(struct sockaddr * sa)876 u_int16_t sa_has_family(struct sockaddr *sa)
877 {
878 return sa->sa_family;
879 }
880