2 * Configuration file parser for IP-Addresse ipv4 and ipv6
4 * Written by Meno Abels, June MMIIII
9 Copyright (C) 2004-2005 Kern Sibbald
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 version 2 as amended with additional clauses defined in the
14 file LICENSE in the main source directory.
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
19 the file LICENSE for additional details.
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 **errstr);
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;
123 struct sockaddr *IPADDR::get_sockaddr()
128 int IPADDR::get_sockaddr_len()
131 return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
133 return sizeof(*saddr4);
136 void IPADDR::copy_addr(IPADDR *src)
138 if (saddr->sa_family == AF_INET) {
139 saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
143 saddr6->sin6_addr = src->saddr6->sin6_addr;
148 void IPADDR::set_addr_any()
150 if (saddr->sa_family == AF_INET) {
151 saddr4->sin_addr.s_addr = INADDR_ANY;
155 saddr6->sin6_addr= in6addr_any;
160 void IPADDR::set_addr4(struct in_addr *ip4)
162 if (saddr->sa_family != AF_INET) {
163 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv6 address to a ipv4(%d)\n"), saddr->sa_family);
165 saddr4->sin_addr = *ip4;
169 void IPADDR::set_addr6(struct in6_addr *ip6)
171 if (saddr->sa_family != AF_INET6) {
172 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv4 address to a ipv6(%d)\n"), saddr->sa_family);
174 saddr6->sin6_addr = *ip6;
178 const char *IPADDR::get_address(char *outputbuf, int outlen)
181 #ifdef HAVE_INET_NTOP
183 inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
184 (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
187 inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
190 bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
195 const char *IPADDR::build_address_str(char *buf, int blen)
198 bsnprintf(buf, blen, "host[%s:%s:%hu] ",
199 get_family() == AF_INET ? "ipv4" : "ipv6",
200 get_address(tmp, sizeof(tmp) - 1), get_port_host_order());
204 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
206 if (!addrs || addrs->size() == 0) {
207 bstrncpy(buf, "", blen);
212 foreach_dlist(p, addrs) {
214 int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
223 const char *get_first_address(dlist * addrs, char *outputbuf, int outlen)
225 return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
228 int get_first_port_net_order(dlist * addrs)
233 return ((IPADDR *)(addrs->first()))->get_port_net_order();
237 int get_first_port_host_order(dlist * addrs)
242 return ((IPADDR *)(addrs->first()))->get_port_host_order();
246 void init_default_addresses(dlist **out, int port)
249 unsigned short sport = port;
250 if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, &errstr)) {
251 Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), errstr);
256 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
257 const char *hostname_str, const char *port_str, char **errstr)
263 IPADDR::i_type intype = type;
265 dlist *addrs = (dlist *)(*(out));
268 addrs = *out = New(dlist(tmp, &tmp->link));
271 type = (type == IPADDR::R_SINGLE_PORT
272 || type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
273 if (type != IPADDR::R_DEFAULT) {
275 foreach_dlist(iaddr, addrs) {
276 if (iaddr->get_type() == IPADDR::R_DEFAULT) {
278 } else if (iaddr->get_type() != type) {
279 *errstr = (char *)malloc(1024);
280 bsnprintf(*errstr, 1023,
281 _("the old style addresses cannot be mixed with new style"));
292 if (!port_str || port_str[0] == '\0') {
295 int pnum = atol(port_str);
296 if (0 < pnum && pnum < 0xffff) {
299 struct servent *s = getservbyname(port_str, "tcp");
303 *errstr = (char *)malloc(1024);
304 bsnprintf(*errstr, 1023, _("can't resolve service(%s)"), port_str);
310 const char *myerrstr;
311 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
313 *errstr = (char *)malloc(1024);
314 bsnprintf(*errstr, 1023, _("can't resolve hostname(%s) %s"), hostname_str,
319 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
322 addr = (IPADDR *)addrs->first();
324 addr = New(IPADDR(family));
325 addr->set_type(type);
326 addr->set_port_net(defaultport);
327 addr->set_addr_any();
330 if (intype == IPADDR::R_SINGLE_PORT) {
331 addr->set_port_net(port);
333 if (intype == IPADDR::R_SINGLE_ADDR) {
334 addr->copy_addr((IPADDR *) (hostaddrs->first()));
337 foreach_dlist(iaddr, hostaddrs) {
340 foreach_dlist(jaddr, addrs) {
341 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
342 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
343 iaddr->get_sockaddr_len()))
345 goto skip; /* no price */
348 clone = New(IPADDR(*iaddr));
349 clone->set_type(type);
350 clone->set_port_net(port);
351 addrs->append(clone);
356 free_addresses(hostaddrs);
363 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
365 * addr = 1.2.3.4; port = 1205; }
367 * addr = 1.2.3.4; port = http; }
380 * addr = 2001:220:222::2
383 * addr = bluedot.thun.net
388 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
389 * = { ipv4 { port = 4711 } }
391 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
394 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
396 char hostname_str[1024];
401 token = lex_get_token(lc, T_SKIP_EOL);
402 if (token != T_BOB) {
403 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
406 token = lex_get_token(lc, T_SKIP_EOL);
407 if (token == T_EOB) {
408 scan_err0(lc, _("Empty addr block is not allowed"));
411 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
412 scan_err1(lc, _("Expected a string, got: %s"), lc->str);
414 if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
418 else if (strcasecmp("ipv6", lc->str) == 0) {
421 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
425 scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
428 token = lex_get_token(lc, T_SKIP_EOL);
429 if (token != T_EQUALS) {
430 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
432 token = lex_get_token(lc, T_SKIP_EOL);
433 if (token != T_BOB) {
434 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
436 token = lex_get_token(lc, T_SKIP_EOL);
438 port_str[0] = hostname_str[0] = '\0';
440 if (token != T_IDENTIFIER) {
441 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
443 if (strcasecmp("port", lc->str) == 0) {
444 next_line = PORTLINE;
445 if (exist & PORTLINE) {
446 scan_err0(lc, _("Only one port per address block"));
449 } else if (strcasecmp("addr", lc->str) == 0) {
450 next_line = ADDRLINE;
451 if (exist & ADDRLINE) {
452 scan_err0(lc, _("Only one addr per address block"));
456 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
458 token = lex_get_token(lc, T_SKIP_EOL);
459 if (token != T_EQUALS) {
460 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
462 token = lex_get_token(lc, T_SKIP_EOL);
466 (token == T_UNQUOTED_STRING || token == T_NUMBER
467 || token == T_IDENTIFIER)) {
468 scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
470 bstrncpy(port_str, lc->str, sizeof(port_str));
473 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
474 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
477 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
480 scan_err0(lc, _("State machine missmatch"));
483 token = lex_get_token(lc, T_SKIP_EOL);
484 } while (token == T_IDENTIFIER);
485 if (token != T_EOB) {
486 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
490 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
491 htons(item->default_value), family, hostname_str, port_str, &errstr)) {
492 scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
493 hostname_str, port_str, errstr);
496 token = scan_to_next_not_eol(lc);
497 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
498 if (token != T_EOB) {
499 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
503 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
506 int token = lex_get_token(lc, T_SKIP_EOL);
507 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
508 scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
511 if (pass == 1 && !add_address((dlist **) (item->value), IPADDR::R_SINGLE_ADDR,
512 htons(item->default_value), AF_INET, lc->str, 0, &errstr)) {
513 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
518 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
520 int token = lex_get_token(lc, T_SKIP_EOL);
521 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
522 scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
525 if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
526 htons(item->default_value), AF_INET, 0, lc->str, &errstr)) {
527 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
532 void free_addresses(dlist * addrs)
534 while (!addrs->empty()) {
535 IPADDR *ptr = (IPADDR*)addrs->first();
542 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
544 if (client_addr->sa_family == AF_INET) {
545 return ((struct sockaddr_in *)client_addr)->sin_port;
549 return ((struct sockaddr_in6 *)client_addr)->sin6_port;
555 int sockaddr_get_port(const struct sockaddr *client_addr)
557 if (client_addr->sa_family == AF_INET) {
558 return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
562 return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
569 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
571 #ifdef HAVE_INET_NTOP
572 /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
573 inet_ntop(sa->sa_family,
575 sa->sa_family == AF_INET ?
576 (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
577 (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
579 (void*)&(((struct sockaddr_in*)sa)->sin_addr),
580 # endif /* HAVE_IPV6 */
583 bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
588 #ifdef HAVE_OLD_SOCKOPT
589 int inet_aton(const char *cp, struct in_addr *inp)
591 struct in_addr inaddr;
593 if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
594 inp->s_addr = inaddr.s_addr;