1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *   Configuration file parser for IP-Addresse ipv4 and ipv6
21  *
22  *     Written by Meno Abels, June MMIV
23  *
24  */
25 
26 
27 #include "bacula.h"
28 #ifdef HAVE_ARPA_NAMESER_H
29 #include <arpa/nameser.h>
30 #endif
31 #ifdef HAVE_RESOLV_H
32 //#include <resolv.h>
33 #endif
34 
35 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
36                 const char *hostname_str, const char *port_str, char *buf, int buflen);
37 
38 
IPADDR(const IPADDR & src)39 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
40 {
41   memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
42   saddr  = &saddrbuf.dontuse;
43   saddr4 = &saddrbuf.dontuse4;
44 #ifdef HAVE_IPV6
45   saddr6 = &saddrbuf.dontuse6;
46 #endif
47 }
48 
IPADDR(int af)49 IPADDR::IPADDR(int af) : type(R_EMPTY)
50 {
51 #ifdef HAVE_IPV6
52   if (!(af == AF_INET6 || af == AF_INET)) {
53      Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
54   }
55 #else
56   if (af != AF_INET) {
57      Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
58   }
59 #endif
60   memset(&saddrbuf, 0, sizeof(saddrbuf));
61   saddr  = &saddrbuf.dontuse;
62   saddr4 = &saddrbuf.dontuse4;
63 #ifdef HAVE_IPV6
64   saddr6 = &saddrbuf.dontuse6;
65 #endif
66   saddr->sa_family = af;
67   if (af  == AF_INET) {
68      saddr4->sin_port = 0xffff;
69   }
70 #ifdef HAVE_IPV6
71   else {
72      saddr6->sin6_port = 0xffff;
73   }
74 #endif
75 #ifdef HAVE_SA_LEN
76 #ifdef HAVE_IPV6
77   saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
78 #else
79   saddr->sa_len = sizeof(sockaddr_in);
80 #endif
81 #endif
82    set_addr_any();
83 }
84 
set_type(i_type o)85 void IPADDR::set_type(i_type o)
86 {
87    type = o;
88 }
89 
get_type()90 IPADDR::i_type IPADDR::get_type() const
91 {
92    return type;
93 }
94 
get_port_net_order()95 unsigned short IPADDR::get_port_net_order() const
96 {
97    unsigned short port = 0;
98    if (saddr->sa_family == AF_INET) {
99       port = saddr4->sin_port;
100    }
101 #ifdef HAVE_IPV6
102    else {
103       port = saddr6->sin6_port;
104    }
105 #endif
106     return port;
107 }
108 
set_port_net(unsigned short port)109 void IPADDR::set_port_net(unsigned short port)
110 {
111    if (saddr->sa_family == AF_INET) {
112       saddr4->sin_port = port;
113    }
114 #ifdef HAVE_IPV6
115    else {
116       saddr6->sin6_port = port;
117    }
118 #endif
119 }
120 
get_family()121 int IPADDR::get_family() const
122 {
123     return saddr->sa_family;
124 }
125 
126 /*
127  * Note, this returns the address of the socket structure
128  *  not the address of the socket address.
129  *  This socket address is a union of the different types
130  *  of sockets (IPv4, ...) available, so it is portable.
131  */
get_sockaddr()132 struct sockaddr *IPADDR::get_sockaddr()
133 {
134    return saddr;
135 }
136 
get_sockaddr_len()137 int IPADDR::get_sockaddr_len()
138 {
139 #ifdef HAVE_IPV6
140    return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
141 #else
142    return sizeof(*saddr4);
143 #endif
144 }
copy_addr(IPADDR * src)145 void IPADDR::copy_addr(IPADDR *src)
146 {
147    if (saddr->sa_family == AF_INET) {
148       saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
149    }
150 #ifdef HAVE_IPV6
151    else if (saddr->sa_family == AF_INET6) {
152       saddr6->sin6_addr = src->saddr6->sin6_addr;
153    }
154 #endif
155 }
156 
157 #ifdef NEED_IN6ADDR_ANY
158 /* The <netinet/in.h> header shall declare the following external variable
159  * On Oses such as Solaris, it requires to define also XPG4_2 and EXTENSIONS
160  * and we have no real idea on what it will change.
161  */
162 extern const struct in6_addr in6addr_any;
163 #endif
164 
set_addr_any()165 void IPADDR::set_addr_any()
166 {
167    if (saddr->sa_family == AF_INET) {
168       saddr4->sin_addr.s_addr = INADDR_ANY;
169    }
170 #ifdef HAVE_IPV6
171    else if (saddr->sa_family == AF_INET6) {
172      saddr6->sin6_addr = in6addr_any;
173    }
174 #endif
175 }
176 
set_addr4(struct in_addr * ip4)177 void IPADDR::set_addr4(struct in_addr *ip4)
178 {
179    if (saddr->sa_family != AF_INET) {
180       Emsg1(M_ERROR_TERM, 0, _("You tried to assign a ipv6 address to an ipv4(%d)\n"), saddr->sa_family);
181    }
182    saddr4->sin_addr = *ip4;
183 }
184 
185 #ifdef HAVE_IPV6
set_addr6(struct in6_addr * ip6)186 void IPADDR::set_addr6(struct in6_addr *ip6)
187 {
188    if (saddr->sa_family != AF_INET6) {
189       Emsg1(M_ERROR_TERM, 0, _("You tried to assign an ipv4 address to an ipv6(%d)\n"), saddr->sa_family);
190    }
191    saddr6->sin6_addr = *ip6;
192 }
193 #endif
194 
get_address(char * outputbuf,int outlen)195 const char *IPADDR::get_address(char *outputbuf, int outlen)
196 {
197    outputbuf[0] = '\0';
198 #ifdef HAVE_INET_NTOP
199 # ifdef HAVE_IPV6
200    inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
201               (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
202               outputbuf, outlen);
203 # else
204    inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
205 # endif
206 #else
207    bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
208 #endif
209    return outputbuf;
210 }
211 
build_address_str(char * buf,int blen)212 const char *IPADDR::build_address_str(char *buf, int blen)
213 {
214    char tmp[1024];
215    if (get_family() == AF_INET) {
216       bsnprintf(buf, blen, "%s:%hu ",
217                 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
218    } else {
219       bsnprintf(buf, blen, "[%s]:%hu ",
220                 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
221    }
222    return buf;
223 }
224 
build_addresses_str(dlist * addrs,char * buf,int blen)225 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
226 {
227    if (!addrs || addrs->size() == 0) {
228       bstrncpy(buf, "", blen);
229       return buf;
230    }
231    char *work = buf;
232    IPADDR *p;
233    foreach_dlist(p, addrs) {
234       char tmp[1024];
235       int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
236       if (len < 0)
237          break;
238       work += len;
239       blen -= len;
240    }
241    return buf;
242 }
243 
get_first_address(dlist * addrs,char * outputbuf,int outlen)244 const char *get_first_address(dlist *addrs, char *outputbuf, int outlen)
245 {
246    IPADDR *addr = (IPADDR *)(addrs->first());
247    if (addr) {
248       return addr->get_address(outputbuf, outlen);
249    } else {
250       return _("N/A");
251    }
252 }
253 
get_first_port_net_order(dlist * addrs)254 int get_first_port_net_order(dlist *addrs)
255 {
256    if (!addrs) {
257       return 0;
258    } else {
259       IPADDR *addr = (IPADDR *)(addrs->first());
260       if (addr) {
261          return addr->get_port_net_order();
262       } else {
263          return 0;
264       }
265    }
266 }
267 
get_first_port_host_order(dlist * addrs)268 int get_first_port_host_order(dlist *addrs)
269 {
270    if (!addrs) {
271       return 0;
272    } else {
273       IPADDR *addr = (IPADDR *)(addrs->first());
274       if (addr) {
275          return addr->get_port_host_order();
276       } else {
277          return 0;
278       }
279    }
280 }
281 
init_default_addresses(dlist ** addr_list,int port)282 void init_default_addresses(dlist **addr_list, int port)
283 {
284    char buf[1024];
285    unsigned short sport = port;
286    if (!add_address(addr_list, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf, sizeof(buf))) {
287       Emsg1(M_ERROR_TERM, 0, _("Can't add default IPv4 address (%s)\n"), buf);
288    }
289    Dmsg1(20, "Initaddr %s\n", build_addresses_str(*addr_list, buf, sizeof(buf)));
290 
291 }
292 
add_address(dlist ** out,IPADDR::i_type type,unsigned short defaultport,int family,const char * hostname_str,const char * port_str,char * buf,int buflen)293 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
294                 const char *hostname_str, const char *port_str, char *buf, int buflen)
295 {
296    IPADDR *iaddr;
297    IPADDR *jaddr;
298    dlist *hostaddrs;
299    unsigned short port;
300    IPADDR::i_type intype = type;
301 
302    buf[0] = 0;
303    dlist *addrs = (dlist *)(*(out));
304    if (!addrs) {
305       IPADDR *tmp = 0;
306       addrs = *out = New(dlist(tmp, &tmp->link));
307    }
308 
309    type = (type == IPADDR::R_SINGLE_PORT ||
310            type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
311    if (type != IPADDR::R_DEFAULT) {
312       IPADDR *def = 0;
313       foreach_dlist(iaddr, addrs) {
314          if (iaddr->get_type() == IPADDR::R_DEFAULT) {
315             def = iaddr;
316          } else if (iaddr->get_type() != type) {
317             bsnprintf(buf, buflen,
318                       _("Old style addresses cannot be mixed with new style. Try removing Port=nnn."));
319             Dmsg1(20, "%s\n", buf);
320             return 0;
321          }
322       }
323       if (def) {
324          addrs->remove(def);
325          delete def;
326       }
327    }
328 
329    if (!port_str || port_str[0] == '\0') {
330       port = defaultport;
331    } else {
332       int pnum = atol(port_str);
333       if (0 < pnum && pnum < 0xffff) {
334          port = htons(pnum);
335       } else {
336          struct servent *s = getservbyname(port_str, "tcp");
337          if (s) {
338             port = s->s_port;
339          } else {
340             bsnprintf(buf, buflen, _("Cannot resolve service(%s)"), port_str);
341             Dmsg1(20, "%s\n", buf);
342             return 0;
343          }
344       }
345    }
346 
347    const char *myerrstr;
348    hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
349    if (!hostaddrs) {
350       bsnprintf(buf, buflen, _("Cannot resolve hostname(%s) %s"), hostname_str,
351                 myerrstr);
352       Dmsg1(20, "%s\n", buf);
353       return 0;
354    }
355 
356    if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
357       IPADDR *addr;
358       if (addrs->size()) {
359          addr = (IPADDR *)addrs->first();
360       } else {
361          addr = New(IPADDR(family));
362          addr->set_type(type);
363          addr->set_port_net(defaultport);
364          addr->set_addr_any();
365          addrs->append(addr);
366       }
367       if (intype == IPADDR::R_SINGLE_PORT) {
368          addr->set_port_net(port);
369       }
370       if (intype == IPADDR::R_SINGLE_ADDR) {
371          addr->copy_addr((IPADDR *)(hostaddrs->first()));
372       }
373    } else {
374       foreach_dlist(iaddr, hostaddrs) {
375          IPADDR *clone;
376          /* for duplicates */
377          foreach_dlist(jaddr, addrs) {
378             if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
379                 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
380                     iaddr->get_sockaddr_len()))
381                 {
382                goto skip;          /* no price */
383             }
384          }
385          clone = New(IPADDR(*iaddr));
386          clone->set_type(type);
387          clone->set_port_net(port);
388          addrs->append(clone);
389        skip:
390          continue;
391       }
392    }
393    free_addresses(hostaddrs);
394    return 1;
395 }
396 
397 /*
398  *  Some IPv6 rules from Wikipedia:
399  *
400  *  For convenience, an IPv6 address may be abbreviated to shorter
401  *  notations by application of the following rules, where possible.
402  *
403  * 1.  One or more leading zeroes from any groups of hexadecimal
404  *     digits are removed; this is usually done to either all or none of
405  *     the leading zeroes.  For example, the group 0042 is converted to
406  *     42.
407  *
408  * 2.  Consecutive sections of zeroes are replaced with a double
409  *     colon (::).  The double colon may only be used once in an
410  *     address, as multiple use would render the address indeterminate.
411  *     RFC 5952 recommends that a double colon must not be used to
412  *     denote an omitted single section of zeroes.[39]
413  *
414  *   my tests
415  *   positiv
416  *   = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
417  *   = { ip = {
418  *         addr = 1.2.3.4; port = 1205; }
419  *     ipv4 = {
420  *         addr = 1.2.3.4; port = http; }
421  *     ipv6 = {
422  *       addr = 1.2.3.4;
423  *       port = 1205;
424  *     }
425  *     ip = {
426  *       addr = 1.2.3.4
427  *       port = 1205
428  *     }
429  *     ip = {
430  *       addr = 1.2.3.4
431  *     }
432  *     ip = {
433  *       addr = 2001:220:222::2
434  *     }
435  *     ip = {
436  *       addr = bluedot.thun.net
437  *     }
438  *   }
439  *
440  *   negativ
441  *   = { ip = { } }
442  *   = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
443  *   = { ipv4 { port = 4711 } }
444  */
store_addresses(LEX * lc,RES_ITEM * item,int index,int pass)445 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
446 {
447    int token;
448    enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
449    int exist;
450    char hostname_str[1024];
451    char port_str[128];
452    int family = 0;
453    char errmsg[1024];
454 
455 
456    token = lex_get_token(lc, T_SKIP_EOL);
457    if (token != T_BOB) {
458       scan_err1(lc, _("Expected a block to begin with { but got: %s"), lc->str);
459    }
460 
461    token = lex_get_token(lc, T_SKIP_EOL);
462    if (token == T_EOB) {
463       scan_err0(lc, _("Empty addr block is not allowed"));
464    }
465    do {
466       if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
467          scan_err1(lc, _("Expected a string but got: %s"), lc->str);
468       }
469       if (strcasecmp("ip", lc->str) == 0) {
470 #ifdef HAVE_IPV6
471          family = AF_INET6;
472 #else
473          family = AF_INET;
474 #endif
475       } else if (strcasecmp("ipv4", lc->str) == 0) {
476          family = AF_INET;
477       }
478 #ifdef HAVE_IPV6
479       else if (strcasecmp("ipv6", lc->str) == 0) {
480          family = AF_INET6;
481       } else {
482          scan_err1(lc, _("Expected a string [ip|ipv4|ipv6] but got: %s"), lc->str);
483       }
484 #else
485       else {
486          scan_err1(lc, _("Expected a string [ip|ipv4] but got: %s"), lc->str);
487       }
488 #endif
489       token = lex_get_token(lc, T_SKIP_EOL);
490       if (token != T_EQUALS) {
491          scan_err1(lc, _("Expected an equal = but got: %s"), lc->str);
492       }
493       token = lex_get_token(lc, T_SKIP_EOL);
494       if (token != T_BOB) {
495          scan_err1(lc, _("Expected a block to begin with { but got: %s"), lc->str);
496       }
497       token = lex_get_token(lc, T_SKIP_EOL);
498       exist = EMPTYLINE;
499       port_str[0] = hostname_str[0] = '\0';
500       do {
501          if (token != T_IDENTIFIER) {
502             scan_err1(lc, _("Expected an identifier [addr|port] but got: %s"), lc->str);
503          }
504          if (strcasecmp("port", lc->str) == 0) {
505             next_line = PORTLINE;
506             if (exist & PORTLINE) {
507                scan_err0(lc, _("Only one port per address block"));
508             }
509             exist |= PORTLINE;
510          } else if (strcasecmp("addr", lc->str) == 0) {
511             next_line = ADDRLINE;
512             if (exist & ADDRLINE) {
513                scan_err0(lc, _("Only one addr per address block"));
514             }
515             exist |= ADDRLINE;
516          } else {
517             scan_err1(lc, _("Expected a identifier [addr|port] but got: %s"), lc->str);
518          }
519          token = lex_get_token(lc, T_SKIP_EOL);
520          if (token != T_EQUALS) {
521             scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
522          }
523          token = lex_get_token(lc, T_SKIP_EOL);
524          switch (next_line) {
525          case PORTLINE:
526             if (!
527                 (token == T_UNQUOTED_STRING || token == T_NUMBER ||
528                  token == T_IDENTIFIER)) {
529                scan_err1(lc, _("Expected a number or a string but got: %s"), lc->str);
530             }
531             bstrncpy(port_str, lc->str, sizeof(port_str));
532             break;
533          case ADDRLINE:
534             if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
535                scan_err1(lc, _("Expected an IP number or a hostname but got: %s"),
536                          lc->str);
537             }
538             bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
539             break;
540          case EMPTYLINE:
541             scan_err0(lc, _("State machine mismatch"));
542             break;
543          }
544          token = lex_get_token(lc, T_SKIP_EOL);
545       } while (token == T_IDENTIFIER);
546       if (token != T_EOB) {
547          scan_err1(lc, _("Expected a end of block with } but got: %s"), lc->str);
548       }
549 
550       if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
551                htons(item->default_value), family, hostname_str, port_str,
552                errmsg, sizeof(errmsg))) {
553          scan_err3(lc, _("Cannot add hostname(%s) and port(%s) to addrlist (%s)"),
554                    hostname_str, port_str, errmsg);
555       }
556       token = scan_to_next_not_eol(lc);
557    } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
558    if (token != T_EOB) {
559       scan_err1(lc, _("Expected an end of block with } but got: %s"), lc->str);
560    }
561 }
562 
store_addresses_address(LEX * lc,RES_ITEM * item,int index,int pass)563 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
564 {
565    char errmsg[1024];
566    int token = lex_get_token(lc, T_SKIP_EOL);
567    if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
568       scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
569    }
570    if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_ADDR,
571                     htons(item->default_value), AF_INET, lc->str, 0,
572                     errmsg, sizeof(errmsg))) {
573       scan_err2(lc, _("Cannot add port (%s) to (%s)"), lc->str, errmsg);
574    }
575 }
576 
store_addresses_port(LEX * lc,RES_ITEM * item,int index,int pass)577 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
578 {
579    char errmsg[1024];
580    int token = lex_get_token(lc, T_SKIP_EOL);
581    if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
582       scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
583    }
584    if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
585                     htons(item->default_value), AF_INET, 0, lc->str,
586                     errmsg, sizeof(errmsg))) {
587       scan_err2(lc, _("Cannot add port (%s) to (%s)"), lc->str, errmsg);
588    }
589 }
590 
free_addresses(dlist * addrs)591 void free_addresses(dlist * addrs)
592 {
593    while (!addrs->empty()) {
594       IPADDR *ptr = (IPADDR*)addrs->first();
595       addrs->remove(ptr);
596       delete ptr;
597    }
598    delete addrs;
599 }
600 
sockaddr_get_port_net_order(const struct sockaddr * client_addr)601 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
602 {
603    if (client_addr->sa_family == AF_INET) {
604       return ((struct sockaddr_in *)client_addr)->sin_port;
605    }
606 #ifdef HAVE_IPV6
607    else {
608       return ((struct sockaddr_in6 *)client_addr)->sin6_port;
609    }
610 #endif
611    return -1;
612 }
613 
sockaddr_get_port(const struct sockaddr * client_addr)614 int sockaddr_get_port(const struct sockaddr *client_addr)
615 {
616    if (client_addr->sa_family == AF_INET) {
617       return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
618    }
619 #ifdef HAVE_IPV6
620    else {
621       return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
622    }
623 #endif
624    return -1;
625 }
626 
627 
sockaddr_to_ascii(const struct sockaddr * sa,int socklen,char * buf,int buflen)628 char *sockaddr_to_ascii(const struct sockaddr *sa, int socklen, char *buf, int buflen)
629 {
630 #ifdef HAVE_GETNAMEINFO
631   /* This is the more modern way of doing it */
632   char clienthost[NI_MAXHOST];
633   char clientservice[NI_MAXSERV];
634   int status = 1;
635   if (sa->sa_family == AF_INET) {
636      status = getnameinfo(sa, sizeof(sockaddr_in), clienthost, sizeof(clienthost),
637                  clientservice, sizeof(clientservice),
638                  NI_NUMERICHOST | NI_NUMERICSERV);
639   }
640 #ifdef HAVE_IPV6
641   else {
642      status = getnameinfo(sa, sizeof(sockaddr_in6), clienthost, sizeof(clienthost),
643                  clientservice, sizeof(clientservice),
644                  NI_NUMERICHOST | NI_NUMERICSERV);
645   }
646 #endif
647   if (status == 0) {
648      /* Enclose IPv6 in [] */
649      if (strchr(clienthost, ':') != NULL) {
650         bsnprintf(buf, buflen, "[%s]", clienthost);
651      } else {
652         bstrncpy(buf, clienthost, buflen);
653      }
654   } else {
655      bstrncpy(buf, "Hostname not found", buflen);
656   }
657 
658 #else
659 #ifdef HAVE_INET_NTOP
660    inet_ntop(sa->sa_family,
661 # ifdef HAVE_IPV6
662              sa->sa_family == AF_INET ?
663                  (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
664                  (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
665 # else
666                  (void*)&(((struct sockaddr_in*)sa)->sin_addr),
667 # endif /* HAVE_IPV6 */
668              buf, buflen);
669 #else
670    bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), buflen);
671 #endif
672 #endif
673    return buf;
674 }
675 
676 /*
677  * Remove duplicate IP addresses.
678  */
remove_duplicate_addresses(dlist * addr_list)679 void remove_duplicate_addresses(dlist *addr_list)
680 {
681    IPADDR *ipaddr, *next, *duplicate;
682    /*
683     * Remove any duplicate addresses.
684     */
685    for (ipaddr = (IPADDR *)addr_list->first(); ipaddr;
686         ipaddr = (IPADDR *)addr_list->next(ipaddr)) {
687       for (next = (IPADDR *)addr_list->next(ipaddr); next; ) {
688          duplicate = NULL;
689          if (ipaddr->get_sockaddr_len() == next->get_sockaddr_len() &&
690              memcmp(ipaddr->get_sockaddr(), next->get_sockaddr(),
691                     ipaddr->get_sockaddr_len()) == 0) {
692             duplicate = next;
693          }
694          next = (IPADDR *)addr_list->next(next);
695          if (duplicate) {
696             addr_list->remove(duplicate);  /* remove from list */
697             delete duplicate;              /* free it */
698          }
699       }
700    }
701 }
702 
703 #ifdef HAVE_OLD_SOCKOPT
inet_aton(const char * cp,struct in_addr * inp)704 int inet_aton(const char *cp, struct in_addr *inp)
705 {
706    struct in_addr inaddr;
707 
708    if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
709       inp->s_addr = inaddr.s_addr;
710       return 1;
711    }
712    return 0;
713 }
714 #endif
715