2 Bacula® - The Network Backup Solution
4 Copyright (C) 2004-2011 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 three of the GNU Affero 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 Affero 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 of Kern Sibbald.
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
37 #ifdef HAVE_ARPA_NAMESER_H
38 #include <arpa/nameser.h>
44 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
45 const char *hostname_str, const char *port_str, char *buf, int buflen);
48 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
50 memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
51 saddr = &saddrbuf.dontuse;
52 saddr4 = &saddrbuf.dontuse4;
54 saddr6 = &saddrbuf.dontuse6;
58 IPADDR::IPADDR(int af) : type(R_EMPTY)
61 if (!(af == AF_INET6 || af == AF_INET)) {
62 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
66 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
69 memset(&saddrbuf, 0, sizeof(saddrbuf));
70 saddr = &saddrbuf.dontuse;
71 saddr4 = &saddrbuf.dontuse4;
73 saddr6 = &saddrbuf.dontuse6;
75 saddr->sa_family = af;
77 saddr4->sin_port = 0xffff;
81 saddr6->sin6_port = 0xffff;
86 saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
88 saddr->sa_len = sizeof(sockaddr_in);
94 void IPADDR::set_type(i_type o)
99 IPADDR::i_type IPADDR::get_type() const
104 unsigned short IPADDR::get_port_net_order() const
106 unsigned short port = 0;
107 if (saddr->sa_family == AF_INET) {
108 port = saddr4->sin_port;
112 port = saddr6->sin6_port;
118 void IPADDR::set_port_net(unsigned short port)
120 if (saddr->sa_family == AF_INET) {
121 saddr4->sin_port = port;
125 saddr6->sin6_port = port;
130 int IPADDR::get_family() const
132 return saddr->sa_family;
135 struct sockaddr *IPADDR::get_sockaddr()
140 int IPADDR::get_sockaddr_len()
143 return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
145 return sizeof(*saddr4);
148 void IPADDR::copy_addr(IPADDR *src)
150 if (saddr->sa_family == AF_INET) {
151 saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
155 saddr6->sin6_addr = src->saddr6->sin6_addr;
160 void IPADDR::set_addr_any()
162 if (saddr->sa_family == AF_INET) {
163 saddr4->sin_addr.s_addr = INADDR_ANY;
167 saddr6->sin6_addr= in6addr_any;
172 void IPADDR::set_addr4(struct in_addr *ip4)
174 if (saddr->sa_family != AF_INET) {
175 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv6 address to a ipv4(%d)\n"), saddr->sa_family);
177 saddr4->sin_addr = *ip4;
181 void IPADDR::set_addr6(struct in6_addr *ip6)
183 if (saddr->sa_family != AF_INET6) {
184 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv4 address to a ipv6(%d)\n"), saddr->sa_family);
186 saddr6->sin6_addr = *ip6;
190 const char *IPADDR::get_address(char *outputbuf, int outlen)
193 #ifdef HAVE_INET_NTOP
195 inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
196 (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
199 inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
202 bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
207 const char *IPADDR::build_address_str(char *buf, int blen)
210 bsnprintf(buf, blen, "host[%s:%s:%hu] ",
211 get_family() == AF_INET ? "ipv4" : "ipv6",
212 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
216 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
218 if (!addrs || addrs->size() == 0) {
219 bstrncpy(buf, "", blen);
224 foreach_dlist(p, addrs) {
226 int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
235 const char *get_first_address(dlist *addrs, char *outputbuf, int outlen)
237 return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
240 int get_first_port_net_order(dlist *addrs)
245 return ((IPADDR *)(addrs->first()))->get_port_net_order();
249 int get_first_port_host_order(dlist *addrs)
254 return ((IPADDR *)(addrs->first()))->get_port_host_order();
258 void init_default_addresses(dlist **out, int port)
261 unsigned short sport = port;
262 if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf, sizeof(buf))) {
263 Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), 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 _("the old style addresses cannot be mixed with new style"));
302 if (!port_str || port_str[0] == '\0') {
305 int pnum = atol(port_str);
306 if (0 < pnum && pnum < 0xffff) {
309 struct servent *s = getservbyname(port_str, "tcp");
313 bsnprintf(buf, buflen, _("can't resolve service(%s)"), port_str);
319 const char *myerrstr;
320 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
322 bsnprintf(buf, buflen, _("can't resolve hostname(%s) %s"), hostname_str,
327 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
330 addr = (IPADDR *)addrs->first();
332 addr = New(IPADDR(family));
333 addr->set_type(type);
334 addr->set_port_net(defaultport);
335 addr->set_addr_any();
338 if (intype == IPADDR::R_SINGLE_PORT) {
339 addr->set_port_net(port);
341 if (intype == IPADDR::R_SINGLE_ADDR) {
342 addr->copy_addr((IPADDR *)(hostaddrs->first()));
345 foreach_dlist(iaddr, hostaddrs) {
348 foreach_dlist(jaddr, addrs) {
349 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
350 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
351 iaddr->get_sockaddr_len()))
353 goto skip; /* no price */
356 clone = New(IPADDR(*iaddr));
357 clone->set_type(type);
358 clone->set_port_net(port);
359 addrs->append(clone);
364 free_addresses(hostaddrs);
371 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
373 * addr = 1.2.3.4; port = 1205; }
375 * addr = 1.2.3.4; port = http; }
388 * addr = 2001:220:222::2
391 * addr = bluedot.thun.net
396 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
397 * = { ipv4 { port = 4711 } }
399 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
402 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
404 char hostname_str[1024];
410 token = lex_get_token(lc, T_SKIP_EOL);
411 if (token != T_BOB) {
412 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
415 token = lex_get_token(lc, T_SKIP_EOL);
416 if (token == T_EOB) {
417 scan_err0(lc, _("Empty addr block is not allowed"));
420 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
421 scan_err1(lc, _("Expected a string, got: %s"), lc->str);
423 if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
427 else if (strcasecmp("ipv6", lc->str) == 0) {
430 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
434 scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
437 token = lex_get_token(lc, T_SKIP_EOL);
438 if (token != T_EQUALS) {
439 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
441 token = lex_get_token(lc, T_SKIP_EOL);
442 if (token != T_BOB) {
443 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
445 token = lex_get_token(lc, T_SKIP_EOL);
447 port_str[0] = hostname_str[0] = '\0';
449 if (token != T_IDENTIFIER) {
450 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
452 if (strcasecmp("port", lc->str) == 0) {
453 next_line = PORTLINE;
454 if (exist & PORTLINE) {
455 scan_err0(lc, _("Only one port per address block"));
458 } else if (strcasecmp("addr", lc->str) == 0) {
459 next_line = ADDRLINE;
460 if (exist & ADDRLINE) {
461 scan_err0(lc, _("Only one addr per address block"));
465 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
467 token = lex_get_token(lc, T_SKIP_EOL);
468 if (token != T_EQUALS) {
469 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
471 token = lex_get_token(lc, T_SKIP_EOL);
475 (token == T_UNQUOTED_STRING || token == T_NUMBER
476 || token == T_IDENTIFIER)) {
477 scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
479 bstrncpy(port_str, lc->str, sizeof(port_str));
482 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
483 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
486 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
489 scan_err0(lc, _("State machine missmatch"));
492 token = lex_get_token(lc, T_SKIP_EOL);
493 } while (token == T_IDENTIFIER);
494 if (token != T_EOB) {
495 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
498 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
499 htons(item->default_value), family, hostname_str, port_str,
500 errmsg, sizeof(errmsg))) {
501 scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
502 hostname_str, port_str, errmsg);
504 token = scan_to_next_not_eol(lc);
505 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
506 if (token != T_EOB) {
507 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
511 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
514 int token = lex_get_token(lc, T_SKIP_EOL);
515 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
516 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
518 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_ADDR,
519 htons(item->default_value), AF_INET, lc->str, 0,
520 errmsg, sizeof(errmsg))) {
521 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg);
525 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
528 int token = lex_get_token(lc, T_SKIP_EOL);
529 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
530 scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
532 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
533 htons(item->default_value), AF_INET, 0, lc->str,
534 errmsg, sizeof(errmsg))) {
535 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg);
539 void free_addresses(dlist * addrs)
541 while (!addrs->empty()) {
542 IPADDR *ptr = (IPADDR*)addrs->first();
549 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
551 if (client_addr->sa_family == AF_INET) {
552 return ((struct sockaddr_in *)client_addr)->sin_port;
556 return ((struct sockaddr_in6 *)client_addr)->sin6_port;
562 int sockaddr_get_port(const struct sockaddr *client_addr)
564 if (client_addr->sa_family == AF_INET) {
565 return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
569 return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
576 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
578 #ifdef HAVE_INET_NTOP
579 /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
580 inet_ntop(sa->sa_family,
582 sa->sa_family == AF_INET ?
583 (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
584 (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
586 (void*)&(((struct sockaddr_in*)sa)->sin_addr),
587 # endif /* HAVE_IPV6 */
590 bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
595 #ifdef HAVE_OLD_SOCKOPT
596 int inet_aton(const char *cp, struct in_addr *inp)
598 struct in_addr inaddr;
600 if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
601 inp->s_addr = inaddr.s_addr;