]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/address_conf.c
Remove configure check for resolv.h -- it is apparently not needed
[bacula/bacula] / bacula / src / lib / address_conf.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2004-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark ofJohn Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *   Configuration file parser for IP-Addresse ipv4 and ipv6
30  *
31  *     Written by Meno Abels, June MMIV
32  *
33  *     Version $Id$
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 *buf, int buflen);
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 buf[1024];
262    unsigned short sport = port;
263    if (!add_address(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf, sizeof(buf))) {
264       Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), buf);
265    }
266 }
267
268 static int add_address(dlist **out, IPADDR::i_type type, unsigned short defaultport, int family,
269                 const char *hostname_str, const char *port_str, char *buf, int buflen)
270 {
271    IPADDR *iaddr;
272    IPADDR *jaddr;
273    dlist *hostaddrs;
274    unsigned short port;
275    IPADDR::i_type intype = type;
276
277    buf[0] = 0;
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             bsnprintf(buf, buflen,
293                       _("the old style addresses cannot be mixed with new style"));
294             return 0;
295          }
296       }
297       if (def) {
298          addrs->remove(def);
299          delete def;
300       }
301    }
302
303    if (!port_str || port_str[0] == '\0') {
304       port = defaultport;
305    } else {
306       int pnum = atol(port_str);
307       if (0 < pnum && pnum < 0xffff) {
308          port = htons(pnum);
309       } else {
310          struct servent *s = getservbyname(port_str, "tcp");
311          if (s) {
312             port = s->s_port;
313          } else {
314             bsnprintf(buf, buflen, _("can't resolve service(%s)"), port_str);
315             return 0;
316          }
317       }
318    }
319
320    const char *myerrstr;
321    hostaddrs = bnet_host2ipaddrs(hostname_str, family, &myerrstr);
322    if (!hostaddrs) {
323       bsnprintf(buf, buflen, _("can't resolve hostname(%s) %s"), hostname_str,
324                 myerrstr);
325       return 0;
326    }
327
328    if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
329       IPADDR *addr;
330       if (addrs->size()) {
331          addr = (IPADDR *)addrs->first();
332       } else {
333          addr = New(IPADDR(family));
334          addr->set_type(type);
335          addr->set_port_net(defaultport);
336          addr->set_addr_any();
337          addrs->append(addr);
338       }
339       if (intype == IPADDR::R_SINGLE_PORT) {
340          addr->set_port_net(port);
341       }
342       if (intype == IPADDR::R_SINGLE_ADDR) {
343          addr->copy_addr((IPADDR *)(hostaddrs->first()));
344       }
345    } else {
346       foreach_dlist(iaddr, hostaddrs) {
347          IPADDR *clone;
348          /* for duplicates */
349          foreach_dlist(jaddr, addrs) {
350             if (iaddr->get_sockaddr_len() == jaddr->get_sockaddr_len() &&
351             !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
352                     iaddr->get_sockaddr_len()))
353                 {
354                goto skip;          /* no price */
355             }
356          }
357          clone = New(IPADDR(*iaddr));
358          clone->set_type(type);
359          clone->set_port_net(port);
360          addrs->append(clone);
361        skip:
362          continue;
363       }
364    }
365    free_addresses(hostaddrs);
366    return 1;
367 }
368
369 /*
370  *   my tests
371  *   positiv
372  *   = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
373  *   = { ip = {
374  *         addr = 1.2.3.4; port = 1205; }
375  *     ipv4 = {
376  *         addr = 1.2.3.4; port = http; }
377  *     ipv6 = {
378  *       addr = 1.2.3.4;
379  *       port = 1205;
380  *     }
381  *     ip = {
382  *       addr = 1.2.3.4
383  *       port = 1205
384  *     }
385  *     ip = {
386  *       addr = 1.2.3.4
387  *     }
388  *     ip = {
389  *       addr = 2001:220:222::2
390  *     }
391  *     ip = {
392  *       addr = bluedot.thun.net
393  (     }
394  *   }
395  *   negativ
396  *   = { ip = { } }
397  *   = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
398  *   = { ipv4 { port = 4711 } }
399  */
400 void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
401 {
402    int token;
403    enum { EMPTYLINE = 0, PORTLINE = 0x1, ADDRLINE = 0x2 } next_line = EMPTYLINE;
404    int exist;
405    char hostname_str[1024];
406    char port_str[128];
407    int family = 0;
408    char errmsg[1024];
409
410
411    token = lex_get_token(lc, T_SKIP_EOL);
412    if (token != T_BOB) {
413       scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
414    }
415
416    token = lex_get_token(lc, T_SKIP_EOL);
417    if (token == T_EOB) {
418       scan_err0(lc, _("Empty addr block is not allowed"));
419    }
420    do {
421       if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
422          scan_err1(lc, _("Expected a string, got: %s"), lc->str);
423       }
424       if (strcasecmp("ip", lc->str) == 0 || strcasecmp("ipv4", lc->str) == 0) {
425          family = AF_INET;
426       }
427 #ifdef HAVE_IPV6
428       else if (strcasecmp("ipv6", lc->str) == 0) {
429          family = AF_INET6;
430       } else {
431          scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
432       }
433 #else
434       else {
435          scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
436       }
437 #endif
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       if (token != T_BOB) {
444          scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
445       }
446       token = lex_get_token(lc, T_SKIP_EOL);
447       exist = EMPTYLINE;
448       port_str[0] = hostname_str[0] = '\0';
449       do {
450          if (token != T_IDENTIFIER) {
451             scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
452          }
453          if (strcasecmp("port", lc->str) == 0) {
454             next_line = PORTLINE;
455             if (exist & PORTLINE) {
456                scan_err0(lc, _("Only one port per address block"));
457             }
458             exist |= PORTLINE;
459          } else if (strcasecmp("addr", lc->str) == 0) {
460             next_line = ADDRLINE;
461             if (exist & ADDRLINE) {
462                scan_err0(lc, _("Only one addr per address block"));
463             }
464             exist |= ADDRLINE;
465          } else {
466             scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
467          }
468          token = lex_get_token(lc, T_SKIP_EOL);
469          if (token != T_EQUALS) {
470             scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
471          }
472          token = lex_get_token(lc, T_SKIP_EOL);
473          switch (next_line) {
474          case PORTLINE:
475             if (!
476                 (token == T_UNQUOTED_STRING || token == T_NUMBER
477                  || token == T_IDENTIFIER)) {
478                scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
479             }
480             bstrncpy(port_str, lc->str, sizeof(port_str));
481             break;
482          case ADDRLINE:
483             if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
484                scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
485                          lc->str);
486             }
487             bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
488             break;
489          case EMPTYLINE:
490             scan_err0(lc, _("State machine missmatch"));
491             break;
492          }
493          token = lex_get_token(lc, T_SKIP_EOL);
494       } while (token == T_IDENTIFIER);
495       if (token != T_EOB) {
496          scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
497       }
498
499       if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
500                htons(item->default_value), family, hostname_str, port_str, 
501                errmsg, sizeof(errmsg))) {
502            scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
503                    hostname_str, port_str, errmsg);
504         }
505       token = scan_to_next_not_eol(lc);
506    } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
507    if (token != T_EOB) {
508       scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
509    }
510 }
511
512 void store_addresses_address(LEX * lc, RES_ITEM * item, int index, int pass)
513 {
514    char errmsg[1024];
515    int token = lex_get_token(lc, T_SKIP_EOL);
516    if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
517       scan_err1(lc, _("Expected an IP number or a hostname, got: %s"), lc->str);
518    }
519    if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_ADDR,
520                     htons(item->default_value), AF_INET, lc->str, 0, 
521                     errmsg, sizeof(errmsg))) {
522       scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg);
523    }
524 }
525
526 void store_addresses_port(LEX * lc, RES_ITEM * item, int index, int pass)
527 {
528    char errmsg[1024];
529    int token = lex_get_token(lc, T_SKIP_EOL);
530    if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
531       scan_err1(lc, _("Expected a port number or string, got: %s"), lc->str);
532    }
533    if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_SINGLE_PORT,
534                     htons(item->default_value), AF_INET, 0, lc->str, 
535                     errmsg, sizeof(errmsg))) {
536       scan_err2(lc, _("can't add port (%s) to (%s)"), lc->str, errmsg);
537    }
538 }
539
540 void free_addresses(dlist * addrs)
541 {
542    while (!addrs->empty()) {
543       IPADDR *ptr = (IPADDR*)addrs->first();
544       addrs->remove(ptr);
545       delete ptr;
546    }
547    delete addrs;
548 }
549
550 int sockaddr_get_port_net_order(const struct sockaddr *client_addr)
551 {
552    if (client_addr->sa_family == AF_INET) {
553       return ((struct sockaddr_in *)client_addr)->sin_port;
554    }
555 #ifdef HAVE_IPV6
556    else {
557       return ((struct sockaddr_in6 *)client_addr)->sin6_port;
558    }
559 #endif
560    return -1;
561 }
562
563 int sockaddr_get_port(const struct sockaddr *client_addr)
564 {
565    if (client_addr->sa_family == AF_INET) {
566       return ntohs(((struct sockaddr_in *)client_addr)->sin_port);
567    }
568 #ifdef HAVE_IPV6
569    else {
570       return ntohs(((struct sockaddr_in6 *)client_addr)->sin6_port);
571    }
572 #endif
573    return -1;
574 }
575
576
577 char *sockaddr_to_ascii(const struct sockaddr *sa, char *buf, int len)
578 {
579 #ifdef HAVE_INET_NTOP
580    /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
581    inet_ntop(sa->sa_family,
582 # ifdef HAVE_IPV6
583              sa->sa_family == AF_INET ? 
584                  (void*)&(((struct sockaddr_in*)sa)->sin_addr) :
585                  (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
586 # else
587                  (void*)&(((struct sockaddr_in*)sa)->sin_addr),
588 # endif /* HAVE_IPV6 */
589              buf, len);
590 #else
591    bstrncpy(buf, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr), len);
592 #endif
593    return buf;
594 }
595
596 #ifdef HAVE_OLD_SOCKOPT
597 int inet_aton(const char *cp, struct in_addr *inp)
598 {
599    struct in_addr inaddr;
600
601    if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
602       inp->s_addr = inaddr.s_addr;
603       return 1;
604    }
605    return 0;
606 }
607 #endif