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