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