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