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