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