2 Bacula® - The Network Backup Solution
4 Copyright (C) 2004-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark ofJohn Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Configuration file parser for IP-Addresse ipv4 and ipv6
31 * Written by Meno Abels, June MMIV
38 #ifdef HAVE_ARPA_NAMESER_H
39 #include <arpa/nameser.h>
45 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
46 const char *hostname_str, const char *port_str, char *buf, int buflen);
49 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
51 memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
52 saddr = &saddrbuf.dontuse;
53 saddr4 = &saddrbuf.dontuse4;
55 saddr6 = &saddrbuf.dontuse6;
59 IPADDR::IPADDR(int af) : type(R_EMPTY)
62 if (!(af == AF_INET6 || af == AF_INET)) {
63 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
67 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
70 memset(&saddrbuf, 0, sizeof(saddrbuf));
71 saddr = &saddrbuf.dontuse;
72 saddr4 = &saddrbuf.dontuse4;
74 saddr6 = &saddrbuf.dontuse6;
76 saddr->sa_family = af;
78 saddr4->sin_port = 0xffff;
82 saddr6->sin6_port = 0xffff;
87 saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
89 saddr->sa_len = sizeof(sockaddr_in);
95 void IPADDR::set_type(i_type o)
100 IPADDR::i_type IPADDR::get_type() const
105 unsigned short IPADDR::get_port_net_order() const
107 unsigned short port = 0;
108 if (saddr->sa_family == AF_INET) {
109 port = saddr4->sin_port;
113 port = saddr6->sin6_port;
119 void IPADDR::set_port_net(unsigned short port)
121 if (saddr->sa_family == AF_INET) {
122 saddr4->sin_port = port;
126 saddr6->sin6_port = port;
131 int IPADDR::get_family() const
133 return saddr->sa_family;
136 struct sockaddr *IPADDR::get_sockaddr()
141 int IPADDR::get_sockaddr_len()
144 return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
146 return sizeof(*saddr4);
149 void IPADDR::copy_addr(IPADDR *src)
151 if (saddr->sa_family == AF_INET) {
152 saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
156 saddr6->sin6_addr = src->saddr6->sin6_addr;
161 void IPADDR::set_addr_any()
163 if (saddr->sa_family == AF_INET) {
164 saddr4->sin_addr.s_addr = INADDR_ANY;
168 saddr6->sin6_addr= in6addr_any;
173 void IPADDR::set_addr4(struct in_addr *ip4)
175 if (saddr->sa_family != AF_INET) {
176 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv6 address to a ipv4(%d)\n"), saddr->sa_family);
178 saddr4->sin_addr = *ip4;
182 void IPADDR::set_addr6(struct in6_addr *ip6)
184 if (saddr->sa_family != AF_INET6) {
185 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv4 address to a ipv6(%d)\n"), saddr->sa_family);
187 saddr6->sin6_addr = *ip6;
191 const char *IPADDR::get_address(char *outputbuf, int outlen)
194 #ifdef HAVE_INET_NTOP
196 inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
197 (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
200 inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
203 bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
208 const char *IPADDR::build_address_str(char *buf, int blen)
211 bsnprintf(buf, blen, "host[%s:%s:%hu] ",
212 get_family() == AF_INET ? "ipv4" : "ipv6",
213 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
217 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
219 if (!addrs || addrs->size() == 0) {
220 bstrncpy(buf, "", blen);
225 foreach_dlist(p, addrs) {
227 int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
236 const char *get_first_address(dlist *addrs, char *outputbuf, int outlen)
238 return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
241 int get_first_port_net_order(dlist *addrs)
246 return ((IPADDR *)(addrs->first()))->get_port_net_order();
250 int get_first_port_host_order(dlist *addrs)
255 return ((IPADDR *)(addrs->first()))->get_port_host_order();
259 void init_default_addresses(dlist **out, int port)
262 unsigned short sport = port;
263 if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf, sizeof(buf))) {
264 Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), buf);
268 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
269 const char *hostname_str, const char *port_str, char *buf, int buflen)
275 IPADDR::i_type intype = type;
278 dlist *addrs = (dlist *)(*(out));
281 addrs = *out = New(dlist(tmp, &tmp->link));
284 type = (type == IPADDR::R_SINGLE_PORT
285 || type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
286 if (type != IPADDR::R_DEFAULT) {
288 foreach_dlist(iaddr, addrs) {
289 if (iaddr->get_type() == IPADDR::R_DEFAULT) {
291 } else if (iaddr->get_type() != type) {
292 bsnprintf(buf, buflen,
293 _("the old style addresses cannot be mixed with new style"));
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, _("can't resolve service(%s)"), port_str);
320 const char *myerrstr;
321 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
323 bsnprintf(buf, buflen, _("can't resolve hostname(%s) %s"), hostname_str,
328 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
331 addr = (IPADDR *)addrs->first();
333 addr = New(IPADDR(family));
334 addr->set_type(type);
335 addr->set_port_net(defaultport);
336 addr->set_addr_any();
339 if (intype == IPADDR::R_SINGLE_PORT) {
340 addr->set_port_net(port);
342 if (intype == IPADDR::R_SINGLE_ADDR) {
343 addr->copy_addr((IPADDR *)(hostaddrs->first()));
346 foreach_dlist(iaddr, hostaddrs) {
349 foreach_dlist(jaddr, addrs) {
350 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
351 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
352 iaddr->get_sockaddr_len()))
354 goto skip; /* no price */
357 clone = New(IPADDR(*iaddr));
358 clone->set_type(type);
359 clone->set_port_net(port);
360 addrs->append(clone);
365 free_addresses(hostaddrs);
372 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
374 * addr = 1.2.3.4; port = 1205; }
376 * addr = 1.2.3.4; port = http; }
389 * addr = 2001:220:222::2
392 * addr = bluedot.thun.net
397 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
398 * = { ipv4 { port = 4711 } }
400 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
403 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
405 char hostname_str[1024];
411 token = lex_get_token(lc, T_SKIP_EOL);
412 if (token != T_BOB) {
413 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
416 token = lex_get_token(lc, T_SKIP_EOL);
417 if (token == T_EOB) {
418 scan_err0(lc, _("Empty addr block is not allowed"));
421 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
422 scan_err1(lc, _("Expected a string, got: %s"), lc->str);
424 if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
428 else if (strcasecmp("ipv6", lc->str) == 0) {
431 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
435 scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
438 token = lex_get_token(lc, T_SKIP_EOL);
439 if (token != T_EQUALS) {
440 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
442 token = lex_get_token(lc, T_SKIP_EOL);
443 if (token != T_BOB) {
444 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
446 token = lex_get_token(lc, T_SKIP_EOL);
448 port_str[0] = hostname_str[0] = '\0';
450 if (token != T_IDENTIFIER) {
451 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
453 if (strcasecmp("port", lc->str) == 0) {
454 next_line = PORTLINE;
455 if (exist & PORTLINE) {
456 scan_err0(lc, _("Only one port per address block"));
459 } else if (strcasecmp("addr", lc->str) == 0) {
460 next_line = ADDRLINE;
461 if (exist & ADDRLINE) {
462 scan_err0(lc, _("Only one addr per address block"));
466 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
468 token = lex_get_token(lc, T_SKIP_EOL);
469 if (token != T_EQUALS) {
470 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
472 token = lex_get_token(lc, T_SKIP_EOL);
476 (token == T_UNQUOTED_STRING || token == T_NUMBER
477 || token == T_IDENTIFIER)) {
478 scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
480 bstrncpy(port_str, lc->str, sizeof(port_str));
483 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
484 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
487 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
490 scan_err0(lc, _("State machine missmatch"));
493 token = lex_get_token(lc, T_SKIP_EOL);
494 } while (token == T_IDENTIFIER);
495 if (token != T_EOB) {
496 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
499 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
500 htons(item->default_value), family, hostname_str, port_str,
501 errmsg, sizeof(errmsg))) {
502 scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
503 hostname_str, port_str, errmsg);
505 token = scan_to_next_not_eol(lc);
506 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
507 if (token != T_EOB) {
508 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
512 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
515 int token = lex_get_token(lc, T_SKIP_EOL);
516 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
517 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
519 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_ADDR,
520 htons(item->default_value), AF_INET, lc->str, 0,
521 errmsg, sizeof(errmsg))) {
522 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg);
526 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
529 int token = lex_get_token(lc, T_SKIP_EOL);
530 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
531 scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
533 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
534 htons(item->default_value), AF_INET, 0, lc->str,
535 errmsg, sizeof(errmsg))) {
536 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg);
540 void free_addresses(dlist * addrs)
542 while (!addrs->empty()) {
543 IPADDR *ptr = (IPADDR*)addrs->first();
550 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
552 if (client_addr->sa_family == AF_INET) {
553 return ((struct sockaddr_in *)client_addr)->sin_port;
557 return ((struct sockaddr_in6 *)client_addr)->sin6_port;
563 int sockaddr_get_port(const struct sockaddr *client_addr)
565 if (client_addr->sa_family == AF_INET) {
566 return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
570 return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
577 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
579 #ifdef HAVE_INET_NTOP
580 /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
581 inet_ntop(sa->sa_family,
583 sa->sa_family == AF_INET ?
584 (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
585 (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
587 (void*)&(((struct sockaddr_in*)sa)->sin_addr),
588 # endif /* HAVE_IPV6 */
591 bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
596 #ifdef HAVE_OLD_SOCKOPT
597 int inet_aton(const char *cp, struct in_addr *inp)
599 struct in_addr inaddr;
601 if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
602 inp->s_addr = inaddr.s_addr;