2 * Configuration file parser for IP-Addresse ipv4 and ipv6
4 * Written by Meno Abels, June MMIIII
9 Copyright (C) 2004 Kern Sibbald and John Walker
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of
14 the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public
22 License along with this program; if not, write to the Free
23 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 #ifdef HAVE_ARPA_NAMESER_H
31 #include <arpa/nameser.h>
37 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
38 const char *hostname_str, const char *port_str, char **errstr);
41 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
43 memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
44 saddr = &saddrbuf.dontuse;
45 saddr4 = &saddrbuf.dontuse4;
47 saddr6 = &saddrbuf.dontuse6;
51 IPADDR::IPADDR(int af) : type(R_EMPTY)
54 if (!(af == AF_INET6 || af == AF_INET)) {
55 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
59 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
62 saddr = &saddrbuf.dontuse;
63 saddr4 = &saddrbuf.dontuse4;
65 saddr6 = &saddrbuf.dontuse6;
67 saddr->sa_family = af;
69 saddr4->sin_port = 0xffff;
73 saddr6->sin6_port = 0xffff;
78 saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
80 saddr->sa_len = sizeof(sockaddr_in);
86 void IPADDR::set_type(i_type o)
91 IPADDR::i_type IPADDR::get_type() const
96 unsigned short IPADDR::get_port_net_order() const
98 unsigned short port = 0;
99 if (saddr->sa_family == AF_INET) {
100 port = saddr4->sin_port;
104 port = saddr6->sin6_port;
110 void IPADDR::set_port_net(unsigned short port)
112 if (saddr->sa_family == AF_INET) {
113 saddr4->sin_port = port;
117 saddr6->sin6_port = port;
122 int IPADDR::get_family() const
124 return saddr->sa_family;
127 struct sockaddr *IPADDR::get_sockaddr()
132 int IPADDR::get_sockaddr_len()
135 return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
137 return sizeof(*saddr4);
140 void IPADDR::copy_addr(IPADDR *src)
142 if (saddr->sa_family == AF_INET) {
143 saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
147 saddr6->sin6_addr = src->saddr6->sin6_addr;
152 void IPADDR::set_addr_any()
154 if (saddr->sa_family == AF_INET) {
155 saddr4->sin_addr.s_addr = INADDR_ANY;
159 saddr6->sin6_addr= in6addr_any;
164 void IPADDR::set_addr4(struct in_addr *ip4)
166 if (saddr->sa_family != AF_INET) {
167 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv6 address to a ipv4(%d)\n"), saddr->sa_family);
169 saddr4->sin_addr = *ip4;
173 void IPADDR::set_addr6(struct in6_addr *ip6)
175 if (saddr->sa_family != AF_INET6) {
176 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv4 address to a ipv6(%d)\n"), saddr->sa_family);
178 saddr6->sin6_addr = *ip6;
182 const char *IPADDR::get_address(char *outputbuf, int outlen)
185 #ifdef HAVE_INET_NTOP
187 inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
188 (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
191 inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
194 bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
199 const char *IPADDR::build_address_str(char *buf, int blen)
202 bsnprintf(buf, blen, "host[%s:%s:%hu] ",
203 get_family() == AF_INET ? "ipv4" : "ipv6",
204 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
208 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
210 if (!addrs || addrs->size() == 0) {
211 bstrncpy(buf, "", blen);
216 foreach_dlist(p, addrs) {
218 int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
227 const char *get_first_address(dlist * addrs, char *outputbuf, int outlen)
229 return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
232 int get_first_port_net_order(dlist * addrs)
237 return ((IPADDR *)(addrs->first()))->get_port_net_order();
241 int get_first_port_host_order(dlist * addrs)
246 return ((IPADDR *)(addrs->first()))->get_port_host_order();
250 void init_default_addresses(dlist **out, int port)
253 unsigned short sport = port;
254 if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, &errstr)) {
255 Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), errstr);
260 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
261 const char *hostname_str, const char *port_str, char **errstr)
267 IPADDR::i_type intype = type;
269 dlist *addrs = (dlist *)(*(out));
272 addrs = *out = New(dlist(tmp, &tmp->link));
275 type = (type == IPADDR::R_SINGLE_PORT
276 || type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
277 if (type != IPADDR::R_DEFAULT) {
279 foreach_dlist(iaddr, addrs) {
280 if (iaddr->get_type() == IPADDR::R_DEFAULT) {
282 } else if (iaddr->get_type() != type) {
283 *errstr = (char *)malloc(1024);
284 bsnprintf(*errstr, 1023,
285 _("the old style addresses cannot be mixed with new style"));
296 if (!port_str || port_str[0] == '\0') {
299 int pnum = atol(port_str);
300 if (0 < pnum && pnum < 0xffff) {
303 struct servent *s = getservbyname(port_str, "tcp");
307 *errstr = (char *)malloc(1024);
308 bsnprintf(*errstr, 1023, _("can't resolve service(%s)"), port_str);
314 const char *myerrstr;
315 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
317 *errstr = (char *)malloc(1024);
318 bsnprintf(*errstr, 1023, _("can't resolve hostname(%s) %s"), hostname_str,
323 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
326 addr = (IPADDR *)addrs->first();
328 addr = New(IPADDR(family));
329 addr->set_type(type);
330 addr->set_port_net(defaultport);
331 addr->set_addr_any();
334 if (intype == IPADDR::R_SINGLE_PORT) {
335 addr->set_port_net(port);
337 if (intype == IPADDR::R_SINGLE_ADDR) {
338 addr->copy_addr((IPADDR *) (hostaddrs->first()));
341 foreach_dlist(iaddr, hostaddrs) {
344 foreach_dlist(jaddr, addrs) {
345 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
346 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
347 iaddr->get_sockaddr_len()))
349 goto skip; /* no price */
352 clone = New(IPADDR(*iaddr));
353 clone->set_type(type);
354 clone->set_port_net(port);
355 addrs->append(clone);
360 free_addresses(hostaddrs);
367 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
369 * addr = 1.2.3.4; port = 1205; }
371 * addr = 1.2.3.4; port = http; }
384 * addr = 2001:220:222::2
387 * addr = bluedot.thun.net
392 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
393 * = { ipv4 { port = 4711 } }
395 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
398 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
400 char hostname_str[1024];
405 token = lex_get_token(lc, T_SKIP_EOL);
406 if (token != T_BOB) {
407 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
410 token = lex_get_token(lc, T_SKIP_EOL);
411 if (token == T_EOB) {
412 scan_err0(lc, _("Empty addr block is not allowed"));
415 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
416 scan_err1(lc, _("Expected a string, got: %s"), lc->str);
418 if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
422 else if (strcasecmp("ipv6", lc->str) == 0) {
425 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
429 scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
432 token = lex_get_token(lc, T_SKIP_EOL);
433 if (token != T_EQUALS) {
434 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
436 token = lex_get_token(lc, T_SKIP_EOL);
437 if (token != T_BOB) {
438 scan_err1(lc, _("Expected a block beginn { , got: %s"), lc->str);
440 token = lex_get_token(lc, T_SKIP_EOL);
442 port_str[0] = hostname_str[0] = '\0';
444 if (token != T_IDENTIFIER) {
445 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
447 if (strcasecmp("port", lc->str) == 0) {
448 next_line = PORTLINE;
449 if (exist & PORTLINE) {
450 scan_err0(lc, _("Only one port per address block"));
453 } else if (strcasecmp("addr", lc->str) == 0) {
454 next_line = ADDRLINE;
455 if (exist & ADDRLINE) {
456 scan_err0(lc, _("Only one addr per address block"));
460 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
462 token = lex_get_token(lc, T_SKIP_EOL);
463 if (token != T_EQUALS) {
464 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
466 token = lex_get_token(lc, T_SKIP_EOL);
470 (token == T_UNQUOTED_STRING || token == T_NUMBER
471 || token == T_IDENTIFIER)) {
472 scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
474 bstrncpy(port_str, lc->str, sizeof(port_str));
477 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
478 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
481 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
484 scan_err0(lc, _("State machine missmatch"));
487 token = lex_get_token(lc, T_SKIP_EOL);
488 } while (token == T_IDENTIFIER);
489 if (token != T_EOB) {
490 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
494 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
495 htons(item->default_value), family, hostname_str, port_str, &errstr)) {
496 scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
497 hostname_str, port_str, errstr);
500 token = scan_to_next_not_eol(lc);
501 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
502 if (token != T_EOB) {
503 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
507 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
510 int token = lex_get_token(lc, T_SKIP_EOL);
511 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
512 scan_err1(lc, _("Expected a hostname or IP nummer, got: %s"), lc->str);
515 if (pass == 1 && !add_address((dlist **) (item->value), IPADDR::R_SINGLE_ADDR,
516 htons(item->default_value), AF_INET, lc->str, 0, &errstr)) {
517 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
522 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
524 int token = lex_get_token(lc, T_SKIP_EOL);
525 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
526 scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
529 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
530 htons(item->default_value), AF_INET, 0, lc->str, &errstr)) {
531 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
536 void free_addresses(dlist * addrs)
538 while (!addrs->empty()) {
539 IPADDR *ptr = (IPADDR*)addrs->first();
546 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
548 if (client_addr->sa_family == AF_INET) {
549 return ((struct sockaddr_in *)client_addr)->sin_port;
553 return ((struct sockaddr_in6 *)client_addr)->sin6_port;
559 int sockaddr_get_port(const struct sockaddr *client_addr)
561 if (client_addr->sa_family == AF_INET) {
562 return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
566 return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
573 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
575 #ifdef HAVE_INET_NTOP
576 /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
577 inet_ntop(sa->sa_family,
579 sa->sa_family == AF_INET ?
580 (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
581 (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
583 (void*)&(((struct sockaddr_in*)sa)->sin_addr),
584 # endif /* HAVE_IPV6 */
587 bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
592 #ifdef HAVE_OLD_SOCKOPT
593 int inet_aton(const char *cp, struct in_addr *inp)
595 struct in_addr inaddr;
597 if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
598 inp->s_addr = inaddr.s_addr;