]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/address_conf.c
Apply fix from Martin Simmons to clear structure before
[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 MMIIII
5  *
6  *     Version $Id$
7  */
8 /*
9    Copyright (C) 2004-2005 Kern Sibbald
10
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.
15
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.
20
21  */
22
23
24 #include "bacula.h"
25 #ifdef HAVE_ARPA_NAMESER_H
26 #include <arpa/nameser.h>
27 #endif
28 #ifdef HAVE_RESOLV_H
29 #include <resolv.h>
30 #endif
31
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);
34
35
36 IPADDR::IPADDR(const IPADDR &src) : type(src.type)
37 {
38   memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
39   saddr  = &saddrbuf.dontuse;
40   saddr4 = &saddrbuf.dontuse4;
41 #ifdef HAVE_IPV6
42   saddr6 = &saddrbuf.dontuse6;
43 #endif
44 }
45
46 IPADDR::IPADDR(int af) : type(R_EMPTY)
47 {
48 #ifdef HAVE_IPV6
49   if (!(af  == AF_INET6 || af  == AF_INET)) {
50      Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
51   }
52 #else
53   if (af != AF_INET) {
54      Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
55   }
56 #endif
57   memset(&saddrbuf, 0, sizeof(saddrbuf));
58   saddr  = &saddrbuf.dontuse;
59   saddr4 = &saddrbuf.dontuse4;
60 #ifdef HAVE_IPV6
61   saddr6 = &saddrbuf.dontuse6;
62 #endif
63   saddr->sa_family = af;
64   if (af  == AF_INET) {
65      saddr4->sin_port = 0xffff;
66   }
67 #ifdef HAVE_IPV6
68   else {
69      saddr6->sin6_port = 0xffff;
70   }
71 #endif
72 #ifdef HAVE_SA_LEN
73 #ifdef HAVE_IPV6
74   saddr->sa_len = (af == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
75 #else
76   saddr->sa_len = sizeof(sockaddr_in);
77 #endif
78 #endif
79    set_addr_any();
80 }
81
82 void IPADDR::set_type(i_type o)
83 {
84    type = o;
85 }
86
87 IPADDR::i_type IPADDR::get_type() const
88 {
89    return type;
90 }
91
92 unsigned short IPADDR::get_port_net_order() const
93 {
94    unsigned short port = 0;
95    if (saddr->sa_family == AF_INET) {
96       port = saddr4->sin_port;
97    }
98 #ifdef HAVE_IPV6
99    else {
100       port = saddr6->sin6_port;
101    }
102 #endif
103     return port;
104 }
105
106 void IPADDR::set_port_net(unsigned short port)
107 {
108    if (saddr->sa_family == AF_INET) {
109       saddr4->sin_port = port;
110    }
111 #ifdef HAVE_IPV6
112    else {
113       saddr6->sin6_port = port;
114    }
115 #endif
116 }
117
118 int IPADDR::get_family() const
119 {
120     return saddr->sa_family;
121 }
122
123 struct sockaddr *IPADDR::get_sockaddr()
124 {
125    return saddr;
126 }
127
128 int IPADDR::get_sockaddr_len()
129 {
130 #ifdef HAVE_IPV6
131    return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
132 #else
133    return sizeof(*saddr4);
134 #endif
135 }
136 void IPADDR::copy_addr(IPADDR *src)
137 {
138    if (saddr->sa_family == AF_INET) {
139       saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
140    }
141 #ifdef HAVE_IPV6
142    else {
143       saddr6->sin6_addr = src->saddr6->sin6_addr;
144    }
145 #endif
146 }
147
148 void IPADDR::set_addr_any()
149 {
150    if (saddr->sa_family == AF_INET) {
151       saddr4->sin_addr.s_addr = INADDR_ANY;
152    }
153 #ifdef HAVE_IPV6
154    else {
155      saddr6->sin6_addr= in6addr_any;
156    }
157 #endif
158 }
159
160 void IPADDR::set_addr4(struct in_addr *ip4)
161 {
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);
164    }
165    saddr4->sin_addr = *ip4;
166 }
167
168 #ifdef HAVE_IPV6
169 void IPADDR::set_addr6(struct in6_addr *ip6)
170 {
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);
173    }
174    saddr6->sin6_addr = *ip6;
175 }
176 #endif
177
178 const char *IPADDR::get_address(char *outputbuf, int outlen)
179 {
180    outputbuf[0] = '\0';
181 #ifdef HAVE_INET_NTOP
182 # ifdef HAVE_IPV6
183    inet_ntop(saddr->sa_family, saddr->sa_family == AF_INET ?
184               (void*)&(saddr4->sin_addr) : (void*)&(saddr6->sin6_addr),
185               outputbuf, outlen);
186 # else
187    inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
188 # endif
189 #else
190    bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
191 #endif
192    return outputbuf;
193 }
194
195 const char *IPADDR::build_address_str(char *buf, int blen)
196 {
197    char tmp[1024];
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());
201    return buf;
202 }
203
204 const char *build_addresses_str(dlist *addrs, char *buf, int blen)
205 {
206    if (!addrs || addrs->size() == 0) {
207       bstrncpy(buf, "", blen);
208       return buf;
209    }
210    char *work = buf;
211    IPADDR *p;
212    foreach_dlist(p, addrs) {
213       char tmp[1024];
214       int len = bsnprintf(work, blen, "%s", p->build_address_str(tmp, sizeof(tmp)));
215       if (len < 0)
216          break;
217       work += len;
218       blen -= len;
219    }
220    return buf;
221 }
222
223 const char *get_first_address(dlist * addrs, char *outputbuf, int outlen)
224 {
225    return ((IPADDR *)(addrs->first()))->get_address(outputbuf, outlen);
226 }
227
228 int get_first_port_net_order(dlist * addrs)
229 {
230    if (!addrs) {
231       return 0;
232    } else {
233       return ((IPADDR *)(addrs->first()))->get_port_net_order();
234    }
235 }
236
237 int get_first_port_host_order(dlist * addrs)
238 {
239    if (!addrs) {
240       return 0;
241    } else {
242       return ((IPADDR *)(addrs->first()))->get_port_host_order();
243    }
244 }
245
246 void init_default_addresses(dlist **out, int port)
247 {
248    char *errstr;
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);
252       free(errstr);
253    }
254 }
255
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)
258 {
259    IPADDR *iaddr;
260    IPADDR *jaddr;
261    dlist *hostaddrs;
262    unsigned short port;
263    IPADDR::i_type intype = type;
264
265    dlist *addrs = (dlist *)(*(out));
266    if (!addrs) {
267       IPADDR *tmp = 0;
268       addrs = *out = New(dlist(tmp, &tmp->link));
269    }
270
271    type = (type == IPADDR::R_SINGLE_PORT
272            || type == IPADDR::R_SINGLE_ADDR) ? IPADDR::R_SINGLE : type;
273    if (type != IPADDR::R_DEFAULT) {
274       IPADDR *def = 0;
275       foreach_dlist(iaddr, addrs) {
276          if (iaddr->get_type() == IPADDR::R_DEFAULT) {
277             def = iaddr;
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"));
282             return 0;
283          }
284       }
285       if (def) {
286          addrs->remove(def);
287          delete def;
288       }
289    }
290
291
292    if (!port_str || port_str[0] == '\0') {
293       port = defaultport;
294    } else {
295       int pnum = atol(port_str);
296       if (0 < pnum && pnum < 0xffff) {
297          port = htons(pnum);
298       } else {
299          struct servent *s = getservbyname(port_str, "tcp");
300          if (s) {
301             port = s->s_port;
302          } else {
303             *errstr = (char *)malloc(1024);
304             bsnprintf(*errstr, 1023, _("can't resolve service(%s)"), port_str);
305             return 0;
306          }
307       }
308    }
309
310    const char *myerrstr;
311    hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
312    if (!hostaddrs) {
313       *errstr = (char *)malloc(1024);
314       bsnprintf(*errstr, 1023, _("can't resolve hostname(%s) %s"), hostname_str,
315                 myerrstr);
316       return 0;
317    }
318
319    if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
320       IPADDR *addr;
321       if (addrs->size()) {
322          addr = (IPADDR *)addrs->first();
323       } else {
324          addr = New(IPADDR(family));
325          addr->set_type(type);
326          addr->set_port_net(defaultport);
327          addr->set_addr_any();
328          addrs->append(addr);
329       }
330       if (intype == IPADDR::R_SINGLE_PORT) {
331          addr->set_port_net(port);
332       }
333       if (intype == IPADDR::R_SINGLE_ADDR) {
334          addr->copy_addr((IPADDR *) (hostaddrs->first()));
335       }
336    } else {
337       foreach_dlist(iaddr, hostaddrs) {
338          IPADDR *clone;
339          /* for duplicates */
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()))
344                 {
345                goto skip;          /* no price */
346             }
347          }
348          clone = New(IPADDR(*iaddr));
349          clone->set_type(type);
350          clone->set_port_net(port);
351          addrs->append(clone);
352        skip:
353          continue;
354       }
355    }
356    free_addresses(hostaddrs);
357    return 1;
358 }
359
360 /*
361  *   my tests
362  *   positiv
363  *   = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
364  *   = { ip = {
365  *         addr = 1.2.3.4; port = 1205; }
366  *     ipv4 = {
367  *         addr = 1.2.3.4; port = http; }
368  *     ipv6 = {
369  *       addr = 1.2.3.4;
370  *       port = 1205;
371  *     }
372  *     ip = {
373  *       addr = 1.2.3.4
374  *       port = 1205
375  *     }
376  *     ip = {
377  *       addr = 1.2.3.4
378  *     }
379  *     ip = {
380  *       addr = 2001:220:222::2
381  *     }
382  *     ip = {
383  *       addr = bluedot.thun.net
384  (     }
385  *   }
386  *   negativ
387  *   = { ip = { } }
388  *   = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
389  *   = { ipv4 { port = 4711 } }
390  */
391 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
392 {
393    int token;
394    enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
395    int exist;
396    char hostname_str[1024];
397    char port_str[128];
398    int family = 0;
399
400
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);
404    }
405
406    token = lex_get_token(lc, T_SKIP_EOL);
407    if (token == T_EOB) {
408       scan_err0(lc, _("Empty addr block is not allowed"));
409    }
410    do {
411       if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
412          scan_err1(lc, _("Expected a string, got: %s"), lc->str);
413       }
414       if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
415          family = AF_INET;
416       }
417 #ifdef HAVE_IPV6
418       else if (strcasecmp("ipv6", lc->str) == 0) {
419          family = AF_INET6;
420       } else {
421          scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
422       }
423 #else
424       else {
425          scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
426       }
427 #endif
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);
431       }
432       token = lex_get_token(lc, T_SKIP_EOL);
433       if (token != T_BOB) {
434          scan_err1(lc, _("Expected a block beginn { , got: %s"), lc->str);
435       }
436       token = lex_get_token(lc, T_SKIP_EOL);
437       exist = EMPTYLINE;
438       port_str[0] = hostname_str[0] = '\0';
439       do {
440          if (token != T_IDENTIFIER) {
441             scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
442          }
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"));
447             }
448             exist |= PORTLINE;
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"));
453             }
454             exist |= ADDRLINE;
455          } else {
456             scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
457          }
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);
461          }
462          token = lex_get_token(lc, T_SKIP_EOL);
463          switch (next_line) {
464          case PORTLINE:
465             if (!
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);
469             }
470             bstrncpy(port_str, lc->str, sizeof(port_str));
471             break;
472          case ADDRLINE:
473             if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
474                scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
475                          lc->str);
476             }
477             bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
478             break;
479          case EMPTYLINE:
480             scan_err0(lc, _("State machine missmatch"));
481             break;
482          }
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);
487       }
488
489       char *errstr;
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);
494            free(errstr);
495         }
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);
500    }
501 }
502
503 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
504 {
505
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 a hostname or IP nummer, got: %s"), lc->str);
509    }
510    char *errstr;
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);
514       free(errstr);
515    }
516 }
517
518 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
519 {
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);
523    }
524    char *errstr;
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);
528       free(errstr);
529    }
530 }
531
532 void free_addresses(dlist * addrs)
533 {
534    while (!addrs->empty()) {
535       IPADDR *ptr = (IPADDR*)addrs->first();
536       addrs->remove(ptr);
537       delete ptr;
538    }
539    delete addrs;
540 }
541
542 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
543 {
544    if (client_addr->sa_family == AF_INET) {
545       return ((struct sockaddr_in *)client_addr)->sin_port;
546    }
547 #ifdef HAVE_IPV6
548    else {
549       return ((struct sockaddr_in6 *)client_addr)->sin6_port;
550    }
551 #endif
552    return -1;
553 }
554
555 int sockaddr_get_port(const struct sockaddr *client_addr)
556 {
557    if (client_addr->sa_family == AF_INET) {
558       return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
559    }
560 #ifdef HAVE_IPV6
561    else {
562       return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
563    }
564 #endif
565    return -1;
566 }
567
568
569 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
570 {
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,
574 # ifdef HAVE_IPV6
575              sa->sa_family == AF_INET ? 
576                  (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
577                  (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
578 # else
579                  (void*)&(((struct sockaddr_in*)sa)->sin_addr),
580 # endif /* HAVE_IPV6 */
581              buf, len);
582 #else
583    bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
584 #endif
585    return buf;
586 }
587
588 #ifdef HAVE_OLD_SOCKOPT
589 int inet_aton(const char *cp, struct in_addr *inp)
590 {
591    struct in_addr inaddr;
592
593    if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
594       inp->s_addr = inaddr.s_addr;
595       return 1;
596    }
597    return 0;
598 }
599 #endif