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