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