2 * Configuration file parser for IP-Addresse ipv4 and ipv6
4 * Written by Meno Abels, June MMIV
9 Bacula® - The Network Backup Solution
11 Copyright (C) 2004-2006 Free Software Foundation Europe e.V.
13 The main author of Bacula is Kern Sibbald, with contributions from
14 many others, a complete list can be found in the file AUTHORS.
15 This program is Free Software; you can redistribute it and/or
16 modify it under the terms of version two of the GNU General Public
17 License as published by the Free Software Foundation plus additions
18 that are listed in the file LICENSE.
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 Bacula® is a registered trademark ofJohn Walker.
31 The licensor of Bacula is the Free Software Foundation Europe
32 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
33 Switzerland, email:ftf@fsfeurope.org.
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 **errstr);
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, &errstr)) {
264 Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), errstr);
269 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
270 const char *hostname_str, const char *port_str, char **errstr)
276 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 *errstr = (char *)malloc(1024);
293 bsnprintf(*errstr, 1023,
294 _("the old style addresses cannot be mixed with new style"));
305 if (!port_str || port_str[0] == '\0') {
308 int pnum = atol(port_str);
309 if (0 < pnum && pnum < 0xffff) {
312 struct servent *s = getservbyname(port_str, "tcp");
316 *errstr = (char *)malloc(1024);
317 bsnprintf(*errstr, 1023, _("can't resolve service(%s)"), port_str);
323 const char *myerrstr;
324 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
326 *errstr = (char *)malloc(1024);
327 bsnprintf(*errstr, 1023, _("can't resolve hostname(%s) %s"), hostname_str,
332 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
335 addr = (IPADDR *)addrs->first();
337 addr = New(IPADDR(family));
338 addr->set_type(type);
339 addr->set_port_net(defaultport);
340 addr->set_addr_any();
343 if (intype == IPADDR::R_SINGLE_PORT) {
344 addr->set_port_net(port);
346 if (intype == IPADDR::R_SINGLE_ADDR) {
347 addr->copy_addr((IPADDR *) (hostaddrs->first()));
350 foreach_dlist(iaddr, hostaddrs) {
353 foreach_dlist(jaddr, addrs) {
354 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
355 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
356 iaddr->get_sockaddr_len()))
358 goto skip; /* no price */
361 clone = New(IPADDR(*iaddr));
362 clone->set_type(type);
363 clone->set_port_net(port);
364 addrs->append(clone);
369 free_addresses(hostaddrs);
376 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
378 * addr = 1.2.3.4; port = 1205; }
380 * addr = 1.2.3.4; port = http; }
393 * addr = 2001:220:222::2
396 * addr = bluedot.thun.net
401 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
402 * = { ipv4 { port = 4711 } }
404 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
407 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
409 char hostname_str[1024];
414 token = lex_get_token(lc, T_SKIP_EOL);
415 if (token != T_BOB) {
416 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
419 token = lex_get_token(lc, T_SKIP_EOL);
420 if (token == T_EOB) {
421 scan_err0(lc, _("Empty addr block is not allowed"));
424 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
425 scan_err1(lc, _("Expected a string, got: %s"), lc->str);
427 if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
431 else if (strcasecmp("ipv6", lc->str) == 0) {
434 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
438 scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
441 token = lex_get_token(lc, T_SKIP_EOL);
442 if (token != T_EQUALS) {
443 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
445 token = lex_get_token(lc, T_SKIP_EOL);
446 if (token != T_BOB) {
447 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
449 token = lex_get_token(lc, T_SKIP_EOL);
451 port_str[0] = hostname_str[0] = '\0';
453 if (token != T_IDENTIFIER) {
454 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
456 if (strcasecmp("port", lc->str) == 0) {
457 next_line = PORTLINE;
458 if (exist & PORTLINE) {
459 scan_err0(lc, _("Only one port per address block"));
462 } else if (strcasecmp("addr", lc->str) == 0) {
463 next_line = ADDRLINE;
464 if (exist & ADDRLINE) {
465 scan_err0(lc, _("Only one addr per address block"));
469 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
471 token = lex_get_token(lc, T_SKIP_EOL);
472 if (token != T_EQUALS) {
473 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
475 token = lex_get_token(lc, T_SKIP_EOL);
479 (token == T_UNQUOTED_STRING || token == T_NUMBER
480 || token == T_IDENTIFIER)) {
481 scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
483 bstrncpy(port_str, lc->str, sizeof(port_str));
486 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
487 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
490 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
493 scan_err0(lc, _("State machine missmatch"));
496 token = lex_get_token(lc, T_SKIP_EOL);
497 } while (token == T_IDENTIFIER);
498 if (token != T_EOB) {
499 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
503 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
504 htons(item->default_value), family, hostname_str, port_str, &errstr)) {
505 scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
506 hostname_str, port_str, errstr);
509 token = scan_to_next_not_eol(lc);
510 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
511 if (token != T_EOB) {
512 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
516 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
519 int token = lex_get_token(lc, T_SKIP_EOL);
520 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
521 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
524 if (pass == 1 && !add_address((dlist **) (item->value), IPADDR::R_SINGLE_ADDR,
525 htons(item->default_value), AF_INET, lc->str, 0, &errstr)) {
526 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
531 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
533 int token = lex_get_token(lc, T_SKIP_EOL);
534 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
535 scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
538 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
539 htons(item->default_value), AF_INET, 0, lc->str, &errstr)) {
540 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
545 void free_addresses(dlist * addrs)
547 while (!addrs->empty()) {
548 IPADDR *ptr = (IPADDR*)addrs->first();
555 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
557 if (client_addr->sa_family == AF_INET) {
558 return ((struct sockaddr_in *)client_addr)->sin_port;
562 return ((struct sockaddr_in6 *)client_addr)->sin6_port;
568 int sockaddr_get_port(const struct sockaddr *client_addr)
570 if (client_addr->sa_family == AF_INET) {
571 return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
575 return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
582 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
584 #ifdef HAVE_INET_NTOP
585 /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
586 inet_ntop(sa->sa_family,
588 sa->sa_family == AF_INET ?
589 (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
590 (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
592 (void*)&(((struct sockaddr_in*)sa)->sin_addr),
593 # endif /* HAVE_IPV6 */
596 bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
601 #ifdef HAVE_OLD_SOCKOPT
602 int inet_aton(const char *cp, struct in_addr *inp)
604 struct in_addr inaddr;
606 if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
607 inp->s_addr = inaddr.s_addr;