XRootD
Loading...
Searching...
No Matches
XrdNetIF.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d N e t I F . c c */
4/* */
5/* (c) 2011 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky for Stanford University under contract */
8/* DE-AC02-76-SFO0515 with the Department of Energy */
9/* */
10/* This file is part of the XRootD software suite. */
11/* */
12/* XRootD is free software: you can redistribute it and/or modify it under */
13/* the terms of the GNU Lesser General Public License as published by the */
14/* Free Software Foundation, either version 3 of the License, or (at your */
15/* option) any later version. */
16/* */
17/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20/* License for more details. */
21/* */
22/* You should have received a copy of the GNU Lesser General Public License */
23/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25/* */
26/* The copyright holder's institutional names and contributor's names may not */
27/* be used to endorse or promote products derived from this software without */
28/* specific prior written permission of the institution or contributor. */
29/******************************************************************************/
30
31#include <cctype>
32#include <netdb.h>
33#include <cstdio>
34#include <sys/types.h>
35
36#ifdef HAVE_GETIFADDRS
37#include <net/if.h>
38#include <ifaddrs.h>
39#endif
40
41#include "XrdNet/XrdNetAddr.hh"
42#include "XrdNet/XrdNetIF.hh"
44#include "XrdNet/XrdNetUtils.hh"
45#include "XrdOuc/XrdOucTList.hh"
46#include "XrdSys/XrdSysE2T.hh"
47#include "XrdSys/XrdSysError.hh"
48
49#include <iostream>
50
51/******************************************************************************/
52/* L o c a l S t a t i c s */
53/******************************************************************************/
54
55namespace
56{
57// Selection mask values
58//
59const char hasPub4 = 0x01;
60const char hasPrv4 = 0x02;
61const char hasPub6 = 0x04;
62const char hasPrv6 = 0x08;
63const char hasAny4 = hasPub4 | hasPrv4;
64const char hasAny6 = hasPub6 | hasPrv6;
65const int hasNum = 4;
66
67// Name translation table
68//
69const char sMask[hasNum] = {hasPub4, hasPrv4, hasPub6, hasPrv6};
70const char *sName[hasNum] = {"pub4 ", "prv4 ", "pub6 ", "prv6"};
71
72// common -> Only private addresses may select any node. Public must select
73// a node that has a public address.
74//
75 const char ifMaskComm [XrdNetIF::ifMax] = {hasPub4, hasAny4,
76 hasPub6, hasAny6,
77 hasPub4 | hasPub6,
78 hasAny6 | hasAny4,
79 hasPub6 | hasPub4,
80 hasAny4 | hasAny6
81 };
82
83// local -> Public-private address is immaterial for node selection.
84//
85 const char ifMaskLocal[XrdNetIF::ifMax] = {hasAny4, hasAny4,
86 hasAny6, hasAny6,
87 hasAny4 | hasAny6,
88 hasAny4 | hasAny6,
89 hasAny6 | hasAny4,
90 hasAny6 | hasAny4
91 };
92
93// split -> Address type may only select node with that address type.
94//
95 const char ifMaskSplit[XrdNetIF::ifMax] = {hasPub4, hasPrv4,
96 hasPub6, hasPrv6,
97 hasPub4 | hasPub6,
98 hasPrv4 | hasPrv6,
99 hasPub6 | hasPub4,
100 hasPrv6 | hasPrv4
101 };
102}
103
104/******************************************************************************/
105/* S t a t i c M e m b e r s */
106/******************************************************************************/
107
108XrdSysError *XrdNetIF::eDest = 0;
109
110const char *XrdNetIF::myDomain = XrdNetIF::GetDomain();
111
112char *XrdNetIF::ifCfg[2] = {0,0}; // public, private
113
114const char *XrdNetIF::ifTName[ifMax] = {"public IPv4", // 01
115 "private IPv4", // 02
116 "public IPv6", // 04
117 "private IPv6", // 08
118 "public",
119 "private",
120 "public",
121 "private"
122 };
123
124
125// The following vector is suitable only for local routing. It is reset
126// to the appropriate selection bits when Routing() is called.
127//
128const char *XrdNetIF::ifMaskVec = ifMaskLocal;
129
130XrdNetIF::netType XrdNetIF::netRoutes = XrdNetIF::netLocal;
131
132int XrdNetIF::dfPort = 1094;
133
134XrdNetIF::ifData XrdNetIF::ifNull;
135
136bool XrdNetIF::rPIPA = false;
137
138/******************************************************************************/
139/* D i s p l a y */
140/******************************************************************************/
141
142void XrdNetIF::Display(const char *pfx)
143{
144 static const char *ifN[] = {"pub4", "prv4", "pub6", "prv6"};
145 static const char *ifT[] = {"all4", 0, "all6", 0};
146 static const char *nNM[] = {"local", "split", "common", "local"};
147 const char *iHX[hasNum] = {"", "", "", ""};
148 const char *ifRType, *hName = "";
149 char buff[256];
150 bool nameOK = false;
151
152// If we have no error routing object, just return
153//
154 if (!eDest) return;
155
156// Get a hostname
157//
158 for (int i = 0; i < (int)ifNum; i++)
159 {if (ifName[i] != &ifNull)
160 {hName = ifName[i]->iVal;
161 if (ifxDNS[i]) {nameOK = true; break;}
162 }
163 }
164
165// Compute selection mask
166//
167 for (int i = 0; i < hasNum; i++)
168 if (ifMask & sMask[i]) iHX[i] = sName[i];
169
170// Print results
171//
172 sprintf(buff, ": %s %s%s%s%s", nNM[ifRoute], iHX[0],iHX[1],iHX[2],iHX[3]);
173 eDest->Say(pfx, "Routing for ", hName, buff);
174
175 for (int i = 0; i < (int)ifNum; i++)
176 {if (ifName[i] != &ifNull)
177 {if (ifT[i] && ifDest[i] == ifDest[i+1]) {ifRType = ifT[i]; i++;}
178 else ifRType = ifN[i];
179 sprintf(buff, "Route %s: ", ifRType);
180 eDest->Say(pfx, buff, (nameOK ? hName : ifName[i]->iVal),
181 " Dest=", ifDest[i]->iVal, portSfx.val);
182 }
183 }
184}
185
186/******************************************************************************/
187/* Private: G e n A d d r s */
188/******************************************************************************/
189
190bool XrdNetIF::GenAddrs(ifAddrs &ifTab, XrdNetAddrInfo *src)
191{
192 static const int noPort = XrdNetAddr::noPort;
193 static const int old6M4 = XrdNetAddr::noPort | XrdNetAddr::old6Map4;
194 int n;
195
196// If this is an IPV4 address, then format as it
197//
198 ifTab.ipV6 = false;
200 {if (!(ifTab.hALen = src->Format(ifTab.hAddr, sizeof(ifTab.hAddr),
201 XrdNetAddr::fmtAddr, noPort))
202 || !(ifTab.hDLen = src->Format(ifTab.hDest, sizeof(ifTab.hDest),
203 XrdNetAddr::fmtAdv6, old6M4))) return false;
204 return true;
205 }
206
207// If this is a mapped address then we can easily generate the IPV4 version
208// and the locate destination address is the deprecated IPV6 address.
209//
210 if (src->isMapped())
211 {char *Colon;
212 if (!src->Format(ifTab.hAddr, sizeof(ifTab.hAddr),
213 XrdNetAddr::fmtAdv6, noPort)) return false;
214 if (!(Colon = rindex(ifTab.hAddr, ':'))) return false;
215 n = strlen(Colon+1);
216 memmove(ifTab.hAddr,Colon+1,n); ifTab.hAddr[n-1] = 0; ifTab.hALen = n-1;
217 if (!(ifTab.hDLen = src->Format(ifTab.hDest, sizeof(ifTab.hDest),
218 XrdNetAddr::fmtAdv6, old6M4))) return false;
219 return true;
220 }
221
222// There is no IPV4 address so use pure IPV6.
223//
224 ifTab.ipV6 = true;
225 if (!(ifTab.hALen = src->Format(ifTab.hAddr, sizeof(ifTab.hAddr),
226 XrdNetAddr::fmtAdv6, noPort))
227 || !(ifTab.hDLen = src->Format(ifTab.hDest, sizeof(ifTab.hDest),
228 XrdNetAddr::fmtAdv6, noPort))) return false;
229 return true;
230}
231
232/******************************************************************************/
233
234bool XrdNetIF::GenAddrs(ifAddrs &ifTab, const char *hName, bool wantV6)
235{
236 XrdNetAddr *iP;
239 int i, iN, iPVT = -1;
240 bool aOK = false;
241
242// Find alternate addresses in the desired protocol family for this host.
243//
244 if (!XrdNetUtils::GetAddrs(hName, &iP, iN, aOpts, 0) && iN)
245 {for (i = 0; i < iN; i++)
246 {if (iP[i].isPrivate()) iPVT = i;
247 else break;
248 }
249 if (i < iN) ifTab.prvt = false;
250 else if (iPVT >= 0) {i = iPVT; ifTab.prvt = true;}
251 if (i > iN) aOK = GenAddrs(ifTab, &iP[i]);
252 delete [] iP;
253 }
254
255// All done
256//
257 return aOK;
258}
259
260/******************************************************************************/
261/* Private: G e n I F */
262/******************************************************************************/
263
264#define ADDSLOT(xdst, xstr, xlen) {strcpy(ifBP->iVal,xstr);ifBP->iLen=xlen; \
265 xdst=ifBP; bP += (6 + xlen + (xlen & 0x01));ifBP = (ifData *)bP;}
266
267#define RLOSLOT(xdst) xdst = (ifData *)(ifBuff+((char *)xdst-buff))
268
269bool XrdNetIF::GenIF(XrdNetAddrInfo **src, int srcnum, const char *xName)
270{
271 ifAddrs ifTab;
272 const char *hName;
273 char buff[4096], *bP = buff;
274 ifData *ifBP = (ifData *)buff;
275 ifType ifT;
276 int i, n;
277 bool isPrivate;
278
279// Initialize all of the vectors and free the buffer if we allocated it
280//
281 for (i = 0; i < (int)ifMax; i++)
282 {ifName[i] = ifDest[i] = &ifNull;
283 ifxDNS[i] = false;
284 }
285 if (ifBuff) {free(ifBuff); ifBuff = 0;}
286
287for (i = 0; i < srcnum; i++)
288{
289
290// Generate interface addresses. Failure here is almost impossible.
291//
292 if (!src[i]) continue;
293 isPrivate = src[i]->isPrivate();
294 if (!GenAddrs(ifTab, src[i]))
295 {if (eDest) eDest->Emsg("SetIF", "Unable to validate net interfaces!");
296 return false;
297 }
298
299// Determine interface type
300//
301 if (isPrivate) ifT = (ifTab.ipV6 ? PrivateV6 : PrivateV4);
302 else ifT = (ifTab.ipV6 ? PublicV6 : PublicV4);
303
304// We can now check if we have a duplicate interface here
305//
306 if (ifDest[ifT] != &ifNull && eDest)
307 {char eBuff[64];
308 sprintf(eBuff, "Skipping duplicate %s interface",
309 (isPrivate ? "private" : "public"));
310 eDest->Emsg("SetIF", eBuff, ifTab.hDest);
311 continue;
312 }
313
314// Set the locate destination, always an address
315//
316 ADDSLOT(ifDest[ifT], ifTab.hDest, ifTab.hDLen);
317
318// If this is a private interface, then set private pointers to actual addresses
319// since, technically, private addresses should not be registered. Otherwise,
320// fill in the public interface information. We also set unregistered public
321// addresses (what a pain). Of course, that is a configurable detail.
322//
323 if (!rPIPA && isPrivate)
324 {ADDSLOT(ifName[ifT], ifTab.hAddr, ifTab.hALen);
325 } else {
326 hName = src[i]->Name();
327 if (!hName || !(src[i]->isRegistered())) hName = xName;
328 if (hName)
329 {ADDSLOT(ifName[ifT], hName, strlen(hName));
330 ifxDNS[ifT] = true;
331 } else ifName[ifT] = ifDest[ifT];
332 }
333}
334
335// At this point we have set all of the advertised interfaces. If this is a
336// registered host then we know we have the name and nest information but not
337// necessarily the locate destination for each protocol. So, we will try to
338// find them via DNS. If the host does not have an IPv6 address then we will
339// use the mapped IPv4 address and hope that the client is dual stacked.
340//
341 if (ifDest[PublicV4] == &ifNull && ifxDNS[PublicV6]
342 && GenAddrs(ifTab, ifName[PublicV6]->iVal, false))
343 {if (!ifTab.prvt)
344 {ADDSLOT(ifDest[PublicV4], ifTab.hDest, ifTab.hDLen);
345 ifName[PublicV4] = ifName[PublicV6];
346 ifxDNS[PublicV4] = ifxDNS[PublicV6];
347 } else if (ifDest[PrivateV4] == &ifNull)
348 {ADDSLOT(ifDest[PrivateV4], ifTab.hDest, ifTab.hDLen);
349 ifName[PrivateV4] = ifName[PublicV6];
350 ifxDNS[PrivateV4] = ifxDNS[PublicV6];
351 }
352 }
353
354 if (ifDest[PublicV6] == &ifNull && ifxDNS[PublicV4]
355 && GenAddrs(ifTab, ifName[PublicV4]->iVal, true))
356 {if (!ifTab.prvt)
357 {ADDSLOT(ifDest[PublicV6], ifTab.hDest, ifTab.hDLen);
358 ifName[PublicV6] = ifName[PublicV4];
359 ifxDNS[PublicV6] = ifxDNS[PublicV4];
360 } else if (ifDest[PrivateV6] == &ifNull)
361 {ADDSLOT(ifDest[PrivateV6], ifTab.hDest, ifTab.hDLen);
362 ifName[PrivateV6] = ifName[PublicV4];
363 ifxDNS[PrivateV6] = ifxDNS[PublicV4];
364 }
365 }
366
367// Allocate/Replace string storage area
368//
369 n = (char *)ifBP - buff;
370 if (!(ifBuff = (char *)malloc(n))) return false;
371 memcpy(ifBuff, buff, n);
372
373// Now relocate all the pointers in the name and dest vectors
374//
375 for (n = 0; n < (int)ifNum; n++)
376 {if (ifName[n] != &ifNull) RLOSLOT(ifName[n]);
377 if (ifDest[n] != &ifNull) RLOSLOT(ifDest[n]);
378 }
379
380// All done
381//
382 return true;
383}
384
385/******************************************************************************/
386/* G e t D e s t */
387/******************************************************************************/
388
389int XrdNetIF::GetDest(char *dest, int dlen, ifType ifT, bool prefn)
390{
391 ifType ifX = (ifT >= ifAny ? static_cast<ifType>(ifAvail) : ifT);
392 ifData *ifP = (prefn && ifxDNS[ifX] ? ifName[ifX] : ifDest[ifX]);
393 int n;
394
395// Compute length and make sure we don't overflow
396//
397 n = ifP->iLen + portSfx.len;
398 if (!(ifP->iLen) || n >= dlen) return 0;
399
400// Return result with port appended
401//
402 strcpy(dest, ifP->iVal);
403 strcpy(dest +ifP->iLen, portSfx.val);
404 return n;
405}
406
407
408/******************************************************************************/
409/* G e t P u b l i c D e s t */
410/******************************************************************************/
411
412int XrdNetIF::GetPublicDest(char *dest, size_t dlen)
413{
414 auto n = m_PublicName.size() + portSfx.len;
415 if (m_PublicName.empty() || n >= dlen) return 0;
416
417 strcpy(dest, m_PublicName.c_str());
418 strcpy(dest + m_PublicName.size(), portSfx.val);
419
420 return n;
421}
422
423/******************************************************************************/
424/* G e t I F */
425/******************************************************************************/
426
427#define prtaddr(x) std::cerr <<"Addr!!! " << *x <<std::endl;
428
429int XrdNetIF::GetIF(XrdOucTList **ifList, const char **eText)
430{
431 static const int prvIF[] = {havePrv4, havePrv6};
432 static const int pubIF[] = {havePub4, havePub6};
433
434 char ipBuff[256];
435 short ifIdx = 0, sval[4] = {0, 0, 0, 0};
436 short iLen;
437 int ifT, haveIF = 0;
438
439#ifdef HAVE_GETIFADDRS
440
441// Obtain the list of interfaces
442//
443 XrdNetAddr netAddr;
444 struct ifaddrs *ifBase, *ifP;
445 XrdOucTList *tLP, *tList = 0, *tLast = 0;
446 int n = 0;
447 bool anyIF = (ifCfg[0] == 0 && ifCfg[1] == 0);
448
449 if (getifaddrs(&ifBase) < 0)
450 {if (eText) *eText = XrdSysE2T(errno);
451 if (ifList) *ifList = 0;
452 if (eDest) eDest->Emsg("GetIF", errno, "get interface addresses.");
453 return 0;
454 }
455
456// Report only those interfaces that are up and are not loop-back devices and
457// have been specified by actual name
458//
459 ifP = ifBase;
460 while(ifP)
461 {if ((ifP->ifa_addr != 0)
462 && (!ifList || anyIF || IsOkName(ifP->ifa_name, ifIdx))
463 && (ifP->ifa_flags & (IFF_UP))
464 && (ifP->ifa_flags & (IFF_RUNNING))
465 && !(ifP->ifa_flags & (IFF_LOOPBACK))
466 && ((ifP->ifa_addr->sa_family == AF_INET &&
467 !V4LinkLocal(ifP->ifa_addr))
468 ||
469 (ifP->ifa_addr->sa_family == AF_INET6 &&
470 !(IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6 *)(ifP->ifa_addr))->sin6_addr)))
471 )
472 )
473 {if (ifP->ifa_addr->sa_family == AF_INET){haveIF |= haveIPv4;ifT=0;}
474 else {haveIF |= haveIPv6; ifT = 1;}
475 if (ifList)
476 {netAddr.Set(ifP->ifa_addr);
477 if ((iLen = netAddr.Format(ipBuff, sizeof(ipBuff),
479 {sval[2] = (anyIF ? 3 : ifIdx);
480 sval[1] = (netAddr.isPrivate() ? 1 : 0);
481 sval[0] = iLen;
482 haveIF |= (sval[1] ? prvIF[ifT] : pubIF[ifT]);
483 tLP = new XrdOucTList(ipBuff, sval);
484 if (tList) tLast->next = tLP;
485 else tList = tLP;
486 tLast = tLP;
487 n++;
488 }
489 } else {
490 netAddr.Set(ifP->ifa_addr);
491 haveIF |= (netAddr.isPrivate() ? prvIF[ifT] : pubIF[ifT]);
492 }
493 }
494 ifP = ifP->ifa_next;
495 }
496
497// All done
498//
499 if (ifBase) freeifaddrs(ifBase);
500 if (eText) *eText = 0;
501 if (!ifList) return haveIF;
502 *ifList = tList;
503 return n;
504
505#else
506
507// If we just need to provide the interface type, indicate we cannot
508//
509 if (!ifList) return haveNoGI;
510
511// For platforms that don't support getifaddrs() use our address
512//
513 XrdNetAddr netAddr((int)0);
514
515// Simply return our formatted address as the interface address
516//
517 if ((iLen = netAddr.Format(ipBuff, sizeof(ipBuff),
519 {if (eText) *eText = 0;
520 sval[0] = iLen;
521 *ifList = new XrdOucTList(ipBuff, sval);
522 return 1;
523 }
524
525// Something bad happened and it shouldn't have
526//
527 if (eText) *eText = "unknown error";
528 if (eDest) eDest->Emsg("GetIF", "Unable to get interface address; "
529 "check if IPV6 enabled!");
530 return 0;
531#endif
532}
533
534/******************************************************************************/
535
536int XrdNetIF::GetIF(char *buff, int blen, const char **eText, bool show)
537{
538 XrdOucTList *ifP, *ifN;
539 const char *ifName[3] = {ifCfg[0], ifCfg[1], "anon"};
540 char *bP = buff;
541 int n, bLeft = blen-8;
542 bool ifOK[3] = {false, false, false};
543
544#ifndef HAVE_GETIFADDRS
545// Display warning on how we are getting the interface addresses
546//
547 if (eDest && show)
548 eDest->Say("Config Warning: using DNS registered address as interface!");
549#endif
550
551// Create the interface list here
552//
553 *buff = 0;
554 if (GetIF(&ifN, eText))
555 {while((ifP = ifN))
556 {n = ifP->sval[0];
557 if (bLeft > n+2)
558 {if (bP != buff) {*bP++ = ' '; bLeft--;}
559 strcpy(bP, ifP->text);
560 bP += n; bLeft -= (n+1);
561 }
562 ifOK[ifP->sval[2]] = true;
563 if (show && eDest)
564 {const char *kind = (ifP->sval[1] ? " private" : " public ");
565 eDest->Say("Config ", ifName[ifP->sval[2]], kind,
566 " network interface: ", ifP->text);
567 }
568 ifN = ifP->next; delete ifP;
569 }
570 }
571
572// Warn about missing interfaces
573//
574 if (show && eDest)
575 {for (n = 0; n < 2; n++)
576 {if (!ifOK[n] && ifCfg[n])
577 eDest->Say("Config ", ifCfg[n],
578 " interface not found or is not usable.");
579 }
580 }
581
582// Return result
583//
584 return bP-buff;
585}
586
587/******************************************************************************/
588
589int XrdNetIF::GetIF(char *&ifline, const char **eText, bool show)
590{
591 char buff[4096];
592 int n;
593
594 if ((n = GetIF(buff, sizeof(buff), eText, show))) ifline = strdup(buff);
595 else ifline = 0;
596
597// Warn about no interfaces
598//
599 if (!ifline && show && eDest)
600 eDest->Say("Config ", "No usable interfaces; using DNS registered "
601 "address as the interface.");
602 return n;
603}
604
605/******************************************************************************/
606/* Private: G e t D o m a i n */
607/******************************************************************************/
608
609const char *XrdNetIF::GetDomain()
610{
611 const char *dnP = XrdNetIdentity::Domain();
612
613// Get our fully resilved name (this doesn't always work)
614//
615 return (dnP ? dnP+1 : 0);
616}
617
618/******************************************************************************/
619/* I n D o m a i n */
620/******************************************************************************/
621
623{
624 const char *hnP;
625
626// Do not attempt to resolve private addresses as they are always in the domain.
627//
628 if (epaddr->isPrivate()) return true;
629
630// Checkout the domain
631//
632 if (!myDomain || !(hnP = epaddr->Name(0)) || !(hnP = index(hnP, '.')))
633 return false;
634
635// Match the domain and returnthe result
636//
637 return strcmp(myDomain, hnP+1) == 0;
638}
639
640/******************************************************************************/
641/* I s O k N a m e */
642/******************************************************************************/
643
644bool XrdNetIF::IsOkName(const char *ifn, short &ifIdx)
645{
646 if (!ifn) return false;
647 if (ifCfg[0] && !strcmp(ifn, ifCfg[0])) ifIdx = 0;
648 else if (ifCfg[1] && !strcmp(ifn, ifCfg[1])) ifIdx = 1;
649 else return false;
650 return true;
651}
652
653/******************************************************************************/
654/* P o r t */
655/******************************************************************************/
656
657int XrdNetIF::Port(int pnum)
658{
659 int prevport = ifPort;
660
661// Check if anything is really changing
662//
663 pnum &= 0x0000ffff;
664 if (pnum == prevport) return prevport;
665
666// Format the port number (can't be more than 5 characters)
667//
668 portSfx.len = sprintf(portSfx.val, ":%d", pnum);
669 ifPort = pnum;
670
671// All done
672//
673 return prevport;
674}
675
676/******************************************************************************/
677/* P o r t D e f a u l t */
678/******************************************************************************/
679
680void XrdNetIF::PortDefault(int pnum) {dfPort = pnum;}
681
682/******************************************************************************/
683/* R o u t i n g */
684/******************************************************************************/
685
687{
688
689// Set the routing type
690//
691 netRoutes = (nettype == netDefault ? netLocal : nettype);
692
693// Based on the routing we need to set the appropriate selection mask vector
694//
695 if (netRoutes == netLocal) ifMaskVec = ifMaskLocal;
696 else if (netRoutes == netSplit) ifMaskVec = ifMaskSplit;
697 else ifMaskVec = ifMaskComm;
698}
699
700/******************************************************************************/
701/* S e t I F */
702/******************************************************************************/
703
704bool XrdNetIF::SetIF(XrdNetAddrInfo *src, const char *ifList, int port,
705 netType nettype, const char *xName)
706{
707 XrdNetAddrInfo *netIF[4] = {0,0,0,0}; //pub 0:v4, prv 1:v4 pub 2:v6 prv 3:v6
708 XrdNetAddr netAdr[4];
709 const char *ifErr = 0, *ifBeg = ifList, *ifEnd, *ifAdr, *ifBad = 0;
710 int i, n, ifCnt = 1;
711 char abuff[64];
712
713// Setup the port number (this sets ifPort)
714//
715 if (port >= 0) Port((port ? port : dfPort));
716
717// Set routing mode for this interface
718//
719 ifRoute = static_cast<short>(nettype == netDefault ? netRoutes : nettype);
720
721// If no list is supplied then fill out based on the source address
722//
723 if (!ifList || !(*ifList))
724 {XrdNetAddrInfo *ifVec[8];
725 XrdNetAddr *iP;
726 const char *hName = src->Name();
727 if (!(src->isRegistered()) && xName) hName = xName;
728 ifCnt = 0;
729 if (!hName
730 || XrdNetUtils::GetAddrs(hName,&iP,ifCnt,XrdNetUtils::allIPv64,ifPort)
731 || !ifCnt) return SetIF64(GenIF(&src, 1));
732 if (ifCnt > 8) ifCnt = 8;
733 for (i = 0; i < ifCnt; i++) ifVec[i] = &iP[i];
734 bool aOK = GenIF(ifVec, ifCnt, hName);
735 delete [] iP;
736 return SetIF64(aOK);
737 }
738
739// Prefrentially use the connect address as the primary interface. This
740// avoids using reported interfaces that may have strange routing.
741//
742 i = (src->isIPType(XrdNetAddrInfo::IPv4) || src->isMapped() ? 0 : 2);
743 if (src->isPrivate()) i |= 1;
744 netIF[i] = src;
745
746// Process the iflist (up to four interfaces)
747//
748 do {while (*ifBeg && *ifBeg == ' ') ifBeg++;
749 if ( !(*ifBeg)) break;
750 if (!(ifEnd = index(ifBeg, ' '))) {ifAdr = ifBeg; ifBeg = "";}
751 else {n = ifEnd - ifBeg;
752 if (n >= (int)sizeof(abuff))
753 {ifAdr = 0; ifBad = ifBeg; ifErr = "invalid";}
754 else {strncpy(abuff, ifBeg, n); abuff[n] = 0; ifAdr = abuff;}
755 ifBeg = ifEnd+1;
756 }
757 if (!ifAdr || (ifErr = netAdr[ifCnt].Set(ifAdr, ifPort)))
758 {if (eDest)
759 {if (!ifAdr) ifAdr = ifBad;
760 eDest->Emsg("SetIF", "Unable to use interface", ifAdr, ifErr);
761 }
762 continue;
763 }
764 i = (netAdr[ifCnt].isIPType(XrdNetAddrInfo::IPv4) ||
765 netAdr[ifCnt].isMapped() ? 0 : 2);
766 if (netAdr[ifCnt].isPrivate()) i |= 1;
767 if (!netIF[i]) netIF[i] = &netAdr[ifCnt--];
768 } while(ifCnt >= 0);
769
770// Set the interface data
771//
772 return SetIF64(GenIF(netIF, 4));
773}
774
775/******************************************************************************/
776/* S e t I F N a m e s */
777/******************************************************************************/
778
779bool XrdNetIF::SetIFNames(char *ifnames)
780{
781 char *comma;
782
783// Parse the interface names
784//
785 if ((comma = index(ifnames, ',')))
786 {if (comma == ifnames || !(*(comma+1)))
787 {if (eDest) eDest->Say("Config","Invalid interface name - ",ifnames);
788 return false;
789 }
790 }
791
792// Free old names, if any
793//
794 if (ifCfg[0]) free(ifCfg[0]);
795 if (ifCfg[1]) free(ifCfg[1]);
796
797// Copy the new names
798//
799 if (comma)
800 {*comma = 0;
801 ifCfg[1] = (strcmp(ifnames, comma+1) ? strdup(comma+1) : 0);
802 *comma = ',';
803 } else ifCfg[1] = 0;
804 ifCfg[0] = strdup(ifnames);
805 return true;
806}
807
808/******************************************************************************/
809/* Private: S e t I F P P */
810/******************************************************************************/
811
812void XrdNetIF::SetIFPP()
813{
814 int i, j;
815
816// For split network we use what we have
817//
818 if (netSplit == (netType)ifRoute) return;
819
820// Now set all undefined private interfaces for common and local network routing
821//
822 i = (int)PrivateV4; j = PublicV4;
823 do {if (ifName[i] == &ifNull) {ifName[i]=ifName[j]; ifxDNS[i]=ifxDNS[j];}
824 if (ifDest[i] == &ifNull) ifDest[i]=ifDest[j];
825 if (i == (int)PrivateV6) break;
826 i = (int)PrivateV6; j = (int)PublicV6;
827 } while(true);
828
829// If this is a common network then we are done
830//
831 if (netCommon == (netType)ifRoute) return;
832
833// Now set all undefined public interfaces for local network routing
834//
835 i = (int)PublicV4; j = PrivateV4;
836 do {if (ifName[i] == &ifNull) {ifName[i]=ifName[j]; ifxDNS[i]=ifxDNS[j];}
837 if (ifDest[i] == &ifNull) ifDest[i]=ifDest[j];
838 if (i == (int)PublicV6) break;
839 i = (int)PublicV6; j = (int)PrivateV6;
840 } while(true);
841}
842
843/******************************************************************************/
844/* Private: S e t I F 6 4 */
845/******************************************************************************/
846
847bool XrdNetIF::SetIF64(bool retVal)
848{
849 static const int ifN46= 4;
850 static ifType ifSet[ifN46] = {Public46, Private46, Public64, Private64};
851 static ifType ifChk[ifN46] = {PublicV4, PrivateV4, PublicV6, PrivateV6};
852 static ifType eqSel[ifN46] = {PublicV6, PrivateV6, PublicV4, PrivateV4};
853 static ifType neSel[ifN46] = {PublicV4, PrivateV4, PublicV6, PrivateV6};
854
855// Readjust routing tables if this is not a split network
856//
857 if (netSplit != (netType)ifRoute) SetIFPP();
858
859// Fill out the 4/6 6/4 tables and compute the selection mask
860//
861 ifMask = 0;
862 for (int i = 0; i < ifN46; i++)
863 {ifName[ifSet[i]] = (ifName[ifChk[i]] == &ifNull ? ifName[eqSel[i]]
864 : ifName[neSel[i]]);
865 ifDest[ifSet[i]] = (ifDest[ifChk[i]] == &ifNull ? ifDest[eqSel[i]]
866 : ifDest[neSel[i]]);
867 ifxDNS[ifSet[i]] = ifName[ifSet[i]] != &ifNull &&
868 isalpha(*(ifName[ifSet[i]]->iVal));
869 if (ifDest[ifChk[i]] != &ifNull) ifMask |= sMask[i];
870 }
871
872// Record the one that is actually present
873//
874 if (ifName[Public64] != &ifNull) ifAvail = static_cast<char>(Public64);
875 else ifAvail = static_cast<char>(Private64);
876
877// Return wha the caller wants us to return
878//
879 return retVal;
880}
881
882/******************************************************************************/
883/* S e t M s g s */
884/******************************************************************************/
885
886void XrdNetIF::SetMsgs(XrdSysError *erp) {eDest = erp;}
887
888/******************************************************************************/
889/* S e t R P I P A */
890/******************************************************************************/
891
892void XrdNetIF::SetRPIPA(bool rval) {rPIPA = rval;}
893
894/******************************************************************************/
895/* Private: V 4 L i n k L o c a l */
896/******************************************************************************/
897
898bool XrdNetIF::V4LinkLocal(struct sockaddr *saP)
899{
900 unsigned char *ipV4;
901
902 ipV4 = (unsigned char *)&((sockaddr_in *)(saP))->sin_addr.s_addr;
903 return ipV4[0] == 169 && ipV4[1] == 254;
904}
static XrdSysError eDest(0,"crypto_")
#define RLOSLOT(xdst)
Definition XrdNetIF.cc:267
#define ADDSLOT(xdst, xstr, xlen)
Definition XrdNetIF.cc:264
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
static const int noPort
Do not add port number.
static const int old6Map4
Use deprecated IPV6 mapped format.
bool isMapped() const
bool isIPType(IPType ipType) const
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
@ fmtAddr
Address using suitable ipv4 or ipv6 format.
const char * Name(const char *eName=0, const char **eText=0)
const char * Set(const char *hSpec, int pNum=PortInSpec)
static const int haveNoGI
ifList == 0 && getifaddrs() is not supported
Definition XrdNetIF.hh:194
bool SetIF(XrdNetAddrInfo *src, const char *ifList, int port=0, netType nettype=netDefault, const char *xName=0)
Definition XrdNetIF.cc:704
static const int haveIPv4
ifList == 0 && non-local ipv4 i/f found (or'd)
Definition XrdNetIF.hh:196
static void SetRPIPA(bool rval)
Definition XrdNetIF.cc:892
static bool InDomain(XrdNetAddrInfo *epaddr)
Definition XrdNetIF.cc:622
void Display(const char *pfx="=====> ")
Definition XrdNetIF.cc:142
static int GetIF(XrdOucTList **ifList, const char **eText=0)
Definition XrdNetIF.cc:429
static void Routing(netType nettype)
Definition XrdNetIF.cc:686
int Port()
Definition XrdNetIF.hh:322
static void SetMsgs(XrdSysError *erp)
Definition XrdNetIF.cc:886
static void PortDefault(int pnum=1094)
Definition XrdNetIF.cc:680
static const int havePub6
ifList == 0 && public ipv6 i/f found (or'd)
Definition XrdNetIF.hh:206
static bool SetIFNames(char *ifnames)
Definition XrdNetIF.cc:779
int GetPublicDest(char *dest, size_t dlen)
Definition XrdNetIF.cc:412
static const int havePub4
ifList == 0 && public ipv4 i/f found (or'd)
Definition XrdNetIF.hh:204
int GetDest(char *dest, int dlen, ifType ifT=PublicV6, bool prefn=false)
Definition XrdNetIF.cc:389
static const int haveIPv6
ifList == 0 && non-local ipv6 i/f found (or'd)
Definition XrdNetIF.hh:198
ifType
The enum that is used to index into ifData to get appropriate interface.
Definition XrdNetIF.hh:65
@ PrivateV4
Definition XrdNetIF.hh:66
@ Private64
Definition XrdNetIF.hh:74
@ Private46
Definition XrdNetIF.hh:72
@ PrivateV6
Definition XrdNetIF.hh:68
static const int havePrv6
ifList == 0 && private ipv6 i/f found (or'd)
Definition XrdNetIF.hh:202
static const int havePrv4
ifList == 0 && private ipv4 i/f found (or'd)
Definition XrdNetIF.hh:200
static const char * Domain(const char **eText=0)
static const char * GetAddrs(const char *hSpec, XrdNetAddr *aListP[], int &aListN, AddrOpts opts=allIPMap, int pNum=PortInSpec)
XrdOucTList * next