]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/address_conf.c
Add support for new POSIX getaddrinfo interface.
[bacula/bacula] / bacula / src / lib / address_conf.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2004-2011 Free Software Foundation Europe e.V.
5
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
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  *   Configuration file parser for IP-Addresse ipv4 and ipv6
30  *
31  *     Written by Meno Abels, June MMIV
32  *
33  */
34
35
36 #include "bacula.h"
37 #ifdef HAVE_ARPA_NAMESER_H
38 #include <arpa/nameser.h>
39 #endif
40 #ifdef HAVE_RESOLV_H
41 //#include <resolv.h>
42 #endif
43
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);
46
47
48 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
49 {
50   memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
51   saddr  = &saddrbuf.dontuse;
52   saddr4 = &saddrbuf.dontuse4;
53 #ifdef HAVE_IPV6
54   saddr6 = &saddrbuf.dontuse6;
55 #endif
56 }
57
58 IPADDR::IPADDR(int af) : type(R_EMPTY)
59 {
60 #ifdef HAVE_IPV6
61   if (!(af == AF_INET6 || af == AF_INET)) {
62      Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
63   }
64 #else
65   if (af != AF_INET) {
66      Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
67   }
68 #endif
69   memset(&saddrbuf, 0, sizeof(saddrbuf));
70   saddr  = &saddrbuf.dontuse;
71   saddr4 = &saddrbuf.dontuse4;
72 #ifdef HAVE_IPV6
73   saddr6 = &saddrbuf.dontuse6;
74 #endif
75   saddr->sa_family = af;
76   if (af  == AF_INET) {
77      saddr4->sin_port = 0xffff;
78   }
79 #ifdef HAVE_IPV6
80   else {
81      saddr6->sin6_port = 0xffff;
82   }
83 #endif
84 #ifdef HAVE_SA_LEN
85 #ifdef HAVE_IPV6
86   saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
87 #else
88   saddr->sa_len = sizeof(sockaddr_in);
89 #endif
90 #endif
91    set_addr_any();
92 }
93
94 void IPADDR::set_type(i_type o)
95 {
96    type = o;
97 }
98
99 IPADDR::i_type IPADDR::get_type() const
100 {
101    return type;
102 }
103
104 unsigned short IPADDR::get_port_net_order() const
105 {
106    unsigned short port = 0;
107    if (saddr->sa_family == AF_INET) {
108       port = saddr4->sin_port;
109    }
110 #ifdef HAVE_IPV6
111    else {
112       port = saddr6->sin6_port;
113    }
114 #endif
115     return port;
116 }
117
118 void IPADDR::set_port_net(unsigned short port)
119 {
120    if (saddr->sa_family == AF_INET) {
121       saddr4->sin_port = port;
122    }
123 #ifdef HAVE_IPV6
124    else {
125       saddr6->sin6_port = port;
126    }
127 #endif
128 }
129
130 int IPADDR::get_family() const
131 {
132     return saddr->sa_family;
133 }
134
135 struct sockaddr *IPADDR::get_sockaddr()
136 {
137    return saddr;
138 }
139
140 int IPADDR::get_sockaddr_len()
141 {
142 #ifdef HAVE_IPV6
143    return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
144 #else
145    return sizeof(*saddr4);
146 #endif
147 }
148 void IPADDR::copy_addr(IPADDR *src)
149 {
150    if (saddr->sa_family == AF_INET) {
151       saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
152    }
153 #ifdef HAVE_IPV6
154    else {
155       saddr6->sin6_addr = src->saddr6->sin6_addr;
156    }
157 #endif
158 }
159
160 void IPADDR::set_addr_any()
161 {
162    if (saddr->sa_family == AF_INET) {
163       saddr4->sin_addr.s_addr = INADDR_ANY;
164    }
165 #ifdef HAVE_IPV6
166    else {
167      saddr6->sin6_addr= in6addr_any;
168    }
169 #endif
170 }
171
172 void IPADDR::set_addr4(struct in_addr *ip4)
173 {
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);
176    }
177    saddr4->sin_addr = *ip4;
178 }
179
180 #ifdef HAVE_IPV6
181 void IPADDR::set_addr6(struct in6_addr *ip6)
182 {
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);
185    }
186    saddr6->sin6_addr = *ip6;
187 }
188 #endif
189
190 const char *IPADDR::get_address(char *outputbuf, int outlen)
191 {
192    outputbuf[0] = '\0';
193 #ifdef HAVE_INET_NTOP
194 # ifdef HAVE_IPV6
195    inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
196               (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
197               outputbuf, outlen);
198 # else
199    inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
200 # endif
201 #else
202    bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
203 #endif
204    return outputbuf;
205 }
206
207 const char *IPADDR::build_address_str(char *buf, int blen)
208 {
209    char tmp[1024];
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());
213    return buf;
214 }
215
216 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
217 {
218    if (!addrs || addrs->size() == 0) {
219       bstrncpy(buf, "", blen);
220       return buf;
221    }
222    char *work = buf;
223    IPADDR *p;
224    foreach_dlist(p, addrs) {
225       char tmp[1024];
226       int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
227       if (len < 0)
228          break;
229       work += len;
230       blen -= len;
231    }
232    return buf;
233 }
234
235 const char *get_first_address(dlist *addrs, char *outputbuf, int outlen)
236 {
237    return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
238 }
239
240 int get_first_port_net_order(dlist *addrs)
241 {
242    if (!addrs) {
243       return 0;
244    } else {
245       return ((IPADDR *)(addrs->first()))->get_port_net_order();
246    }
247 }
248
249 int get_first_port_host_order(dlist *addrs)
250 {
251    if (!addrs) {
252       return 0;
253    } else {
254       return ((IPADDR *)(addrs->first()))->get_port_host_order();
255    }
256 }
257
258 void init_default_addresses(dlist **out, int port)
259 {
260    char buf[1024];
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);
264    }
265 }
266
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)
269 {
270    IPADDR *iaddr;
271    IPADDR *jaddr;
272    dlist *hostaddrs;
273    unsigned short port;
274    IPADDR::i_type intype = type;
275
276    buf[0] = 0;
277    dlist *addrs = (dlist *)(*(out));
278    if (!addrs) {
279       IPADDR *tmp = 0;
280       addrs = *out = New(dlist(tmp, &tmp->link));
281    }
282
283    type = (type == IPADDR::R_SINGLE_PORT
284            || type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
285    if (type != IPADDR::R_DEFAULT) {
286       IPADDR *def = 0;
287       foreach_dlist(iaddr, addrs) {
288          if (iaddr->get_type() == IPADDR::R_DEFAULT) {
289             def = iaddr;
290          } else if (iaddr->get_type() != type) {
291             bsnprintf(buf, buflen,
292                       _("the old style addresses cannot be mixed with new style"));
293             return 0;
294          }
295       }
296       if (def) {
297          addrs->remove(def);
298          delete def;
299       }
300    }
301
302    if (!port_str || port_str[0] == '\0') {
303       port = defaultport;
304    } else {
305       int pnum = atol(port_str);
306       if (0 < pnum && pnum < 0xffff) {
307          port = htons(pnum);
308       } else {
309          struct servent *s = getservbyname(port_str, "tcp");
310          if (s) {
311             port = s->s_port;
312          } else {
313             bsnprintf(buf, buflen, _("can't resolve service(%s)"), port_str);
314             return 0;
315          }
316       }
317    }
318
319    const char *myerrstr;
320    hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
321    if (!hostaddrs) {
322       bsnprintf(buf, buflen, _("can't resolve hostname(%s) %s"), hostname_str,
323                 myerrstr);
324       return 0;
325    }
326
327    if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
328       IPADDR *addr;
329       if (addrs->size()) {
330          addr = (IPADDR *)addrs->first();
331       } else {
332          addr = New(IPADDR(family));
333          addr->set_type(type);
334          addr->set_port_net(defaultport);
335          addr->set_addr_any();
336          addrs->append(addr);
337       }
338       if (intype == IPADDR::R_SINGLE_PORT) {
339          addr->set_port_net(port);
340       }
341       if (intype == IPADDR::R_SINGLE_ADDR) {
342          addr->copy_addr((IPADDR *)(hostaddrs->first()));
343       }
344    } else {
345       foreach_dlist(iaddr, hostaddrs) {
346          IPADDR *clone;
347          /* for duplicates */
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()))
352                 {
353                goto skip;          /* no price */
354             }
355          }
356          clone = New(IPADDR(*iaddr));
357          clone->set_type(type);
358          clone->set_port_net(port);
359          addrs->append(clone);
360        skip:
361          continue;
362       }
363    }
364    free_addresses(hostaddrs);
365    return 1;
366 }
367
368 /*
369  *   my tests
370  *   positiv
371  *   = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
372  *   = { ip = {
373  *         addr = 1.2.3.4; port = 1205; }
374  *     ipv4 = {
375  *         addr = 1.2.3.4; port = http; }
376  *     ipv6 = {
377  *       addr = 1.2.3.4;
378  *       port = 1205;
379  *     }
380  *     ip = {
381  *       addr = 1.2.3.4
382  *       port = 1205
383  *     }
384  *     ip = {
385  *       addr = 1.2.3.4
386  *     }
387  *     ip = {
388  *       addr = 2001:220:222::2
389  *     }
390  *     ip = {
391  *       addr = bluedot.thun.net
392  (     }
393  *   }
394  *   negativ
395  *   = { ip = { } }
396  *   = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
397  *   = { ipv4 { port = 4711 } }
398  */
399 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
400 {
401    int token;
402    enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
403    int exist;
404    char hostname_str[1024];
405    char port_str[128];
406    int family = 0;
407    char errmsg[1024];
408
409
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);
413    }
414
415    token = lex_get_token(lc, T_SKIP_EOL);
416    if (token == T_EOB) {
417       scan_err0(lc, _("Empty addr block is not allowed"));
418    }
419    do {
420       if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
421          scan_err1(lc, _("Expected a string, got: %s"), lc->str);
422       }
423       if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
424          family = AF_INET;
425       }
426 #ifdef HAVE_IPV6
427       else if (strcasecmp("ipv6", lc->str) == 0) {
428          family = AF_INET6;
429       } else {
430          scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
431       }
432 #else
433       else {
434          scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
435       }
436 #endif
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);
440       }
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);
444       }
445       token = lex_get_token(lc, T_SKIP_EOL);
446       exist = EMPTYLINE;
447       port_str[0] = hostname_str[0] = '\0';
448       do {
449          if (token != T_IDENTIFIER) {
450             scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
451          }
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"));
456             }
457             exist |= PORTLINE;
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"));
462             }
463             exist |= ADDRLINE;
464          } else {
465             scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
466          }
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);
470          }
471          token = lex_get_token(lc, T_SKIP_EOL);
472          switch (next_line) {
473          case PORTLINE:
474             if (!
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);
478             }
479             bstrncpy(port_str, lc->str, sizeof(port_str));
480             break;
481          case ADDRLINE:
482             if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
483                scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
484                          lc->str);
485             }
486             bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
487             break;
488          case EMPTYLINE:
489             scan_err0(lc, _("State machine missmatch"));
490             break;
491          }
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);
496       }
497
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);
503         }
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);
508    }
509 }
510
511 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
512 {
513    char errmsg[1024];
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);
517    }
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);
522    }
523 }
524
525 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
526 {
527    char errmsg[1024];
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);
531    }
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);
536    }
537 }
538
539 void free_addresses(dlist * addrs)
540 {
541    while (!addrs->empty()) {
542       IPADDR *ptr = (IPADDR*)addrs->first();
543       addrs->remove(ptr);
544       delete ptr;
545    }
546    delete addrs;
547 }
548
549 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
550 {
551    if (client_addr->sa_family == AF_INET) {
552       return ((struct sockaddr_in *)client_addr)->sin_port;
553    }
554 #ifdef HAVE_IPV6
555    else {
556       return ((struct sockaddr_in6 *)client_addr)->sin6_port;
557    }
558 #endif
559    return -1;
560 }
561
562 int sockaddr_get_port(const struct sockaddr *client_addr)
563 {
564    if (client_addr->sa_family == AF_INET) {
565       return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
566    }
567 #ifdef HAVE_IPV6
568    else {
569       return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
570    }
571 #endif
572    return -1;
573 }
574
575
576 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
577 {
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,
581 # ifdef HAVE_IPV6
582              sa->sa_family == AF_INET ? 
583                  (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
584                  (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
585 # else
586                  (void*)&(((struct sockaddr_in*)sa)->sin_addr),
587 # endif /* HAVE_IPV6 */
588              buf, len);
589 #else
590    bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
591 #endif
592    return buf;
593 }
594
595 #ifdef HAVE_OLD_SOCKOPT
596 int inet_aton(const char *cp, struct in_addr *inp)
597 {
598    struct in_addr inaddr;
599
600    if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
601       inp->s_addr = inaddr.s_addr;
602       return 1;
603    }
604    return 0;
605 }
606 #endif