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