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,
31 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
33 memcpy(&buf, &src.buf, sizeof(buf));
35 saddr4 = &buf.dontuse4;
37 saddr6 = &buf.dontuse6;
41 IPADDR::IPADDR(int af) : type(R_EMPTY)
43 if (!(af == AF_INET6 || af == AF_INET)) {
44 Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported(%d)\n"), af);
47 saddr4 = &buf.dontuse4;
49 saddr6 = &buf.dontuse6;
51 saddr->sa_family = af;
53 saddr4->sin_port = 0xffff;
57 saddr6->sin6_port = 0xffff;
62 saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
64 saddr->sa_len = sizeof(sockaddr_in);
70 void IPADDR::set_type(i_type o)
75 IPADDR::i_type IPADDR::get_type() const
80 unsigned short IPADDR::get_port() const
82 unsigned short port = 0;
83 if (saddr->sa_family == AF_INET) {
84 port = saddr4->sin_port;
88 port = saddr6->sin6_port;
94 void IPADDR::set_port(unsigned short port)
96 if (saddr->sa_family == AF_INET) {
97 saddr4->sin_port = port;
101 saddr6->sin6_port = port;
106 int IPADDR::get_family() const
108 return saddr->sa_family;
111 struct sockaddr *IPADDR::get_sockaddr()
116 int IPADDR::get_sockaddr_len()
118 return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
120 void IPADDR::copy_addr(IPADDR *src)
122 if (saddr->sa_family == AF_INET) {
123 saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
127 saddr6->sin6_addr = src->saddr6->sin6_addr;
132 void IPADDR::set_addr_any()
134 if (saddr->sa_family == AF_INET) {
135 saddr4->sin_addr.s_addr = INADDR_ANY;
139 saddr6->sin6_addr= in6addr_any;
144 void IPADDR::set_addr4(struct in_addr *ip4)
146 if (saddr->sa_family != AF_INET) {
147 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv6 address to a ipv4(%d)\n"), saddr->sa_family);
149 saddr4->sin_addr = *ip4;
153 void IPADDR::set_addr6(struct in6_addr *ip6)
155 if (saddr->sa_family != AF_INET6) {
156 Emsg1(M_ERROR_TERM, 0, _("It was tried to assign a ipv4 address to a ipv6(%d)\n"), saddr->sa_family);
158 saddr6->sin6_addr = *ip6;
162 const char *IPADDR::get_address(char *outputbuf, int outlen)
165 #if defined(HAVE_INET_NTOP) && defined(HAVE_IPV6)
166 inet_ntop(saddr->sa_family,
167 saddr->sa_family == AF_INET ?
168 (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
172 strcpy(outputbuf, inet_ntoa(saddr4->sin_addr));
178 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
180 if (!addrs->size()) {
181 bstrncpy(buf, "", blen);
186 foreach_dlist(p, addrs) {
188 int len = snprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
197 const char *get_first_address(dlist * addrs, char *outputbuf, int outlen)
199 return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
202 int get_first_port(dlist * addrs)
204 return ((IPADDR *)(addrs->first()))->get_port();
207 static int skip_to_next_not_eol(LEX * lc)
212 token = lex_get_token(lc, T_ALL);
213 } while (token == T_EOL);
218 void init_default_addresses(dlist ** out, int port)
221 unsigned short sport = port;
222 if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, &errstr)) {
223 Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), errstr);
228 int add_address(dlist ** out, IPADDR::i_type type, unsigned short defaultport, int family,
229 const char *hostname_str, const char *port_str, char **errstr)
235 IPADDR::i_type intype = type;
237 dlist *addrs = (dlist *) (*(out));
240 addrs = *out = new dlist(tmp, &tmp->link);
243 type = (type == IPADDR::R_SINGLE_PORT
244 || type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
245 if (type != IPADDR::R_DEFAULT) {
247 foreach_dlist(iaddr, addrs) {
248 if (iaddr->get_type() == IPADDR::R_DEFAULT) {
250 } else if (iaddr->get_type() != type) {
251 *errstr = (char *)malloc(1024);
252 bsnprintf(*errstr, 1023,
253 "the old style addresses could mixed with new style");
264 if (!port_str || port_str[0] == '\0') {
267 int pnum = atol(port_str);
268 if (0 < pnum && pnum < 0xffff) {
271 struct servent *s = getservbyname(port_str, "tcp");
275 *errstr = (char *)malloc(1024);
276 bsnprintf(*errstr, 1023, "can't resolve service(%s)", port_str);
282 const char *myerrstr;
283 hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
285 *errstr = (char *)malloc(1024);
286 bsnprintf(*errstr, 1023, "can't resolve hostname(%s) %s", hostname_str,
291 if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
294 addr = (IPADDR *) addrs->first();
296 addr = new IPADDR(family);
297 addr->set_type(type);
298 addr->set_port(defaultport);
299 addr->set_addr_any();
302 if (intype == IPADDR::R_SINGLE_PORT) {
303 addr->set_port(port);
305 if (intype == IPADDR::R_SINGLE_ADDR) {
306 addr->copy_addr((IPADDR *) (hostaddrs->first()));
309 foreach_dlist(iaddr, hostaddrs) {
312 foreach_dlist(jaddr, addrs) {
313 if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
314 !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
315 iaddr->get_sockaddr_len()))
317 goto skip; /* no price */
320 clone = new IPADDR(*iaddr);
321 clone->set_type(type);
322 clone->set_port(port);
323 addrs->append(clone);
328 free_addresses(hostaddrs);
332 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
335 enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
337 char hostname_str[1024];
342 * = { [[ip|ipv4|ipv6] = { [[addr|port] = [^ ]+[\n;]+] }]+ }
345 * = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
347 * addr = 1.2.3.4; port = 1205; }
349 * addr = 1.2.3.4; port = http; }
362 * addr = 2001:220:222::2
365 * addr = bluedot.thun.net
370 * = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
371 * = { ipv4 { port = 4711 } }
374 token = skip_to_next_not_eol(lc);
375 if (token != T_BOB) {
376 scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
379 token = skip_to_next_not_eol(lc);
380 if (token == T_EOB) {
381 scan_err0(lc, _("Empty addr block is not allowed"));
384 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
385 scan_err1(lc, _("Expected a string, got: %s"), lc->str);
387 if (!strcmp("ip", lc->str) || !strcmp("ipv4", lc->str)) {
391 else if (!strcmp("ipv6", lc->str)) {
396 scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
398 token = skip_to_next_not_eol(lc);
399 if (token != T_EQUALS) {
400 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
402 token = skip_to_next_not_eol(lc);
403 if (token != T_BOB) {
404 scan_err1(lc, _("Expected a block beginn { , got: %s"), lc->str);
406 token = skip_to_next_not_eol(lc);
408 port_str[0] = hostname_str[0] = '\0';
410 if (token != T_IDENTIFIER) {
411 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
413 if (!strcmp("port", lc->str)) {
414 next_line = PORTLINE;
415 if (exist & PORTLINE) {
416 scan_err0(lc, _("Only one port per address block"));
419 } else if (!strcmp("addr", lc->str)) {
420 next_line = ADDRLINE;
421 if (exist & ADDRLINE) {
422 scan_err0(lc, _("Only one addr per address block"));
426 scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
428 token = lex_get_token(lc, T_ALL);
429 if (token != T_EQUALS) {
430 scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
432 token = lex_get_token(lc, T_ALL);
436 (token == T_UNQUOTED_STRING || token == T_NUMBER
437 || token == T_IDENTIFIER)) {
438 scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
440 bstrncpy(port_str, lc->str, sizeof(port_str));
443 if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
444 scan_err1(lc, _("Expected a ipnumber or a hostname, got: %s"),
447 bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
450 scan_err0(lc, _("Statemachine missmatch"));
453 token = skip_to_next_not_eol(lc);
454 } while (token == T_IDENTIFIER);
455 if (token != T_EOB) {
456 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
461 ((dlist **) (item->value), IPADDR::R_MULTIPLE, htons(item->default_value),
462 family, hostname_str, port_str, &errstr)) {
463 scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
464 hostname_str, port_str, errstr);
467 token = skip_to_next_not_eol(lc);
468 } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
469 if (token != T_EOB) {
470 scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
474 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
476 int token = lex_get_token(lc, T_ALL);
477 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
478 scan_err1(lc, _("Expected a hostname or ipnummer, got: %s"), lc->str);
481 if (!add_address((dlist **) (item->value), IPADDR::R_SINGLE_ADDR,
482 htons(item->default_value), AF_INET, lc->str, 0, &errstr)) {
483 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
488 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
490 int token = lex_get_token(lc, T_ALL);
491 if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
492 scan_err1(lc, _("Expected a port nummer or string, got: %s"), lc->str);
495 if (!add_address((dlist **) (item->value), IPADDR::R_SINGLE_PORT,
496 htons(item->default_value), AF_INET, 0, lc->str, &errstr)) {
497 scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errstr);
502 void free_addresses(dlist * addrs)
504 while (!addrs->empty()) {
505 IPADDR *ptr = (IPADDR*)addrs->first();