1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2004-2011 Free Software Foundation Europe e.V.
5    Copyright (C) 2011-2012 Planets Communications B.V.
6    Copyright (C) 2013-2016 Bareos GmbH & Co. KG
7 
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero 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    Affero General Public License for more details.
17 
18    You should have received a copy of the GNU Affero 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 /*
24  * Written by Meno Abels, June MMIV
25  */
26 /**
27  * @file
28  * Configuration file parser for IP-Addresse ipv4 and ipv6
29  */
30 
31 #include "include/bareos.h"
32 #include "lib/address_conf.h"
33 #include "lib/bnet.h"
34 #include "lib/bsys.h"
35 #include "lib/edit.h"
36 
37 
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 
IPADDR()45 IPADDR::IPADDR()
46     : type(R_UNDEFINED)
47     , saddr(nullptr)
48     , saddr4(nullptr)
49 #ifdef HAVE_IPV6
50     , saddr6(nullptr)
51 #endif
52 {
53   memset(&saddrbuf, 0, sizeof(saddrbuf));
54 }
55 
IPADDR(const IPADDR & src)56 IPADDR::IPADDR(const IPADDR& src) : IPADDR()
57 {
58   type = src.type;
59   memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
60   saddr = &saddrbuf.dontuse;
61   saddr4 = &saddrbuf.dontuse4;
62 #ifdef HAVE_IPV6
63   saddr6 = &saddrbuf.dontuse6;
64 #endif
65 }
66 
IPADDR(int af)67 IPADDR::IPADDR(int af) : IPADDR()
68 {
69   type = R_EMPTY;
70 #ifdef HAVE_IPV6
71   if (!(af == AF_INET6 || af == AF_INET)) {
72     Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
73   }
74 #else
75   if (af != AF_INET) {
76     Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
77   }
78 #endif
79 
80   memset(&saddrbuf, 0, sizeof(saddrbuf));
81   saddr = &saddrbuf.dontuse;
82   saddr4 = &saddrbuf.dontuse4;
83 #ifdef HAVE_IPV6
84   saddr6 = &saddrbuf.dontuse6;
85 #endif
86   saddr->sa_family = af;
87   switch (af) {
88     case AF_INET:
89       saddr4->sin_port = 0xffff;
90 #ifdef HAVE_SA_LEN
91       saddr->sa_len = sizeof(sockaddr_in);
92 #endif
93       break;
94 #ifdef HAVE_IPV6
95     case AF_INET6:
96       saddr6->sin6_port = 0xffff;
97 #ifdef HAVE_SA_LEN
98       saddr->sa_len = sizeof(sockaddr_in6);
99 #endif
100       break;
101 #endif
102   }
103 
104   SetAddrAny();
105 }
106 
SetType(i_type o)107 void IPADDR::SetType(i_type o) { type = o; }
108 
GetType() const109 IPADDR::i_type IPADDR::GetType() const { return type; }
110 
GetPortNetOrder() const111 unsigned short IPADDR::GetPortNetOrder() const
112 {
113   unsigned short port = 0;
114   if (saddr->sa_family == AF_INET) {
115     port = saddr4->sin_port;
116   }
117 #ifdef HAVE_IPV6
118   else {
119     port = saddr6->sin6_port;
120   }
121 #endif
122   return port;
123 }
124 
SetPortNet(unsigned short port)125 void IPADDR::SetPortNet(unsigned short port)
126 {
127   if (saddr->sa_family == AF_INET) {
128     saddr4->sin_port = port;
129   }
130 #ifdef HAVE_IPV6
131   else {
132     saddr6->sin6_port = port;
133   }
134 #endif
135 }
136 
GetFamily() const137 int IPADDR::GetFamily() const { return saddr->sa_family; }
138 
get_sockaddr()139 struct sockaddr* IPADDR::get_sockaddr() { return saddr; }
140 
GetSockaddrLen()141 int IPADDR::GetSockaddrLen()
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 }
CopyAddr(IPADDR * src)149 void IPADDR::CopyAddr(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 
SetAddrAny()161 void IPADDR::SetAddrAny()
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 
SetAddr4(struct in_addr * ip4)173 void IPADDR::SetAddr4(struct in_addr* ip4)
174 {
175   if (saddr->sa_family != AF_INET) {
176     Emsg1(M_ERROR_TERM, 0,
177           _("It was tried to assign a ipv6 address to a ipv4(%d)\n"),
178           saddr->sa_family);
179   }
180   saddr4->sin_addr = *ip4;
181 }
182 
183 #ifdef HAVE_IPV6
SetAddr6(struct in6_addr * ip6)184 void IPADDR::SetAddr6(struct in6_addr* ip6)
185 {
186   if (saddr->sa_family != AF_INET6) {
187     Emsg1(M_ERROR_TERM, 0,
188           _("It was tried to assign a ipv4 address to a ipv6(%d)\n"),
189           saddr->sa_family);
190   }
191   saddr6->sin6_addr = *ip6;
192 }
193 #endif
194 
GetAddress(char * outputbuf,int outlen)195 const char* IPADDR::GetAddress(char* outputbuf, int outlen)
196 {
197   outputbuf[0] = '\0';
198 #ifdef HAVE_INET_NTOP
199 #ifdef HAVE_IPV6
200   inet_ntop(saddr->sa_family,
201             saddr->sa_family == AF_INET ? (void*)&(saddr4->sin_addr)
202                                         : (void*)&(saddr6->sin6_addr),
203             outputbuf, outlen);
204 #else
205   inet_ntop(saddr->sa_family, (void*)&(saddr4->sin_addr), outputbuf, outlen);
206 #endif
207 #else
208   bstrncpy(outputbuf, inet_ntoa(saddr4->sin_addr), outlen);
209 #endif
210   return outputbuf;
211 }
212 
BuildConfigString(char * buf,int blen)213 const char* IPADDR::BuildConfigString(char* buf, int blen)
214 {
215   char tmp[1024];
216 
217   switch (GetFamily()) {
218     case AF_INET:
219       Bsnprintf(buf, blen,
220                 "      ipv4 = {\n"
221                 "         addr = %s\n"
222                 "         port = %hu\n"
223                 "      }",
224                 GetAddress(tmp, sizeof(tmp) - 1), GetPortHostOrder());
225       break;
226     case AF_INET6:
227       Bsnprintf(buf, blen,
228                 "      ipv6 = {\n"
229                 "         addr = %s\n"
230                 "         port = %hu\n"
231                 "      }",
232                 GetAddress(tmp, sizeof(tmp) - 1), GetPortHostOrder());
233       break;
234     default:
235       break;
236   }
237 
238   return buf;
239 }
240 
build_address_str(char * buf,int blen,bool print_port)241 const char* IPADDR::build_address_str(char* buf,
242                                       int blen,
243                                       bool print_port /*=true*/)
244 {
245   char tmp[1024];
246   if (print_port) {
247     switch (GetFamily()) {
248       case AF_INET:
249         Bsnprintf(buf, blen, "host[ipv4;%s;%hu] ",
250                   GetAddress(tmp, sizeof(tmp) - 1), GetPortHostOrder());
251         break;
252       case AF_INET6:
253         Bsnprintf(buf, blen, "host[ipv6;%s;%hu] ",
254                   GetAddress(tmp, sizeof(tmp) - 1), GetPortHostOrder());
255         break;
256       default:
257         break;
258     }
259   } else {
260     switch (GetFamily()) {
261       case AF_INET:
262         Bsnprintf(buf, blen, "host[ipv4;%s] ",
263                   GetAddress(tmp, sizeof(tmp) - 1));
264         break;
265       case AF_INET6:
266         Bsnprintf(buf, blen, "host[ipv6;%s] ",
267                   GetAddress(tmp, sizeof(tmp) - 1));
268         break;
269       default:
270         break;
271     }
272   }
273 
274   return buf;
275 }
276 
BuildAddressesString(dlist * addrs,char * buf,int blen,bool print_port)277 const char* BuildAddressesString(dlist* addrs,
278                                  char* buf,
279                                  int blen,
280                                  bool print_port /*=true*/)
281 {
282   if (!addrs || addrs->size() == 0) {
283     bstrncpy(buf, "", blen);
284     return buf;
285   }
286   char* work = buf;
287   IPADDR* p;
288   foreach_dlist (p, addrs) {
289     char tmp[1024];
290     int len = Bsnprintf(work, blen, "%s",
291                         p->build_address_str(tmp, sizeof(tmp), print_port));
292     if (len < 0) break;
293     work += len;
294     blen -= len;
295   }
296   return buf;
297 }
298 
GetFirstAddress(dlist * addrs,char * outputbuf,int outlen)299 const char* GetFirstAddress(dlist* addrs, char* outputbuf, int outlen)
300 {
301   return ((IPADDR*)(addrs->first()))->GetAddress(outputbuf, outlen);
302 }
303 
GetFirstPortNetOrder(dlist * addrs)304 int GetFirstPortNetOrder(dlist* addrs)
305 {
306   if (!addrs) {
307     return 0;
308   } else {
309     return ((IPADDR*)(addrs->first()))->GetPortNetOrder();
310   }
311 }
312 
GetFirstPortHostOrder(dlist * addrs)313 int GetFirstPortHostOrder(dlist* addrs)
314 {
315   if (!addrs) {
316     return 0;
317   } else {
318     return ((IPADDR*)(addrs->first()))->GetPortHostOrder();
319   }
320 }
321 
AddAddress(dlist ** out,IPADDR::i_type type,unsigned short defaultport,int family,const char * hostname_str,const char * port_str,char * buf,int buflen)322 int AddAddress(dlist** out,
323                IPADDR::i_type type,
324                unsigned short defaultport,
325                int family,
326                const char* hostname_str,
327                const char* port_str,
328                char* buf,
329                int buflen)
330 {
331   IPADDR* iaddr;
332   IPADDR* jaddr;
333   dlist* hostaddrs;
334   unsigned short port;
335   IPADDR::i_type intype = type;
336 
337   buf[0] = 0;
338   dlist* addrs = (dlist*)(*(out));
339   if (!addrs) {
340     IPADDR* tmp = 0;
341     addrs = *out = new dlist(tmp, &tmp->link);
342   }
343 
344   type = (type == IPADDR::R_SINGLE_PORT || type == IPADDR::R_SINGLE_ADDR)
345              ? IPADDR::R_SINGLE
346              : type;
347   if (type != IPADDR::R_DEFAULT) {
348     IPADDR* def = 0;
349     foreach_dlist (iaddr, addrs) {
350       if (iaddr->GetType() == IPADDR::R_DEFAULT) {
351         def = iaddr;
352       } else if (iaddr->GetType() != type) {
353         Bsnprintf(buf, buflen,
354                   _("the old style addresses cannot be mixed with new style"));
355         return 0;
356       }
357     }
358     if (def) {
359       addrs->remove(def);
360       delete def;
361     }
362   }
363 
364   if (!port_str || port_str[0] == '\0') {
365     port = defaultport;
366   } else {
367     int pnum = atol(port_str);
368     if (0 < pnum && pnum < 0xffff) {
369       port = htons(pnum);
370     } else {
371       struct servent* s = getservbyname(port_str, "tcp");
372       if (s) {
373         port = s->s_port;
374       } else {
375         Bsnprintf(buf, buflen, _("can't resolve service(%s)"), port_str);
376         return 0;
377       }
378     }
379   }
380 
381   const char* myerrstr;
382   hostaddrs = BnetHost2IpAddrs(hostname_str, family, &myerrstr);
383   if (!hostaddrs) {
384     Bsnprintf(buf, buflen, _("can't resolve hostname(%s) %s"), hostname_str,
385               myerrstr);
386     return 0;
387   }
388 
389   if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
390     IPADDR* addr;
391     if (addrs->size()) {
392       addr = (IPADDR*)addrs->first();
393     } else {
394       addr = new IPADDR(family);
395       addr->SetType(type);
396       addr->SetPortNet(defaultport);
397       addr->SetAddrAny();
398       addrs->append(addr);
399     }
400     if (intype == IPADDR::R_SINGLE_PORT) { addr->SetPortNet(port); }
401     if (intype == IPADDR::R_SINGLE_ADDR) {
402       addr->CopyAddr((IPADDR*)(hostaddrs->first()));
403     }
404   } else {
405     foreach_dlist (iaddr, hostaddrs) {
406       IPADDR* clone;
407       /* for duplicates */
408       foreach_dlist (jaddr, addrs) {
409         if (iaddr->GetSockaddrLen() == jaddr->GetSockaddrLen() &&
410             !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
411                     iaddr->GetSockaddrLen())) {
412           goto skip; /* no price */
413         }
414       }
415       clone = new IPADDR(*iaddr);
416       clone->SetType(type);
417       clone->SetPortNet(port);
418       addrs->append(clone);
419     skip:
420       continue;
421     }
422   }
423   FreeAddresses(hostaddrs);
424   return 1;
425 }
426 
InitDefaultAddresses(dlist ** out,const char * port)427 void InitDefaultAddresses(dlist** out, const char* port)
428 {
429   char buf[1024];
430   unsigned short sport = str_to_int32(port);
431 
432   if (!AddAddress(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf,
433                   sizeof(buf))) {
434     Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), buf);
435   }
436 }
437 
FreeAddresses(dlist * addrs)438 void FreeAddresses(dlist* addrs)
439 {
440   while (!addrs->empty()) {
441     IPADDR* ptr = (IPADDR*)addrs->first();
442     addrs->remove(ptr);
443     delete ptr;
444   }
445   delete addrs;
446 }
447 
SockaddrGetPortNetOrder(const struct sockaddr * client_addr)448 int SockaddrGetPortNetOrder(const struct sockaddr* client_addr)
449 {
450   if (client_addr->sa_family == AF_INET) {
451     return ((struct sockaddr_in*)client_addr)->sin_port;
452   }
453 #ifdef HAVE_IPV6
454   else {
455     return ((struct sockaddr_in6*)client_addr)->sin6_port;
456   }
457 #endif
458   return -1;
459 }
460 
SockaddrGetPort(const struct sockaddr * client_addr)461 int SockaddrGetPort(const struct sockaddr* client_addr)
462 {
463   if (client_addr->sa_family == AF_INET) {
464     return ntohs(((struct sockaddr_in*)client_addr)->sin_port);
465   }
466 #ifdef HAVE_IPV6
467   else {
468     return ntohs(((struct sockaddr_in6*)client_addr)->sin6_port);
469   }
470 #endif
471   return -1;
472 }
473 
SockaddrToAscii(const struct sockaddr * sa,char * buf,int len)474 char* SockaddrToAscii(const struct sockaddr* sa, char* buf, int len)
475 {
476 #ifdef HAVE_INET_NTOP
477   /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
478   inet_ntop(sa->sa_family,
479 #ifdef HAVE_IPV6
480             sa->sa_family == AF_INET
481                 ? (void*)&(((struct sockaddr_in*)sa)->sin_addr)
482                 : (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
483 #else
484             (void*)&(((struct sockaddr_in*)sa)->sin_addr),
485 #endif /* HAVE_IPV6 */
486             buf, len);
487 #else
488   bstrncpy(buf, inet_ntoa(((struct sockaddr_in*)sa)->sin_addr), len);
489 #endif
490   return buf;
491 }
492 
493 #ifdef HAVE_OLD_SOCKOPT
inet_aton(const char * cp,struct in_addr * inp)494 int inet_aton(const char* cp, struct in_addr* inp)
495 {
496   struct in_addr inaddr;
497 
498   if ((inaddr.s_addr = InetAddr(cp)) != INADDR_NONE) {
499     inp->s_addr = inaddr.s_addr;
500     return 1;
501   }
502   return 0;
503 }
504 #endif
505