1 /* $Id$ */
2
3 /*
4 * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
5 * Copyright (c) 2013-2018 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
6 *
7 * The Tcpreplay Suite of tools is free software: you can redistribute it
8 * and/or modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or with the authors permission any later version.
11 *
12 * The Tcpreplay Suite 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 the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22 #include "defines.h"
23 #include "common.h"
24 #include "../../lib/sll.h"
25
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <stdlib.h>
33
34 #ifdef DEBUG
35 extern int debug;
36 #endif
37
38 #if defined HAVE_PCAP_VERSION && ! defined HAVE_WIN32
39 extern const char pcap_version[];
40 #endif
41
42 #define JUNIPER_FLAG_NO_L2 0x02 /* L2 header */
43 #define JUNIPER_FLAG_EXT 0x80 /* Juniper extensions present */
44 #define JUNIPER_PCAP_MAGIC "MGC"
45 /**
46 * Depending on what version of libpcap/WinPcap there are different ways to get
47 * the version of the libpcap/WinPcap library. This presents a unified way to
48 * get that information.
49 */
50 const char *
get_pcap_version(void)51 get_pcap_version(void)
52 {
53
54 #if defined HAVE_WINPCAP
55 static char ourver[255];
56 char *last, *version;
57 /* WinPcap returns a string like:
58 * WinPcap version 4.0 (packet.dll version 4.0.0.755), based on libpcap version 0.9.5
59 */
60 version = safe_strdup(pcap_lib_version());
61
62 strtok_r(version, " ", &last);
63 strtok_r(NULL, " ", &last);
64 strlcpy(ourver, strtok_r(NULL, " ", &last), 255);
65 safe_free(version);
66 return ourver;
67 #elif defined HAVE_PCAP_VERSION
68 return pcap_version;
69 #else
70 return pcap_lib_version();
71 #endif
72 }
73
74
75
76 /**
77 * returns the L2 protocol (IP, ARP, etc)
78 * or 0 for error
79 */
80 uint16_t
get_l2protocol(const u_char * pktdata,const uint32_t datalen,const int datalink)81 get_l2protocol(const u_char *pktdata, const uint32_t datalen, const int datalink)
82 {
83 uint16_t eth_hdr_offset = 0;
84
85 if (!pktdata || !datalen) {
86 errx(-1, "invalid l2 parameters: pktdata=0x%p len=%d",
87 pktdata, datalen);
88 return 0;
89 }
90
91 switch (datalink) {
92 case DLT_RAW:
93 if (datalen < 1)
94 return 0;
95 if ((pktdata[0] >> 4) == 4)
96 return ETHERTYPE_IP;
97 else if ((pktdata[0] >> 4) == 6)
98 return ETHERTYPE_IP6;
99 break;
100
101 case DLT_JUNIPER_ETHER:
102 if (datalen < 4)
103 return 0;
104
105 if (memcmp(pktdata, JUNIPER_PCAP_MAGIC, 3)) {
106 warnx("No Magic Number found during protocol lookup: %s (0x%x)",
107 pcap_datalink_val_to_description(datalink), datalink);
108 return 0;
109 }
110
111 if ((pktdata[3] & JUNIPER_FLAG_EXT) == JUNIPER_FLAG_EXT) {
112 if (datalen < 6)
113 return 0; /* datalen too short */
114
115 eth_hdr_offset = ntohs(*((uint16_t*)&pktdata[4]));
116 eth_hdr_offset += 6; /* MGC + flags + ext_total_len */
117 } else {
118 eth_hdr_offset = 4; /* MGC + flags (no header extensions) */
119 }
120 if ((pktdata[3] & JUNIPER_FLAG_NO_L2) == JUNIPER_FLAG_NO_L2) {
121 /* no L2 header present - eth_hdr_offset is actually IP offset */
122 uint32_t ip_hdr_offset = eth_hdr_offset;
123 if (datalen < ip_hdr_offset + 1)
124 return 0;
125 if ((pktdata[ip_hdr_offset] >> 4) == 4)
126 return ETHERTYPE_IP;
127 else if ((pktdata[ip_hdr_offset] >> 4) == 6)
128 return ETHERTYPE_IP6;
129 else
130 return 0;
131 }
132 /* fall through */
133 case DLT_EN10MB:
134 if ((size_t)datalen >= (sizeof(eth_hdr_t) + eth_hdr_offset)) {
135 eth_hdr_t *eth_hdr = (eth_hdr_t *)(pktdata + eth_hdr_offset);
136 uint16_t ether_type = ntohs(eth_hdr->ether_type);
137 uint16_t l2_len = sizeof(*eth_hdr) + eth_hdr_offset;
138 while (ether_type == ETHERTYPE_VLAN) {
139 if (datalen < l2_len + sizeof(vlan_hdr_t))
140 return 0;
141
142 vlan_hdr_t *vlan_hdr = (vlan_hdr_t*)(pktdata + l2_len);
143 ether_type = ntohs(vlan_hdr->vlan_tpid);
144 l2_len += sizeof(vlan_hdr_t);
145 }
146
147 return ether_type; /* yes, return it in host byte order */
148 }
149 break;
150
151 case DLT_PPP_SERIAL:
152 if ((size_t)datalen >= sizeof(struct tcpr_pppserial_hdr)) {
153 struct tcpr_pppserial_hdr *ppp = (struct tcpr_pppserial_hdr *)pktdata;
154 if (ntohs(ppp->protocol) == 0x0021)
155 return htons(ETHERTYPE_IP);
156 else
157 return ppp->protocol;
158 }
159 break;
160
161 case DLT_C_HDLC:
162 if ((size_t)datalen >= sizeof(hdlc_hdr_t)) {
163 hdlc_hdr_t *hdlc_hdr = (hdlc_hdr_t *)pktdata;
164 return hdlc_hdr->protocol;
165 }
166 break;
167
168 case DLT_LINUX_SLL:
169 if ((size_t)datalen >= sizeof(sll_hdr_t)) {
170 sll_hdr_t *sll_hdr = (sll_hdr_t *)pktdata;
171 return sll_hdr->sll_protocol;
172 }
173 break;
174
175 default:
176 errx(-1, "Unable to process unsupported DLT type: %s (0x%x)",
177 pcap_datalink_val_to_description(datalink), datalink);
178
179 }
180
181 return 0;
182 }
183
184 /**
185 * returns the length in number of bytes of the L2 header, or -1 on error
186 */
187 int
get_l2len(const u_char * pktdata,const int datalen,const int datalink)188 get_l2len(const u_char *pktdata, const int datalen, const int datalink)
189 {
190 int l2_len = 0;
191
192 assert(pktdata);
193 assert(datalen);
194
195 switch (datalink) {
196 case DLT_RAW:
197 /* pktdata IS the ip header! */
198 break;
199
200 case DLT_JUNIPER_ETHER:
201 if (datalen < 4) {
202 l2_len = -1;
203 break;
204 }
205
206 if (memcmp(pktdata, JUNIPER_PCAP_MAGIC, 3)) {
207 warnx("No Magic Number found during L2 lookup: %s (0x%x)",
208 pcap_datalink_val_to_description(datalink), datalink);
209 l2_len = -1;
210 break;
211 }
212
213 if ((pktdata[3] & JUNIPER_FLAG_NO_L2) == JUNIPER_FLAG_NO_L2) {
214 /* no L2 header present */
215 l2_len = 0;
216 break;
217 }
218
219 if ((pktdata[3] & JUNIPER_FLAG_EXT) == JUNIPER_FLAG_EXT) {
220 if (datalen < 6) {
221 /* datalen too short */
222 l2_len = -1;
223 break;
224 }
225 l2_len = ntohs(*((uint16_t*)&pktdata[4]));
226 l2_len += 6; /* MGC + flags + ext_total_len */
227 } else {
228 l2_len = 4; /* MGC + flags */
229 }
230 /* fall through */
231 case DLT_EN10MB:
232 if ((size_t)datalen >= sizeof(eth_hdr_t) + l2_len) {
233 uint16_t ether_type = ntohs(((eth_hdr_t*)(pktdata + l2_len))->ether_type);
234
235 l2_len += sizeof(eth_hdr_t);
236 while (ether_type == ETHERTYPE_VLAN) {
237 if ((size_t)datalen < sizeof(vlan_hdr_t) + l2_len) {
238 l2_len = -1;
239 break;
240 }
241 vlan_hdr_t *vlan_hdr = (vlan_hdr_t *)(pktdata + l2_len);
242 ether_type = ntohs(vlan_hdr->vlan_tpid);
243 l2_len += 4;
244 }
245 }
246
247 if (datalen < l2_len)
248 l2_len = -1;
249
250 break;
251
252 case DLT_PPP_SERIAL:
253 if (datalen >= 4) {
254 l2_len = 4;
255 }
256 break;
257
258 case DLT_C_HDLC:
259 if (datalen >= CISCO_HDLC_LEN) {
260 l2_len = CISCO_HDLC_LEN;
261 }
262 break;
263
264 case DLT_LINUX_SLL:
265 if (datalen >= SLL_HDR_LEN) {
266 l2_len = SLL_HDR_LEN;
267 }
268 break;
269
270 default:
271 errx(-1, "Unable to process unsupported DLT type: %s (0x%x)",
272 pcap_datalink_val_to_description(datalink), datalink);
273 return -1; /* we shouldn't get here */
274 }
275
276 return l2_len;
277 }
278
279 /**
280 * \brief returns a ptr to the ipv4 header + data or NULL if it's not IP
281 *
282 * we may use an extra buffer for the IP header (and above)
283 * on strictly aligned systems where the layer 2 header doesn't
284 * fall on a 4 byte boundary (like a standard Ethernet header)
285 *
286 * Note: you can cast the result as an ip_hdr_t, but you'll be able
287 * to access data above the header minus any stripped L2 data
288 */
289 const u_char *
get_ipv4(const u_char * pktdata,int datalen,int datalink,u_char ** newbuff)290 get_ipv4(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
291 {
292 const u_char *ip_hdr = NULL;
293 int l2_len = 0;
294 uint16_t proto;
295
296 assert(pktdata);
297 assert(datalen);
298 assert(*newbuff);
299
300 l2_len = get_l2len(pktdata, datalen, datalink);
301
302 /* sanity... datalen must be > l2_len + IP header len*/
303 if (l2_len < 0 || l2_len + TCPR_IPV4_H > datalen) {
304 dbg(1, "get_ipv4(): Layer 2 len > total packet len, hence no IP header");
305 return NULL;
306 }
307
308 proto = get_l2protocol(pktdata, datalen, datalink);
309
310 if (proto != ETHERTYPE_IP)
311 return NULL;
312
313 #ifdef FORCE_ALIGN
314 /*
315 * copy layer 3 and up to our temp packet buffer
316 * for now on, we have to edit the packetbuff because
317 * just before we send the packet, we copy the packetbuff
318 * back onto the pkt.data + l2len buffer
319 * we do all this work to prevent byte alignment issues
320 */
321 if (l2_len % sizeof(long)) {
322 memcpy(*newbuff, (pktdata + l2_len), (datalen - l2_len));
323 ip_hdr = *newbuff;
324 } else {
325
326 /* we don't have to do a memcpy if l2_len lands on a boundary */
327 ip_hdr = (pktdata + l2_len);
328 }
329 #else
330 /*
331 * on non-strict byte align systems, don't need to memcpy(),
332 * just point to l2len bytes into the existing buffer
333 */
334 ip_hdr = (pktdata + l2_len);
335 #endif
336
337 return ip_hdr;
338 }
339
340
341 /**
342 * \brief returns a ptr to the ipv6 header + data or NULL if it's not IP
343 *
344 * we may use an extra buffer for the IP header (and above)
345 * on strictly aligned systems where the layer 2 header doesn't
346 * fall on a 4 byte boundary (like a standard Ethernet header)
347 *
348 * Note: you can cast the result as an ip_hdr_t, but you'll be able
349 * to access data above the header minus any stripped L2 data
350 */
351 const u_char *
get_ipv6(const u_char * pktdata,int datalen,int datalink,u_char ** newbuff)352 get_ipv6(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
353 {
354 const u_char *ip6_hdr = NULL;
355 int l2_len = 0;
356 uint16_t proto;
357
358 assert(pktdata);
359 assert(datalen);
360 assert(*newbuff);
361
362 l2_len = get_l2len(pktdata, datalen, datalink);
363
364 /* sanity... datalen must be > l2_len + IP header len*/
365 if (l2_len < 0 || l2_len + TCPR_IPV6_H > datalen) {
366 dbg(1, "get_ipv6(): Layer 2 len > total packet len, hence no IPv6 header");
367 return NULL;
368 }
369
370 proto = get_l2protocol(pktdata, datalen, datalink);
371
372 if (proto != ETHERTYPE_IP6)
373 return NULL;
374
375 #ifdef FORCE_ALIGN
376 /*
377 * copy layer 3 and up to our temp packet buffer
378 * for now on, we have to edit the packetbuff because
379 * just before we send the packet, we copy the packetbuff
380 * back onto the pkt.data + l2len buffer
381 * we do all this work to prevent byte alignment issues
382 */
383 if (l2_len % sizeof(long)) {
384 memcpy(*newbuff, (pktdata + l2_len), (datalen - l2_len));
385 ip6_hdr = *newbuff;
386 } else {
387
388 /* we don't have to do a memcpy if l2_len lands on a boundary */
389 ip6_hdr = (pktdata + l2_len);
390 }
391 #else
392 /*
393 * on non-strict byte align systems, don't need to memcpy(),
394 * just point to l2len bytes into the existing buffer
395 */
396 ip6_hdr = (pktdata + l2_len);
397 #endif
398
399 return ip6_hdr;
400 }
401
402 /**
403 * \brief returns a pointer to the layer 4 header which is just beyond the IPv4 header
404 *
405 * If the packet is to short, returns NULL
406 */
407 void *
get_layer4_v4(const ipv4_hdr_t * ip_hdr,const int l3len)408 get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int l3len)
409 {
410 void *ptr;
411
412 assert(ip_hdr);
413
414 ptr = (u_char *)ip_hdr + (ip_hdr->ip_hl << 2);
415 /* make sure we don't jump over the end of the buffer */
416 if ((u_char *)ptr > ((u_char *)ip_hdr + l3len))
417 return NULL;
418
419 return ((void *)ptr);
420 }
421
422 /**
423 * returns a pointer to the layer 4 header which is just beyond the IPv6 header
424 * and any extension headers or NULL when there is none as in the case of
425 * v6 Frag or ESP header. Function is recursive.
426 */
427 void *
get_layer4_v6(const ipv6_hdr_t * ip6_hdr,const int l3len)428 get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
429 {
430 struct tcpr_ipv6_ext_hdr_base *next, *exthdr;
431 uint8_t proto;
432 uint32_t maxlen;
433 int min_len;
434
435 assert(ip6_hdr);
436
437 min_len = TCPR_IPV6_H + sizeof(struct tcpr_ipv6_ext_hdr_base);
438 if (l3len < min_len)
439 return NULL;
440
441 /* jump to the end of the IPv6 header */
442 next = (struct tcpr_ipv6_ext_hdr_base *)((u_char *)ip6_hdr + TCPR_IPV6_H);
443 proto = ip6_hdr->ip_nh;
444
445 while (1) {
446 dbgx(3, "Processing proto: 0x%hx", (uint16_t)proto);
447
448 switch (proto) {
449 /* recurse due to v6-in-v6, need to recast next as an IPv6 Header */
450 case TCPR_IPV6_NH_IPV6:
451 dbg(3, "recursing due to v6-in-v6");
452 return get_layer4_v6((ipv6_hdr_t *)next, l3len - min_len);
453 break;
454
455 /* loop again */
456 case TCPR_IPV6_NH_AH:
457 case TCPR_IPV6_NH_ROUTING:
458 case TCPR_IPV6_NH_DESTOPTS:
459 case TCPR_IPV6_NH_HBH:
460 dbgx(3, "Going deeper due to extension header 0x%02X", proto);
461 maxlen = l3len - (int)((u_char *)ip6_hdr - (u_char *)next);
462 exthdr = get_ipv6_next(next, maxlen);
463 if (exthdr == NULL)
464 return next;
465 proto = exthdr->ip_nh;
466 next = exthdr;
467 break;
468
469 /*
470 * Can't handle. Unparsable IPv6 fragment/encrypted data
471 */
472 case TCPR_IPV6_NH_FRAGMENT:
473 case TCPR_IPV6_NH_ESP:
474 return NULL;
475 break;
476
477 /*
478 * no further processing, either TCP, UDP, ICMP, etc...
479 */
480 default:
481 if (proto != ip6_hdr->ip_nh) {
482 dbgx(3, "Returning byte offset of this ext header: %u",
483 IPV6_EXTLEN_TO_BYTES(next->ip_len));
484 return (void *)((u_char *)next + IPV6_EXTLEN_TO_BYTES(next->ip_len));
485 } else {
486 dbgx(3, "%s", "Returning end of IPv6 Header");
487 return next;
488 }
489 break;
490 } /* switch */
491 } /* while */
492 }
493
494
495 /**
496 * returns the next payload or header of the current extension header
497 * returns NULL for none/ESP.
498 */
499 void *
get_ipv6_next(struct tcpr_ipv6_ext_hdr_base * exthdr,const int len)500 get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len)
501 {
502 int extlen = 0;
503 int maxlen;
504 void *ptr;
505 assert(exthdr);
506
507 maxlen = *((int*)((u_char *)exthdr + len));
508
509 dbgx(3, "Jumping to next IPv6 header. Processing 0x%02x", exthdr->ip_nh);
510 switch (exthdr->ip_nh) {
511 /* no further processing */
512 case TCPR_IPV6_NH_NO_NEXT:
513 case TCPR_IPV6_NH_ESP:
514 dbg(3, "No-Next or ESP... can't go any further...");
515 return NULL;
516 break;
517
518 /*
519 * fragment header is fixed size
520 * FIXME: Frag header has further ext headers (has a ip_nh field)
521 * but I don't support it because there's never a full L4 + payload beyond.
522 */
523 case TCPR_IPV6_NH_FRAGMENT:
524 dbg(3, "Looks like were a fragment header. Returning some frag'd data.");
525 ptr = (void *)((u_char *)exthdr + sizeof(struct tcpr_ipv6_frag_hdr));
526 if (*(int*)ptr > maxlen)
527 return NULL;
528 return ptr;
529 break;
530
531 /* all the rest require us to go deeper using the ip_len field */
532 case TCPR_IPV6_NH_IPV6:
533 case TCPR_IPV6_NH_ROUTING:
534 case TCPR_IPV6_NH_DESTOPTS:
535 case TCPR_IPV6_NH_HBH:
536 case TCPR_IPV6_NH_AH:
537 extlen = IPV6_EXTLEN_TO_BYTES(exthdr->ip_len);
538 dbgx(3, "Looks like we're an ext header (0x%hhx). Jumping %u bytes"
539 " to the next", exthdr->ip_nh, extlen);
540 ptr = (void *)((u_char *)exthdr + extlen);
541 if (*(int*)ptr > maxlen)
542 return NULL;
543 return ptr;
544 break;
545
546 default:
547 dbg(3, "Must not be a v6 extension header... returning self");
548 return (void *)exthdr;
549 break;
550 }
551 }
552
553 /**
554 * returns the protocol of the actual layer4 header by processing through
555 * the extension headers
556 */
557 uint8_t
get_ipv6_l4proto(const ipv6_hdr_t * ip6_hdr,const int l3len)558 get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int l3len)
559 {
560 u_char *ptr = (u_char *)ip6_hdr + TCPR_IPV6_H; /* jump to the end of the IPv6 header */
561 uint8_t proto;
562 struct tcpr_ipv6_ext_hdr_base *exthdr = NULL;
563
564 assert(ip6_hdr);
565
566 proto = ip6_hdr->ip_nh;
567 int l4len = l3len - TCPR_IPV6_H;
568 if (l4len < 0)
569 return proto;
570
571 while (TRUE) {
572 dbgx(3, "Processing next proto 0x%02X", proto);
573 switch (proto) {
574 /* no further processing for IPV6 types with nothing beyond them */
575 case TCPR_IPV6_NH_FRAGMENT:
576 case TCPR_IPV6_NH_ESP:
577 dbg(3, "No-Next or ESP... can't go any further...");
578 return proto;
579 break;
580
581 /* recurse */
582 case TCPR_IPV6_NH_IPV6:
583 dbg(3, "Recursing due to v6 in v6");
584 return get_ipv6_l4proto((ipv6_hdr_t *)ptr, l4len);
585 break;
586
587 /* loop again */
588 case TCPR_IPV6_NH_AH:
589 case TCPR_IPV6_NH_ROUTING:
590 case TCPR_IPV6_NH_DESTOPTS:
591 case TCPR_IPV6_NH_HBH:
592 dbgx(3, "Jumping to next extension header (0x%hhx)", proto);
593 exthdr = get_ipv6_next((struct tcpr_ipv6_ext_hdr_base *)ptr,
594 l4len);
595 if (exthdr == NULL)
596 return proto;
597 proto = exthdr->ip_nh;
598 l4len -= (u_char *)exthdr - ptr;
599 ptr = (u_char *)exthdr;
600 break;
601
602 /* should be TCP, UDP or the like */
603 default:
604 dbgx(3, "Selecting next L4 Proto as: 0x%02x", proto);
605 return proto;
606 } /* switch */
607 } /* while */
608 }
609
610 /**
611 * \brief Converts a human readable IPv4 address to a binary one
612 *
613 * stolen from LIBNET since I didn't want to have to deal with
614 * passing a libnet_t around. Returns 0xFFFFFFFF (255.255.255.255)
615 * on error
616 */
617 uint32_t
get_name2addr4(const char * hostname,bool dnslookup)618 get_name2addr4(const char *hostname, bool dnslookup)
619 {
620 struct in_addr addr;
621 #if ! defined HAVE_INET_ATON && defined HAVE_INET_ADDR
622 struct hostent *host_ent;
623 #endif
624
625 if (dnslookup) {
626 #ifdef HAVE_INET_ATON
627 if (inet_aton(hostname, &addr) != 1) {
628 return(0xffffffff);
629 }
630 #elif defined HAVE_INET_ADDR
631
632 if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
633 if (!(host_ent = gethostbyname(hostname))) {
634 warnx("unable to resolve %s: %s", hostname, strerror(errno));
635 /* this is actually 255.255.255.255 */
636 return (0xffffffff);
637 }
638
639 /* was: host_ent->h_length); */
640 memcpy(&addr.s_addr, host_ent->h_addr, sizeof(addr.s_addr));
641 }
642 #else
643 warn("Unable to support get_name2addr4 w/ resolve");
644 /* call ourselves recursively once w/o resolving the hostname */
645 return get_name2addr4(hostname, DNS_DONT_RESOLVE);
646 #endif
647 /* return in network byte order */
648 return (addr.s_addr);
649 } else {
650 /*
651 * We only want dots 'n decimals.
652 */
653 int i;
654 uint32_t m;
655
656 if (!isdigit(hostname[0])) {
657 warnx("Expected dotted-quad notation (%s) when DNS lookups are disabled",
658 hostname);
659 /* XXX - this is actually 255.255.255.255 */
660 return (-1);
661 }
662
663
664 m = 0;
665 for (i = 0; i < 4; i++) {
666 u_int val;
667
668 m <<= 8;
669 if (*hostname) {
670 val = 0;
671 while (*hostname && *hostname != '.') {
672 val *= 10;
673 val += *hostname - '0';
674 if (val > 255) {
675 dbgx(4, "value %d > 255 for dotted quad", val);
676 /* this is actually 255.255.255.255 */
677 return (-1);
678 }
679 hostname++;
680 }
681 m |= val;
682 if (*hostname) {
683 hostname++;
684 }
685 }
686 }
687 /* host byte order */
688 return (ntohl(m));
689 }
690 }
691
692 /**
693 * \brief Converts human readable IPv6 address to binary value
694 *
695 * Wrapper around inet_pton
696 * Returns 1 for valid, 0 for not parsable and -1 for system error.
697 * Does not support DNS.
698 */
699 int
get_name2addr6(const char * hostname,bool dnslookup,struct tcpr_in6_addr * addr)700 get_name2addr6(const char *hostname, bool dnslookup, struct tcpr_in6_addr *addr)
701 {
702 (void)dnslookup; /* prevent warning about unused arg */
703
704 #ifdef HAVE_INET_PTON
705 return inet_pton(AF_INET6, hostname, addr);
706 #else
707 #error "Unable to support get_name2addr6: Missing inet_pton() support."
708 #endif
709 return -1;
710 }
711
712 /**
713 * \brief Converts binary IPv4 address to a string.
714 *
715 * Generic wrapper around inet_ntop() and inet_ntoa() depending on whichever
716 * is available on your system. Does not support DNS.
717 */
718 const char *
get_addr2name4(const uint32_t ip,bool _U_ dnslookup)719 get_addr2name4(const uint32_t ip, bool _U_ dnslookup)
720 {
721 struct in_addr addr;
722 static char *new_string = NULL;
723
724 if (new_string == NULL)
725 new_string = (char *)safe_malloc(255);
726
727 new_string[0] = '\0';
728 addr.s_addr = ip;
729
730 #ifdef HAVE_INET_NTOP
731 if (inet_ntop(AF_INET, &addr, new_string, 255) == NULL) {
732 warnx("Unable to convert 0x%x to a string", ip);
733 new_string[0] = 0;
734 }
735 return new_string;
736 #elif defined HAVE_INET_NTOA
737 return inet_ntoa(&addr);
738 #else
739 #error "Unable to support get_addr2name4."
740 #endif
741 }
742
743 /**
744 * \brief Converts a IPv6 binary address to a string.a
745 *
746 * Does not support DNS.
747 */
748 const char *
get_addr2name6(const struct tcpr_in6_addr * addr,_U_ bool dnslookup)749 get_addr2name6(const struct tcpr_in6_addr *addr, _U_ bool dnslookup)
750 {
751 static char *new_string = NULL;
752
753 if (new_string == NULL)
754 new_string = (char *)safe_malloc(255);
755
756 new_string[0] = '\0';
757
758 #ifdef HAVE_INET_NTOP
759 if (inet_ntop(AF_INET6, addr, new_string, 255) == NULL) {
760 warn("Unable to convert addr to a string");
761 new_string[0] = 0;
762 }
763 return new_string;
764 #else
765 #error "Unable to support get_addr2name6."
766 #endif
767 }
768
769 /**
770 * \brief Converts the binary network address of a tcpr_cidr_t to a string
771 */
772 const char *
get_cidr2name(const tcpr_cidr_t * cidr_ptr,bool dnslookup)773 get_cidr2name(const tcpr_cidr_t *cidr_ptr, bool dnslookup)
774 {
775 if (cidr_ptr->family == AF_INET) {
776 return get_addr2name4(cidr_ptr->u.network, dnslookup);
777 } else if (cidr_ptr->family == AF_INET6) {
778 return get_addr2name6(&cidr_ptr->u.network6, dnslookup);
779 } else {
780 return NULL;
781 }
782 }
783
784