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-2020 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 #include "lib/output_formatter_resource.h"
37 
38 
39 #ifdef HAVE_ARPA_NAMESER_H
40 #  include <arpa/nameser.h>
41 #endif
42 #ifdef HAVE_RESOLV_H
43 //#include <resolv.h>
44 #endif
45 
IPADDR()46 IPADDR::IPADDR()
47     : type(R_UNDEFINED)
48     , saddr(nullptr)
49     , saddr4(nullptr)
50 #ifdef HAVE_IPV6
51     , saddr6(nullptr)
52 #endif
53 {
54   memset(&saddrbuf, 0, sizeof(saddrbuf));
55 }
56 
IPADDR(const IPADDR & src)57 IPADDR::IPADDR(const IPADDR& src) : IPADDR()
58 {
59   type = src.type;
60   memcpy(&saddrbuf, &src.saddrbuf, sizeof(saddrbuf));
61   saddr = &saddrbuf.dontuse;
62   saddr4 = &saddrbuf.dontuse4;
63 #ifdef HAVE_IPV6
64   saddr6 = &saddrbuf.dontuse6;
65 #endif
66 }
67 
IPADDR(int af)68 IPADDR::IPADDR(int af) : IPADDR()
69 {
70   type = R_EMPTY;
71 #ifdef HAVE_IPV6
72   if (!(af == AF_INET6 || af == AF_INET)) {
73     Emsg1(M_ERROR_TERM, 0, _("Only ipv4 and ipv6 are supported (%d)\n"), af);
74   }
75 #else
76   if (af != AF_INET) {
77     Emsg1(M_ERROR_TERM, 0, _("Only ipv4 is supported (%d)\n"), af);
78   }
79 #endif
80 
81   memset(&saddrbuf, 0, sizeof(saddrbuf));
82   saddr = &saddrbuf.dontuse;
83   saddr4 = &saddrbuf.dontuse4;
84 #ifdef HAVE_IPV6
85   saddr6 = &saddrbuf.dontuse6;
86 #endif
87   saddr->sa_family = af;
88   switch (af) {
89     case AF_INET:
90       saddr4->sin_port = 0xffff;
91       break;
92 #ifdef HAVE_IPV6
93     case AF_INET6:
94       saddr6->sin6_port = 0xffff;
95       break;
96 #endif
97   }
98 
99   SetAddrAny();
100 }
101 
SetType(i_type o)102 void IPADDR::SetType(i_type o) { type = o; }
103 
GetType() const104 IPADDR::i_type IPADDR::GetType() const { return type; }
105 
GetPortNetOrder() const106 unsigned short IPADDR::GetPortNetOrder() const
107 {
108   unsigned short port = 0;
109   if (saddr->sa_family == AF_INET) {
110     port = saddr4->sin_port;
111   }
112 #ifdef HAVE_IPV6
113   else {
114     port = saddr6->sin6_port;
115   }
116 #endif
117   return port;
118 }
119 
SetPortNet(unsigned short port)120 void IPADDR::SetPortNet(unsigned short port)
121 {
122   if (saddr->sa_family == AF_INET) {
123     saddr4->sin_port = port;
124   }
125 #ifdef HAVE_IPV6
126   else {
127     saddr6->sin6_port = port;
128   }
129 #endif
130 }
131 
GetFamily() const132 int IPADDR::GetFamily() const { return saddr->sa_family; }
133 
get_sockaddr()134 struct sockaddr* IPADDR::get_sockaddr() { return saddr; }
135 
GetSockaddrLen()136 int IPADDR::GetSockaddrLen()
137 {
138 #ifdef HAVE_IPV6
139   return saddr->sa_family == AF_INET ? sizeof(*saddr4) : sizeof(*saddr6);
140 #else
141   return sizeof(*saddr4);
142 #endif
143 }
CopyAddr(IPADDR * src)144 void IPADDR::CopyAddr(IPADDR* src)
145 {
146   if (saddr->sa_family == AF_INET) {
147     saddr4->sin_addr.s_addr = src->saddr4->sin_addr.s_addr;
148   }
149 #ifdef HAVE_IPV6
150   else {
151     saddr6->sin6_addr = src->saddr6->sin6_addr;
152   }
153 #endif
154 }
155 
SetAddrAny()156 void IPADDR::SetAddrAny()
157 {
158   if (saddr->sa_family == AF_INET) {
159     saddr4->sin_addr.s_addr = INADDR_ANY;
160   }
161 #ifdef HAVE_IPV6
162   else {
163     saddr6->sin6_addr = in6addr_any;
164   }
165 #endif
166 }
167 
SetAddr4(struct in_addr * ip4)168 void IPADDR::SetAddr4(struct in_addr* ip4)
169 {
170   if (saddr->sa_family != AF_INET) {
171     Emsg1(M_ERROR_TERM, 0,
172           _("It was tried to assign a ipv6 address to a ipv4(%d)\n"),
173           saddr->sa_family);
174   }
175   saddr4->sin_addr = *ip4;
176 }
177 
178 #ifdef HAVE_IPV6
SetAddr6(struct in6_addr * ip6)179 void IPADDR::SetAddr6(struct in6_addr* ip6)
180 {
181   if (saddr->sa_family != AF_INET6) {
182     Emsg1(M_ERROR_TERM, 0,
183           _("It was tried to assign a ipv4 address to a ipv6(%d)\n"),
184           saddr->sa_family);
185   }
186   saddr6->sin6_addr = *ip6;
187 }
188 #endif
189 
GetAddress(char * outputbuf,int outlen)190 const char* IPADDR::GetAddress(char* outputbuf, int outlen)
191 {
192   outputbuf[0] = '\0';
193 #ifdef HAVE_INET_NTOP
194 #  ifdef HAVE_IPV6
195   inet_ntop(saddr->sa_family,
196             saddr->sa_family == AF_INET ? (void*)&(saddr4->sin_addr)
197                                         : (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 
BuildConfigString(OutputFormatterResource & send,bool as_comment)208 void IPADDR::BuildConfigString(OutputFormatterResource& send, bool as_comment)
209 {
210   char tmp[1024];
211   std::string formatstring;
212 
213   switch (GetFamily()) {
214     case AF_INET:
215       send.SubResourceStart("ipv4", as_comment, "%s = {\n");
216       send.KeyString("addr", GetAddress(tmp, sizeof(tmp) - 1), as_comment);
217       send.KeyUnsignedInt("port", GetPortHostOrder(), as_comment);
218       send.SubResourceEnd("ipv4", as_comment);
219       break;
220     case AF_INET6:
221       send.SubResourceStart("ipv6", as_comment, "%s = {\n");
222       send.KeyString("addr", GetAddress(tmp, sizeof(tmp) - 1), as_comment);
223       send.KeyUnsignedInt("port", GetPortHostOrder(), as_comment);
224       send.SubResourceEnd("ipv6", as_comment);
225       break;
226     default:
227       break;
228   }
229 }
230 
231 
build_address_str(char * buf,int blen,bool print_port)232 const char* IPADDR::build_address_str(char* buf,
233                                       int blen,
234                                       bool print_port /*=true*/)
235 {
236   char tmp[1024];
237   if (print_port) {
238     switch (GetFamily()) {
239       case AF_INET:
240         Bsnprintf(buf, blen, "host[ipv4;%s;%hu] ",
241                   GetAddress(tmp, sizeof(tmp) - 1), GetPortHostOrder());
242         break;
243       case AF_INET6:
244         Bsnprintf(buf, blen, "host[ipv6;%s;%hu] ",
245                   GetAddress(tmp, sizeof(tmp) - 1), GetPortHostOrder());
246         break;
247       default:
248         break;
249     }
250   } else {
251     switch (GetFamily()) {
252       case AF_INET:
253         Bsnprintf(buf, blen, "host[ipv4;%s] ",
254                   GetAddress(tmp, sizeof(tmp) - 1));
255         break;
256       case AF_INET6:
257         Bsnprintf(buf, blen, "host[ipv6;%s] ",
258                   GetAddress(tmp, sizeof(tmp) - 1));
259         break;
260       default:
261         break;
262     }
263   }
264 
265   return buf;
266 }
267 
BuildAddressesString(dlist * addrs,char * buf,int blen,bool print_port)268 const char* BuildAddressesString(dlist* addrs,
269                                  char* buf,
270                                  int blen,
271                                  bool print_port /*=true*/)
272 {
273   if (!addrs || addrs->size() == 0) {
274     bstrncpy(buf, "", blen);
275     return buf;
276   }
277   char* work = buf;
278   IPADDR* p;
279   foreach_dlist (p, addrs) {
280     char tmp[1024];
281     int len = Bsnprintf(work, blen, "%s",
282                         p->build_address_str(tmp, sizeof(tmp), print_port));
283     if (len < 0) break;
284     work += len;
285     blen -= len;
286   }
287   return buf;
288 }
289 
GetFirstAddress(dlist * addrs,char * outputbuf,int outlen)290 const char* GetFirstAddress(dlist* addrs, char* outputbuf, int outlen)
291 {
292   return ((IPADDR*)(addrs->first()))->GetAddress(outputbuf, outlen);
293 }
294 
GetFirstPortNetOrder(dlist * addrs)295 int GetFirstPortNetOrder(dlist* addrs)
296 {
297   if (!addrs) {
298     return 0;
299   } else {
300     return ((IPADDR*)(addrs->first()))->GetPortNetOrder();
301   }
302 }
303 
GetFirstPortHostOrder(dlist * addrs)304 int GetFirstPortHostOrder(dlist* addrs)
305 {
306   if (!addrs) {
307     return 0;
308   } else {
309     return ((IPADDR*)(addrs->first()))->GetPortHostOrder();
310   }
311 }
312 
AddAddress(dlist ** out,IPADDR::i_type type,unsigned short defaultport,int family,const char * hostname_str,const char * port_str,char * buf,int buflen)313 int AddAddress(dlist** out,
314                IPADDR::i_type type,
315                unsigned short defaultport,
316                int family,
317                const char* hostname_str,
318                const char* port_str,
319                char* buf,
320                int buflen)
321 {
322   IPADDR* iaddr;
323   IPADDR* jaddr;
324   dlist* hostaddrs;
325   unsigned short port;
326   IPADDR::i_type intype = type;
327 
328   buf[0] = 0;
329   dlist* addrs = (dlist*)(*(out));
330   if (!addrs) {
331     IPADDR* tmp = 0;
332     addrs = *out = new dlist(tmp, &tmp->link);
333   }
334 
335   type = (type == IPADDR::R_SINGLE_PORT || type == IPADDR::R_SINGLE_ADDR)
336              ? IPADDR::R_SINGLE
337              : type;
338   if (type != IPADDR::R_DEFAULT) {
339     IPADDR* def = 0;
340     foreach_dlist (iaddr, addrs) {
341       if (iaddr->GetType() == IPADDR::R_DEFAULT) {
342         def = iaddr;
343       } else if (iaddr->GetType() != type) {
344         Bsnprintf(buf, buflen,
345                   _("the old style addresses cannot be mixed with new style"));
346         return 0;
347       }
348     }
349     if (def) {
350       addrs->remove(def);
351       delete def;
352     }
353   }
354 
355   if (!port_str || port_str[0] == '\0') {
356     port = defaultport;
357   } else {
358     int pnum = atol(port_str);
359     if (0 < pnum && pnum < 0xffff) {
360       port = htons(pnum);
361     } else {
362       struct servent* s = getservbyname(port_str, "tcp");
363       if (s) {
364         port = s->s_port;
365       } else {
366         Bsnprintf(buf, buflen, _("can't resolve service(%s)"), port_str);
367         return 0;
368       }
369     }
370   }
371 
372   const char* myerrstr;
373   hostaddrs = BnetHost2IpAddrs(hostname_str, family, &myerrstr);
374   if (!hostaddrs) {
375     Bsnprintf(buf, buflen, _("can't resolve hostname(%s) %s"), hostname_str,
376               myerrstr);
377     return 0;
378   }
379 
380   if (intype == IPADDR::R_SINGLE_PORT || intype == IPADDR::R_SINGLE_ADDR) {
381     IPADDR* addr;
382     if (addrs->size()) {
383       addr = (IPADDR*)addrs->first();
384     } else {
385       addr = new IPADDR(family);
386       addr->SetType(type);
387       addr->SetPortNet(defaultport);
388       addr->SetAddrAny();
389       addrs->append(addr);
390     }
391     if (intype == IPADDR::R_SINGLE_PORT) { addr->SetPortNet(port); }
392     if (intype == IPADDR::R_SINGLE_ADDR) {
393       addr->CopyAddr((IPADDR*)(hostaddrs->first()));
394     }
395   } else {
396     foreach_dlist (iaddr, hostaddrs) {
397       IPADDR* clone;
398       /* for duplicates */
399       foreach_dlist (jaddr, addrs) {
400         if (iaddr->GetSockaddrLen() == jaddr->GetSockaddrLen()
401             && !memcmp(iaddr->get_sockaddr(), jaddr->get_sockaddr(),
402                        iaddr->GetSockaddrLen())) {
403           goto skip; /* no price */
404         }
405       }
406       clone = new IPADDR(*iaddr);
407       clone->SetType(type);
408       clone->SetPortNet(port);
409       addrs->append(clone);
410     skip:
411       continue;
412     }
413   }
414   FreeAddresses(hostaddrs);
415   return 1;
416 }
417 
InitDefaultAddresses(dlist ** out,const char * port)418 void InitDefaultAddresses(dlist** out, const char* port)
419 {
420   char buf[1024];
421   unsigned short sport = str_to_int32(port);
422 
423   if (!AddAddress(out, IPADDR::R_DEFAULT, htons(sport), AF_INET, 0, 0, buf,
424                   sizeof(buf))) {
425     Emsg1(M_ERROR_TERM, 0, _("Can't add default address (%s)\n"), buf);
426   }
427 }
428 
FreeAddresses(dlist * addrs)429 void FreeAddresses(dlist* addrs)
430 {
431   while (!addrs->empty()) {
432     IPADDR* ptr = (IPADDR*)addrs->first();
433     addrs->remove(ptr);
434     delete ptr;
435   }
436   delete addrs;
437 }
438 
SockaddrGetPortNetOrder(const struct sockaddr * client_addr)439 int SockaddrGetPortNetOrder(const struct sockaddr* client_addr)
440 {
441   if (client_addr->sa_family == AF_INET) {
442     return ((struct sockaddr_in*)client_addr)->sin_port;
443   }
444 #ifdef HAVE_IPV6
445   else {
446     return ((struct sockaddr_in6*)client_addr)->sin6_port;
447   }
448 #endif
449   return -1;
450 }
451 
SockaddrGetPort(const struct sockaddr * client_addr)452 int SockaddrGetPort(const struct sockaddr* client_addr)
453 {
454   if (client_addr->sa_family == AF_INET) {
455     return ntohs(((struct sockaddr_in*)client_addr)->sin_port);
456   }
457 #ifdef HAVE_IPV6
458   else {
459     return ntohs(((struct sockaddr_in6*)client_addr)->sin6_port);
460   }
461 #endif
462   return -1;
463 }
464 
SockaddrToAscii(const struct sockaddr * sa,char * buf,int len)465 char* SockaddrToAscii(const struct sockaddr* sa, char* buf, int len)
466 {
467 #ifdef HAVE_INET_NTOP
468   /* MA Bug 5 the problem was that i mixed up sockaddr and in_addr */
469   inet_ntop(sa->sa_family,
470 #  ifdef HAVE_IPV6
471             sa->sa_family == AF_INET
472                 ? (void*)&(((struct sockaddr_in*)sa)->sin_addr)
473                 : (void*)&(((struct sockaddr_in6*)sa)->sin6_addr),
474 #  else
475             (void*)&(((struct sockaddr_in*)sa)->sin_addr),
476 #  endif /* HAVE_IPV6 */
477             buf, len);
478 #else
479   bstrncpy(buf, inet_ntoa(((struct sockaddr_in*)sa)->sin_addr), len);
480 #endif
481   return buf;
482 }
483 
484 #ifdef HAVE_OLD_SOCKOPT
inet_aton(const char * cp,struct in_addr * inp)485 int inet_aton(const char* cp, struct in_addr* inp)
486 {
487   struct in_addr inaddr;
488 
489   if ((inaddr.s_addr = InetAddr(cp)) != INADDR_NONE) {
490     inp->s_addr = inaddr.s_addr;
491     return 1;
492   }
493   return 0;
494 }
495 #endif
496