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