2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Configuration file parser for IP-Addresse ipv4 and ipv6
22 * Written by Meno Abels, June MMIV
28 #ifdef HAVE_ARPA_NAMESER_H
29 #include <arpa/nameser.h>
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);
39 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
41 memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
42 saddr = &saddrbuf.dontuse;
43 saddr4 = &saddrbuf.dontuse4;
45 saddr6 = &saddrbuf.dontuse6;
49 IPADDR::IPADDR(int af) : type(R_EMPTY)
52 if (!(af == AF_INET6 || af == AF_INET)) {
53 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
57 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
60 memset(&saddrbuf, 0, sizeof(saddrbuf));
61 saddr = &saddrbuf.dontuse;
62 saddr4 = &saddrbuf.dontuse4;
64 saddr6 = &saddrbuf.dontuse6;
66 saddr->sa_family = af;
68 saddr4->sin_port = 0xffff;
72 saddr6->sin6_port = 0xffff;
77 saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
79 saddr->sa_len = sizeof(sockaddr_in);
85 void IPADDR::set_type(i_type o)
90 IPADDR::i_type IPADDR::get_type() const
95 unsigned short IPADDR::get_port_net_order() const
97 unsigned short port = 0;
98 if (saddr->sa_family == AF_INET) {
99 port = saddr4->sin_port;
103 port = saddr6->sin6_port;
109 void IPADDR::set_port_net(unsigned short port)
111 if (saddr->sa_family == AF_INET) {
112 saddr4->sin_port = port;
116 saddr6->sin6_port = port;
121 int IPADDR::get_family() const
123 return saddr->sa_family;
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.
132 struct sockaddr *IPADDR::get_sockaddr()
137 int IPADDR::get_sockaddr_len()
140 return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
142 return sizeof(*saddr4);
145 void IPADDR::copy_addr(IPADDR *src)
147 if (saddr->sa_family == AF_INET) {
148 saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
151 else if (saddr->sa_family == AF_INET6) {
152 saddr6->sin6_addr = src->saddr6->sin6_addr;
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.
162 extern const struct in6_addr in6addr_any;
165 void IPADDR::set_addr_any()
167 if (saddr->sa_family == AF_INET) {
168 saddr4->sin_addr.s_addr = INADDR_ANY;
171 else if (saddr->sa_family == AF_INET6) {
172 saddr6->sin6_addr = in6addr_any;
177 void IPADDR::set_addr4(struct in_addr *ip4)
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);
182 saddr4->sin_addr = *ip4;
186 void IPADDR::set_addr6(struct in6_addr *ip6)
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);
191 saddr6->sin6_addr = *ip6;
195 const char *IPADDR::get_address(char *outputbuf, int outlen)
198 #ifdef HAVE_INET_NTOP
200 inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
201 (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
204 inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
207 bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
212 const char *IPADDR::build_address_str(char *buf, int blen)
215 if (get_family() == AF_INET) {
216 bsnprintf(buf, blen, "%s:%hu ",
217 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
219 bsnprintf(buf, blen, "[%s]:%hu ",
220 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
225 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
227 if (!addrs || addrs->size() == 0) {
228 bstrncpy(buf, "", blen);
233 foreach_dlist(p, addrs) {
235 int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
244 const char *get_first_address(dlist *addrs, char *outputbuf, int outlen)
246 return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
249 int get_first_port_net_order(dlist *addrs)
254 return ((IPADDR *)(addrs->first()))->get_port_net_order();
258 int get_first_port_host_order(dlist *addrs)
263 return ((IPADDR *)(addrs->first()))->get_port_host_order();
267 void init_default_addresses(dlist **addr_list, int port)
270 unsigned short sport = port;
271 if (!add_address(addr_list, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf, sizeof(buf))) {
272 Emsg1(M_ERROR_TERM, 0, _("Can't add default IPv4 address (%s)\n"), buf);
274 Dmsg1(20, "Initaddr %s\n", build_addresses_str(*addr_list, buf, sizeof(buf)));
278 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
279 const char *hostname_str, const char *port_str, char *buf, int buflen)
285 IPADDR::i_type intype = type;
288 dlist *addrs = (dlist *)(*(out));
291 addrs = *out = New(dlist(tmp, &tmp->link));
294 type = (type == IPADDR::R_SINGLE_PORT ||
295 type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
296 if (type != IPADDR::R_DEFAULT) {
298 foreach_dlist(iaddr, addrs) {
299 if (iaddr->get_type() == IPADDR::R_DEFAULT) {
301 } else if (iaddr->get_type() != type) {
302 bsnprintf(buf, buflen,
303 _("Old style addresses cannot be mixed with new style. Try removing Port=nnn."));
304 Dmsg1(20, "%s\n", buf);
314 if (!port_str || port_str[0] == '\0') {
317 int pnum = atol(port_str);
318 if (0 < pnum && pnum < 0xffff) {
321 struct servent *s = getservbyname(port_str, "tcp");
325 bsnprintf(buf, buflen, _("Cannot resolve service(%s)"), port_str);
326 Dmsg1(20, "%s\n", buf);
332 const char *myerrstr;
333 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
335 bsnprintf(buf, buflen, _("Cannot resolve hostname(%s) %s"), hostname_str,
337 Dmsg1(20, "%s\n", buf);
341 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
344 addr = (IPADDR *)addrs->first();
346 addr = New(IPADDR(family));
347 addr->set_type(type);
348 addr->set_port_net(defaultport);
349 addr->set_addr_any();
352 if (intype == IPADDR::R_SINGLE_PORT) {
353 addr->set_port_net(port);
355 if (intype == IPADDR::R_SINGLE_ADDR) {
356 addr->copy_addr((IPADDR *)(hostaddrs->first()));
359 foreach_dlist(iaddr, hostaddrs) {
362 foreach_dlist(jaddr, addrs) {
363 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
364 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
365 iaddr->get_sockaddr_len()))
367 goto skip; /* no price */
370 clone = New(IPADDR(*iaddr));
371 clone->set_type(type);
372 clone->set_port_net(port);
373 addrs->append(clone);
378 free_addresses(hostaddrs);
383 * Some IPv6 rules from Wikipedia:
385 * For convenience, an IPv6 address may be abbreviated to shorter
386 * notations by application of the following rules, where possible.
388 * 1. One or more leading zeroes from any groups of hexadecimal
389 * digits are removed; this is usually done to either all or none of
390 * the leading zeroes. For example, the group 0042 is converted to
393 * 2. Consecutive sections of zeroes are replaced with a double
394 * colon (::). The double colon may only be used once in an
395 * address, as multiple use would render the address indeterminate.
396 * RFC 5952 recommends that a double colon must not be used to
397 * denote an omitted single section of zeroes.[39]
401 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
403 * addr = 1.2.3.4; port = 1205; }
405 * addr = 1.2.3.4; port = http; }
418 * addr = 2001:220:222::2
421 * addr = bluedot.thun.net
427 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
428 * = { ipv4 { port = 4711 } }
430 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
433 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
435 char hostname_str[1024];
441 token = lex_get_token(lc, T_SKIP_EOL);
442 if (token != T_BOB) {
443 scan_err1(lc, _("Expected a block to begin with { but got: %s"), lc->str);
446 token = lex_get_token(lc, T_SKIP_EOL);
447 if (token == T_EOB) {
448 scan_err0(lc, _("Empty addr block is not allowed"));
451 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
452 scan_err1(lc, _("Expected a string but got: %s"), lc->str);
454 if (strcasecmp("ip", lc->str) == 0) {
456 } else if (strcasecmp("ipv4", lc->str) == 0) {
460 else if (strcasecmp("ipv6", lc->str) == 0) {
463 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6] but got: %s"), lc->str);
467 scan_err1(lc, _("Expected a string [ip|ipv4] but got: %s"), lc->str);
470 token = lex_get_token(lc, T_SKIP_EOL);
471 if (token != T_EQUALS) {
472 scan_err1(lc, _("Expected an equal = but got: %s"), lc->str);
474 token = lex_get_token(lc, T_SKIP_EOL);
475 if (token != T_BOB) {
476 scan_err1(lc, _("Expected a block to begin with { but got: %s"), lc->str);
478 token = lex_get_token(lc, T_SKIP_EOL);
480 port_str[0] = hostname_str[0] = '\0';
482 if (token != T_IDENTIFIER) {
483 scan_err1(lc, _("Expected an identifier [addr|port] but got: %s"), lc->str);
485 if (strcasecmp("port", lc->str) == 0) {
486 next_line = PORTLINE;
487 if (exist & PORTLINE) {
488 scan_err0(lc, _("Only one port per address block"));
491 } else if (strcasecmp("addr", lc->str) == 0) {
492 next_line = ADDRLINE;
493 if (exist & ADDRLINE) {
494 scan_err0(lc, _("Only one addr per address block"));
498 scan_err1(lc, _("Expected a identifier [addr|port] but got: %s"), lc->str);
500 token = lex_get_token(lc, T_SKIP_EOL);
501 if (token != T_EQUALS) {
502 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
504 token = lex_get_token(lc, T_SKIP_EOL);
508 (token == T_UNQUOTED_STRING || token == T_NUMBER ||
509 token == T_IDENTIFIER)) {
510 scan_err1(lc, _("Expected a number or a string but got: %s"), lc->str);
512 bstrncpy(port_str, lc->str, sizeof(port_str));
515 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
516 scan_err1(lc, _("Expected an IP number or a hostname but got: %s"),
519 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
522 scan_err0(lc, _("State machine missmatch"));
525 token = lex_get_token(lc, T_SKIP_EOL);
526 } while (token == T_IDENTIFIER);
527 if (token != T_EOB) {
528 scan_err1(lc, _("Expected a end of block with } but got: %s"), lc->str);
531 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
532 htons(item->default_value), family, hostname_str, port_str,
533 errmsg, sizeof(errmsg))) {
534 scan_err3(lc, _("Cannot add hostname(%s) and port(%s) to addrlist (%s)"),
535 hostname_str, port_str, errmsg);
537 token = scan_to_next_not_eol(lc);
538 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
539 if (token != T_EOB) {
540 scan_err1(lc, _("Expected an end of block with } but got: %s"), lc->str);
544 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
547 int token = lex_get_token(lc, T_SKIP_EOL);
548 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
549 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
551 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_ADDR,
552 htons(item->default_value), AF_INET, lc->str, 0,
553 errmsg, sizeof(errmsg))) {
554 scan_err2(lc, _("Cannot add port (%s) to (%s)"), lc->str, errmsg);
558 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
561 int token = lex_get_token(lc, T_SKIP_EOL);
562 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
563 scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
565 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
566 htons(item->default_value), AF_INET, 0, lc->str,
567 errmsg, sizeof(errmsg))) {
568 scan_err2(lc, _("Cannot add port (%s) to (%s)"), lc->str, errmsg);
572 void free_addresses(dlist * addrs)
574 while (!addrs->empty()) {
575 IPADDR *ptr = (IPADDR*)addrs->first();
582 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
584 if (client_addr->sa_family == AF_INET) {
585 return ((struct sockaddr_in *)client_addr)->sin_port;
589 return ((struct sockaddr_in6 *)client_addr)->sin6_port;
595 int sockaddr_get_port(const struct sockaddr *client_addr)
597 if (client_addr->sa_family == AF_INET) {
598 return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
602 return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
609 char *sockaddr_to_ascii(const struct sockaddr *sa, int socklen, char *buf, int buflen)
611 #ifdef HAVE_GETNAMEINFO
612 /* This is the more modern way of doing it */
613 char clienthost[NI_MAXHOST];
614 char clientservice[NI_MAXSERV];
616 if (sa->sa_family == AF_INET) {
617 status = getnameinfo(sa, sizeof(sockaddr_in), clienthost, sizeof(clienthost),
618 clientservice, sizeof(clientservice),
619 NI_NUMERICHOST | NI_NUMERICSERV);
623 status = getnameinfo(sa, sizeof(sockaddr_in6), clienthost, sizeof(clienthost),
624 clientservice, sizeof(clientservice),
625 NI_NUMERICHOST | NI_NUMERICSERV);
629 /* Enclose IPv6 in [] */
630 if (strchr(clienthost, ':') != NULL) {
631 bsnprintf(buf, buflen, "[%s]", clienthost);
633 bstrncpy(buf, clienthost, buflen);
636 bstrncpy(buf, "Hostname not found", buflen);
640 #ifdef HAVE_INET_NTOP
641 inet_ntop(sa->sa_family,
643 sa->sa_family == AF_INET ?
644 (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
645 (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
647 (void*)&(((struct sockaddr_in*)sa)->sin_addr),
648 # endif /* HAVE_IPV6 */
651 bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), buflen);
658 * Remove duplicate IP addresses.
660 void remove_duplicate_addresses(dlist *addr_list)
662 IPADDR *ipaddr, *next, *duplicate;
664 * Remove any duplicate addresses.
666 for (ipaddr = (IPADDR *)addr_list->first(); ipaddr;
667 ipaddr = (IPADDR *)addr_list->next(ipaddr)) {
668 for (next = (IPADDR *)addr_list->next(ipaddr); next; ) {
670 if (ipaddr->get_sockaddr_len() == next->get_sockaddr_len() &&
671 memcmp(ipaddr->get_sockaddr(), next->get_sockaddr(),
672 ipaddr->get_sockaddr_len()) == 0) {
675 next = (IPADDR *)addr_list->next(next);
677 addr_list->remove(duplicate); /* remove from list */
678 delete duplicate; /* free it */
684 #ifdef HAVE_OLD_SOCKOPT
685 int inet_aton(const char *cp, struct in_addr *inp)
687 struct in_addr inaddr;
689 if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
690 inp->s_addr = inaddr.s_addr;