2 Bacula® - The Network Backup Solution
4 Copyright (C) 2004-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 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 Bacula® is a registered trademark of Kern Sibbald.
17 * Configuration file parser for IP-Addresse ipv4 and ipv6
19 * Written by Meno Abels, June MMIV
25 #ifdef HAVE_ARPA_NAMESER_H
26 #include <arpa/nameser.h>
32 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
33 const char *hostname_str, const char *port_str, char *buf, int buflen);
36 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
38 memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
39 saddr = &saddrbuf.dontuse;
40 saddr4 = &saddrbuf.dontuse4;
42 saddr6 = &saddrbuf.dontuse6;
46 IPADDR::IPADDR(int af) : type(R_EMPTY)
49 if (!(af == AF_INET6 || af == AF_INET)) {
50 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
54 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
57 memset(&saddrbuf, 0, sizeof(saddrbuf));
58 saddr = &saddrbuf.dontuse;
59 saddr4 = &saddrbuf.dontuse4;
61 saddr6 = &saddrbuf.dontuse6;
63 saddr->sa_family = af;
65 saddr4->sin_port = 0xffff;
69 saddr6->sin6_port = 0xffff;
74 saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
76 saddr->sa_len = sizeof(sockaddr_in);
82 void IPADDR::set_type(i_type o)
87 IPADDR::i_type IPADDR::get_type() const
92 unsigned short IPADDR::get_port_net_order() const
94 unsigned short port = 0;
95 if (saddr->sa_family == AF_INET) {
96 port = saddr4->sin_port;
100 port = saddr6->sin6_port;
106 void IPADDR::set_port_net(unsigned short port)
108 if (saddr->sa_family == AF_INET) {
109 saddr4->sin_port = port;
113 saddr6->sin6_port = port;
118 int IPADDR::get_family() const
120 return saddr->sa_family;
124 * Note, this returns the address of the socket structure
125 * not the address of the socket address.
126 * This socket address is a union of the different types
127 * of sockets (IPv4, ...) available, so it is portable.
129 struct sockaddr *IPADDR::get_sockaddr()
134 int IPADDR::get_sockaddr_len()
137 return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
139 return sizeof(*saddr4);
142 void IPADDR::copy_addr(IPADDR *src)
144 if (saddr->sa_family == AF_INET) {
145 saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
148 else if (saddr->sa_family == AF_INET6) {
149 saddr6->sin6_addr = src->saddr6->sin6_addr;
154 void IPADDR::set_addr_any()
156 if (saddr->sa_family == AF_INET) {
157 saddr4->sin_addr.s_addr = INADDR_ANY;
160 else if (saddr->sa_family == AF_INET6) {
161 saddr6->sin6_addr = in6addr_any;
166 void IPADDR::set_addr4(struct in_addr *ip4)
168 if (saddr->sa_family != AF_INET) {
169 Emsg1(M_ERROR_TERM, 0, _("You tried to assign a ipv6 address to an ipv4(%d)\n"), saddr->sa_family);
171 saddr4->sin_addr = *ip4;
175 void IPADDR::set_addr6(struct in6_addr *ip6)
177 if (saddr->sa_family != AF_INET6) {
178 Emsg1(M_ERROR_TERM, 0, _("You tried to assign an ipv4 address to an ipv6(%d)\n"), saddr->sa_family);
180 saddr6->sin6_addr = *ip6;
184 const char *IPADDR::get_address(char *outputbuf, int outlen)
187 #ifdef HAVE_INET_NTOP
189 inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
190 (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
193 inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
196 bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
201 const char *IPADDR::build_address_str(char *buf, int blen)
204 if (get_family() == AF_INET) {
205 bsnprintf(buf, blen, "%s:%hu ",
206 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
208 bsnprintf(buf, blen, "[%s]:%hu ",
209 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
214 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
216 if (!addrs || addrs->size() == 0) {
217 bstrncpy(buf, "", blen);
222 foreach_dlist(p, addrs) {
224 int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
233 const char *get_first_address(dlist *addrs, char *outputbuf, int outlen)
235 return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
238 int get_first_port_net_order(dlist *addrs)
243 return ((IPADDR *)(addrs->first()))->get_port_net_order();
247 int get_first_port_host_order(dlist *addrs)
252 return ((IPADDR *)(addrs->first()))->get_port_host_order();
256 void init_default_addresses(dlist **addr_list, int port)
259 unsigned short sport = port;
260 if (!add_address(addr_list, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf, sizeof(buf))) {
261 Emsg1(M_ERROR_TERM, 0, _("Can't add default IPv4 address (%s)\n"), buf);
263 Dmsg1(20, "Initaddr %s\n", build_addresses_str(*addr_list, buf, sizeof(buf)));
267 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
268 const char *hostname_str, const char *port_str, char *buf, int buflen)
274 IPADDR::i_type intype = type;
277 dlist *addrs = (dlist *)(*(out));
280 addrs = *out = New(dlist(tmp, &tmp->link));
283 type = (type == IPADDR::R_SINGLE_PORT ||
284 type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
285 if (type != IPADDR::R_DEFAULT) {
287 foreach_dlist(iaddr, addrs) {
288 if (iaddr->get_type() == IPADDR::R_DEFAULT) {
290 } else if (iaddr->get_type() != type) {
291 bsnprintf(buf, buflen,
292 _("Old style addresses cannot be mixed with new style. Try removing Port=nnn."));
293 Dmsg1(20, "%s\n", buf);
303 if (!port_str || port_str[0] == '\0') {
306 int pnum = atol(port_str);
307 if (0 < pnum && pnum < 0xffff) {
310 struct servent *s = getservbyname(port_str, "tcp");
314 bsnprintf(buf, buflen, _("Cannot resolve service(%s)"), port_str);
315 Dmsg1(20, "%s\n", buf);
321 const char *myerrstr;
322 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
324 bsnprintf(buf, buflen, _("Cannot resolve hostname(%s) %s"), hostname_str,
326 Dmsg1(20, "%s\n", buf);
330 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
333 addr = (IPADDR *)addrs->first();
335 addr = New(IPADDR(family));
336 addr->set_type(type);
337 addr->set_port_net(defaultport);
338 addr->set_addr_any();
341 if (intype == IPADDR::R_SINGLE_PORT) {
342 addr->set_port_net(port);
344 if (intype == IPADDR::R_SINGLE_ADDR) {
345 addr->copy_addr((IPADDR *)(hostaddrs->first()));
348 foreach_dlist(iaddr, hostaddrs) {
351 foreach_dlist(jaddr, addrs) {
352 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
353 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
354 iaddr->get_sockaddr_len()))
356 goto skip; /* no price */
359 clone = New(IPADDR(*iaddr));
360 clone->set_type(type);
361 clone->set_port_net(port);
362 addrs->append(clone);
367 free_addresses(hostaddrs);
372 * Some IPv6 rules from Wikipedia:
374 * For convenience, an IPv6 address may be abbreviated to shorter
375 * notations by application of the following rules, where possible.
377 * 1. One or more leading zeroes from any groups of hexadecimal
378 * digits are removed; this is usually done to either all or none of
379 * the leading zeroes. For example, the group 0042 is converted to
382 * 2. Consecutive sections of zeroes are replaced with a double
383 * colon (::). The double colon may only be used once in an
384 * address, as multiple use would render the address indeterminate.
385 * RFC 5952 recommends that a double colon must not be used to
386 * denote an omitted single section of zeroes.[39]
390 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
392 * addr = 1.2.3.4; port = 1205; }
394 * addr = 1.2.3.4; port = http; }
407 * addr = 2001:220:222::2
410 * addr = bluedot.thun.net
416 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
417 * = { ipv4 { port = 4711 } }
419 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
422 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
424 char hostname_str[1024];
430 token = lex_get_token(lc, T_SKIP_EOL);
431 if (token != T_BOB) {
432 scan_err1(lc, _("Expected a block to begin with { but got: %s"), lc->str);
435 token = lex_get_token(lc, T_SKIP_EOL);
436 if (token == T_EOB) {
437 scan_err0(lc, _("Empty addr block is not allowed"));
440 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
441 scan_err1(lc, _("Expected a string but got: %s"), lc->str);
443 if (strcasecmp("ip", lc->str) == 0) {
445 } else if (strcasecmp("ipv4", lc->str) == 0) {
449 else if (strcasecmp("ipv6", lc->str) == 0) {
452 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6] but got: %s"), lc->str);
456 scan_err1(lc, _("Expected a string [ip|ipv4] but got: %s"), lc->str);
459 token = lex_get_token(lc, T_SKIP_EOL);
460 if (token != T_EQUALS) {
461 scan_err1(lc, _("Expected an equal = but got: %s"), lc->str);
463 token = lex_get_token(lc, T_SKIP_EOL);
464 if (token != T_BOB) {
465 scan_err1(lc, _("Expected a block to begin with { but got: %s"), lc->str);
467 token = lex_get_token(lc, T_SKIP_EOL);
469 port_str[0] = hostname_str[0] = '\0';
471 if (token != T_IDENTIFIER) {
472 scan_err1(lc, _("Expected an identifier [addr|port] but got: %s"), lc->str);
474 if (strcasecmp("port", lc->str) == 0) {
475 next_line = PORTLINE;
476 if (exist & PORTLINE) {
477 scan_err0(lc, _("Only one port per address block"));
480 } else if (strcasecmp("addr", lc->str) == 0) {
481 next_line = ADDRLINE;
482 if (exist & ADDRLINE) {
483 scan_err0(lc, _("Only one addr per address block"));
487 scan_err1(lc, _("Expected a identifier [addr|port] but got: %s"), lc->str);
489 token = lex_get_token(lc, T_SKIP_EOL);
490 if (token != T_EQUALS) {
491 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
493 token = lex_get_token(lc, T_SKIP_EOL);
497 (token == T_UNQUOTED_STRING || token == T_NUMBER ||
498 token == T_IDENTIFIER)) {
499 scan_err1(lc, _("Expected a number or a string but got: %s"), lc->str);
501 bstrncpy(port_str, lc->str, sizeof(port_str));
504 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
505 scan_err1(lc, _("Expected an IP number or a hostname but got: %s"),
508 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
511 scan_err0(lc, _("State machine missmatch"));
514 token = lex_get_token(lc, T_SKIP_EOL);
515 } while (token == T_IDENTIFIER);
516 if (token != T_EOB) {
517 scan_err1(lc, _("Expected a end of block with } but got: %s"), lc->str);
520 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
521 htons(item->default_value), family, hostname_str, port_str,
522 errmsg, sizeof(errmsg))) {
523 scan_err3(lc, _("Cannot add hostname(%s) and port(%s) to addrlist (%s)"),
524 hostname_str, port_str, errmsg);
526 token = scan_to_next_not_eol(lc);
527 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
528 if (token != T_EOB) {
529 scan_err1(lc, _("Expected an end of block with } but got: %s"), lc->str);
533 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
536 int token = lex_get_token(lc, T_SKIP_EOL);
537 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
538 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
540 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_ADDR,
541 htons(item->default_value), AF_INET, lc->str, 0,
542 errmsg, sizeof(errmsg))) {
543 scan_err2(lc, _("Cannot add port (%s) to (%s)"), lc->str, errmsg);
547 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
550 int token = lex_get_token(lc, T_SKIP_EOL);
551 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
552 scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
554 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
555 htons(item->default_value), AF_INET, 0, lc->str,
556 errmsg, sizeof(errmsg))) {
557 scan_err2(lc, _("Cannot add port (%s) to (%s)"), lc->str, errmsg);
561 void free_addresses(dlist * addrs)
563 while (!addrs->empty()) {
564 IPADDR *ptr = (IPADDR*)addrs->first();
571 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
573 if (client_addr->sa_family == AF_INET) {
574 return ((struct sockaddr_in *)client_addr)->sin_port;
578 return ((struct sockaddr_in6 *)client_addr)->sin6_port;
584 int sockaddr_get_port(const struct sockaddr *client_addr)
586 if (client_addr->sa_family == AF_INET) {
587 return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
591 return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
598 char *sockaddr_to_ascii(const struct sockaddr *sa, int socklen, char *buf, int buflen)
600 #ifdef HAVE_GETNAMEINFO
601 /* This is the more modern way of doing it */
602 char clienthost[NI_MAXHOST];
603 char clientservice[NI_MAXSERV];
605 status = getnameinfo(sa, socklen, clienthost, sizeof(clienthost),
606 clientservice, sizeof(clientservice),
607 NI_NUMERICHOST | NI_NUMERICSERV);
609 /* Enclose IPv6 in [] */
610 if (strchr(clienthost, ':') != NULL) {
611 bsnprintf(buf, buflen, "[%s]", clienthost);
613 bstrncpy(buf, clienthost, buflen);
616 bstrncpy(buf, "Hostname not found", buflen);
620 #ifdef HAVE_INET_NTOP
621 inet_ntop(sa->sa_family,
623 sa->sa_family == AF_INET ?
624 (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
625 (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
627 (void*)&(((struct sockaddr_in*)sa)->sin_addr),
628 # endif /* HAVE_IPV6 */
631 bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), buflen);
638 * Remove duplicate IP addresses.
640 void remove_duplicate_addresses(dlist *addr_list)
642 IPADDR *ipaddr, *next, *duplicate;
644 * Remove any duplicate addresses.
646 for (ipaddr = (IPADDR *)addr_list->first(); ipaddr;
647 ipaddr = (IPADDR *)addr_list->next(ipaddr)) {
648 for (next = (IPADDR *)addr_list->next(ipaddr); next; ) {
650 if (ipaddr->get_sockaddr_len() == next->get_sockaddr_len() &&
651 memcmp(ipaddr->get_sockaddr(), next->get_sockaddr(),
652 ipaddr->get_sockaddr_len()) == 0) {
655 next = (IPADDR *)addr_list->next(next);
657 addr_list->remove(duplicate); /* remove from list */
658 delete duplicate; /* free it */
664 #ifdef HAVE_OLD_SOCKOPT
665 int inet_aton(const char *cp, struct in_addr *inp)
667 struct in_addr inaddr;
669 if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
670 inp->s_addr = inaddr.s_addr;