34 #include <sys/types.h>
36 #ifdef HAVE_GETIFADDRS
59 const char hasPub4 = 0x01;
60 const char hasPrv4 = 0x02;
61 const char hasPub6 = 0x04;
62 const char hasPrv6 = 0x08;
63 const char hasAny4 = hasPub4 | hasPrv4;
64 const char hasAny6 = hasPub6 | hasPrv6;
69 const char sMask[hasNum] = {hasPub4, hasPrv4, hasPub6, hasPrv6};
70 const char *sName[hasNum] = {
"pub4 ",
"prv4 ",
"pub6 ",
"prv6"};
110 const char *XrdNetIF::myDomain = XrdNetIF::GetDomain();
112 char *XrdNetIF::ifCfg[2] = {0,0};
114 const char *XrdNetIF::ifTName[ifMax] = {
"public IPv4",
128 const char *XrdNetIF::ifMaskVec = ifMaskLocal;
132 int XrdNetIF::dfPort = 1094;
134 XrdNetIF::ifData XrdNetIF::ifNull;
136 bool XrdNetIF::rPIPA =
false;
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 =
"";
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;}
167 for (
int i = 0; i < hasNum; i++)
168 if (ifMask & sMask[i]) iHX[i] = sName[i];
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);
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);
200 {
if (!(ifTab.hALen = src->
Format(ifTab.hAddr,
sizeof(ifTab.hAddr),
202 || !(ifTab.hDLen = src->
Format(ifTab.hDest,
sizeof(ifTab.hDest),
212 if (!src->
Format(ifTab.hAddr,
sizeof(ifTab.hAddr),
214 if (!(Colon = rindex(ifTab.hAddr,
':')))
return false;
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),
225 if (!(ifTab.hALen = src->
Format(ifTab.hAddr,
sizeof(ifTab.hAddr),
227 || !(ifTab.hDLen = src->
Format(ifTab.hDest,
sizeof(ifTab.hDest),
234 bool XrdNetIF::GenAddrs(ifAddrs &ifTab,
const char *hName,
bool wantV6)
239 int i, iN, iPVT = -1;
245 {
for (i = 0; i < iN; i++)
246 {
if (iP[i].isPrivate()) iPVT = i;
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]);
264 #define ADDSLOT(xdst, xstr, xlen) {strcpy(ifBP->iVal,xstr);ifBP->iLen=xlen; \
265 xdst=ifBP; bP += (6 + xlen + (xlen & 0x01));ifBP = (ifData *)bP;}
267 #define RLOSLOT(xdst) xdst = (ifData *)(ifBuff+((char *)xdst-buff))
269 bool XrdNetIF::GenIF(
XrdNetAddrInfo **src,
int srcnum,
const char *xName)
273 char buff[4096], *bP = buff;
274 ifData *ifBP = (ifData *)buff;
281 for (i = 0; i < (int)
ifMax; i++)
282 {ifName[i] = ifDest[i] = &ifNull;
285 if (ifBuff) {free(ifBuff); ifBuff = 0;}
287 for (i = 0; i < srcnum; i++)
292 if (!src[i])
continue;
294 if (!GenAddrs(ifTab, src[i]))
295 {
if (eDest) eDest->
Emsg(
"SetIF",
"Unable to validate net interfaces!");
306 if (ifDest[ifT] != &ifNull && eDest)
308 sprintf(eBuff,
"Skipping duplicate %s interface",
309 (isPrivate ?
"private" :
"public"));
310 eDest->
Emsg(
"SetIF", eBuff, ifTab.hDest);
316 ADDSLOT(ifDest[ifT], ifTab.hDest, ifTab.hDLen);
323 if (!rPIPA && isPrivate)
324 {
ADDSLOT(ifName[ifT], ifTab.hAddr, ifTab.hALen);
326 hName = src[i]->
Name();
327 if (!hName || !(src[i]->isRegistered())) hName = xName;
329 {
ADDSLOT(ifName[ifT], hName, strlen(hName));
331 }
else ifName[ifT] = ifDest[ifT];
342 && GenAddrs(ifTab, ifName[
PublicV6]->iVal,
false))
355 && GenAddrs(ifTab, ifName[
PublicV4]->iVal,
true))
369 n = (
char *)ifBP - buff;
370 if (!(ifBuff = (
char *)malloc(n)))
return false;
371 memcpy(ifBuff, buff, n);
375 for (n = 0; n < (int)
ifNum; n++)
376 {
if (ifName[n] != &ifNull)
RLOSLOT(ifName[n]);
377 if (ifDest[n] != &ifNull)
RLOSLOT(ifDest[n]);
392 ifData *ifP = (prefn && ifxDNS[ifX] ? ifName[ifX] : ifDest[ifX]);
397 n = ifP->iLen + portSfx.len;
398 if (!(ifP->iLen) || n >= dlen)
return 0;
402 strcpy(dest, ifP->iVal);
403 strcpy(dest +ifP->iLen, portSfx.val);
414 auto n = m_PublicName.size() + portSfx.len;
415 if (m_PublicName.empty() || n >= dlen)
return 0;
417 strcpy(dest, m_PublicName.c_str());
418 strcpy(dest + m_PublicName.size(), portSfx.val);
427 #define prtaddr(x) std::cerr <<"Addr!!! " << *x <<std::endl;
435 short ifIdx = 0, sval[4] = {0, 0, 0, 0};
439 #ifdef HAVE_GETIFADDRS
444 struct ifaddrs *ifBase, *ifP;
447 bool anyIF = (ifCfg[0] == 0 && ifCfg[1] == 0);
449 if (getifaddrs(&ifBase) < 0)
451 if (ifList) *ifList = 0;
452 if (
eDest)
eDest->
Emsg(
"GetIF", errno,
"get interface addresses.");
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))
469 (ifP->ifa_addr->sa_family == AF_INET6 &&
470 !(IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6 *)(ifP->ifa_addr))->sin6_addr)))
473 {
if (ifP->ifa_addr->sa_family == AF_INET){haveIF |=
haveIPv4;ifT=0;}
476 {netAddr.
Set(ifP->ifa_addr);
477 if ((iLen = netAddr.
Format(ipBuff,
sizeof(ipBuff),
479 {sval[2] = (anyIF ? 3 : ifIdx);
482 haveIF |= (sval[1] ? prvIF[ifT] : pubIF[ifT]);
484 if (tList) tLast->next = tLP;
490 netAddr.
Set(ifP->ifa_addr);
491 haveIF |= (netAddr.
isPrivate() ? prvIF[ifT] : pubIF[ifT]);
499 if (ifBase) freeifaddrs(ifBase);
500 if (eText) *eText = 0;
501 if (!ifList)
return haveIF;
517 if ((iLen = netAddr.
Format(ipBuff,
sizeof(ipBuff),
519 {
if (eText) *eText = 0;
527 if (eText) *eText =
"unknown error";
528 if (
eDest)
eDest->
Emsg(
"GetIF",
"Unable to get interface address; "
529 "check if IPV6 enabled!");
539 const char *ifName[3] = {ifCfg[0], ifCfg[1],
"anon"};
541 int n, bLeft = blen-8;
542 bool ifOK[3] = {
false,
false,
false};
544 #ifndef HAVE_GETIFADDRS
548 eDest->
Say(
"Config Warning: using DNS registered address as interface!");
554 if (
GetIF(&ifN, eText))
558 {
if (bP != buff) {*bP++ =
' '; bLeft--;}
559 strcpy(bP, ifP->
text);
560 bP += n; bLeft -= (n+1);
562 ifOK[ifP->sval[2]] =
true;
564 {
const char *kind = (ifP->sval[1] ?
" private" :
" public ");
565 eDest->
Say(
"Config ", ifName[ifP->sval[2]], kind,
566 " network interface: ", ifP->
text);
568 ifN = ifP->
next;
delete ifP;
575 {
for (n = 0; n < 2; n++)
576 {
if (!ifOK[n] && ifCfg[n])
578 " interface not found or is not usable.");
594 if ((n =
GetIF(buff,
sizeof(buff), eText, show))) ifline = strdup(buff);
599 if (!ifline && show &&
eDest)
600 eDest->
Say(
"Config ",
"No usable interfaces; using DNS registered "
601 "address as the interface.");
609 const char *XrdNetIF::GetDomain()
615 return (dnP ? dnP+1 : 0);
632 if (!
myDomain || !(hnP = epaddr->
Name(0)) || !(hnP = index(hnP,
'.')))
637 return strcmp(
myDomain, hnP+1) == 0;
644 bool XrdNetIF::IsOkName(
const char *ifn,
short &ifIdx)
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;
659 int prevport = ifPort;
664 if (pnum == prevport)
return prevport;
668 portSfx.len = sprintf(portSfx.val,
":%d", pnum);
695 if (netRoutes ==
netLocal) ifMaskVec = ifMaskLocal;
696 else if (netRoutes ==
netSplit) ifMaskVec = ifMaskSplit;
697 else ifMaskVec = ifMaskComm;
705 netType nettype,
const char *xName)
709 const char *ifErr = 0, *ifBeg = ifList, *ifEnd, *ifAdr, *ifBad = 0;
715 if (port >= 0)
Port((port ? port : dfPort));
719 ifRoute =
static_cast<short>(nettype ==
netDefault ? netRoutes : nettype);
723 if (!ifList || !(*ifList))
726 const char *hName = src->
Name();
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);
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;}
757 if (!ifAdr || (ifErr = netAdr[ifCnt].Set(ifAdr, ifPort)))
759 {
if (!ifAdr) ifAdr = ifBad;
760 eDest->
Emsg(
"SetIF",
"Unable to use interface", ifAdr, ifErr);
766 if (netAdr[ifCnt].isPrivate()) i |= 1;
767 if (!netIF[i]) netIF[i] = &netAdr[ifCnt--];
772 return SetIF64(GenIF(netIF, 4));
785 if ((comma = index(ifnames,
',')))
786 {
if (comma == ifnames || !(*(comma+1)))
787 {
if (
eDest)
eDest->
Say(
"Config",
"Invalid interface name - ",ifnames);
794 if (ifCfg[0]) free(ifCfg[0]);
795 if (ifCfg[1]) free(ifCfg[1]);
801 ifCfg[1] = (strcmp(ifnames, comma+1) ? strdup(comma+1) : 0);
804 ifCfg[0] = strdup(ifnames);
812 void XrdNetIF::SetIFPP()
823 do {
if (ifName[i] == &ifNull) {ifName[i]=ifName[j]; ifxDNS[i]=ifxDNS[j];}
824 if (ifDest[i] == &ifNull) ifDest[i]=ifDest[j];
836 do {
if (ifName[i] == &ifNull) {ifName[i]=ifName[j]; ifxDNS[i]=ifxDNS[j];}
837 if (ifDest[i] == &ifNull) ifDest[i]=ifDest[j];
847 bool XrdNetIF::SetIF64(
bool retVal)
849 static const int ifN46= 4;
862 for (
int i = 0; i < ifN46; i++)
863 {ifName[ifSet[i]] = (ifName[ifChk[i]] == &ifNull ? ifName[eqSel[i]]
865 ifDest[ifSet[i]] = (ifDest[ifChk[i]] == &ifNull ? ifDest[eqSel[i]]
867 ifxDNS[ifSet[i]] = ifName[ifSet[i]] != &ifNull &&
868 isalpha(*(ifName[ifSet[i]]->iVal));
869 if (ifDest[ifChk[i]] != &ifNull) ifMask |= sMask[i];
875 else ifAvail =
static_cast<char>(
Private64);
898 bool XrdNetIF::V4LinkLocal(
struct sockaddr *saP)
902 ipV4 = (
unsigned char *)&((sockaddr_in *)(saP))->sin_addr.s_addr;
903 return ipV4[0] == 169 && ipV4[1] == 254;
static XrdSysError eDest(0,"crypto_")
#define ADDSLOT(xdst, xstr, xlen)
const char * XrdSysE2T(int errcode)
static const int noPort
Do not add port number.
static const int old6Map4
Use deprecated IPV6 mapped format.
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
bool SetIF(XrdNetAddrInfo *src, const char *ifList, int port=0, netType nettype=netDefault, const char *xName=0)
static const int haveIPv4
ifList == 0 && non-local ipv4 i/f found (or'd)
static void SetRPIPA(bool rval)
static bool InDomain(XrdNetAddrInfo *epaddr)
void Display(const char *pfx="=====> ")
static int GetIF(XrdOucTList **ifList, const char **eText=0)
static void Routing(netType nettype)
static void SetMsgs(XrdSysError *erp)
static void PortDefault(int pnum=1094)
static const int havePub6
ifList == 0 && public ipv6 i/f found (or'd)
static bool SetIFNames(char *ifnames)
int GetPublicDest(char *dest, size_t dlen)
static const int havePub4
ifList == 0 && public ipv4 i/f found (or'd)
int GetDest(char *dest, int dlen, ifType ifT=PublicV6, bool prefn=false)
static const int haveIPv6
ifList == 0 && non-local ipv6 i/f found (or'd)
ifType
The enum that is used to index into ifData to get appropriate interface.
static const int havePrv6
ifList == 0 && private ipv6 i/f found (or'd)
static const int havePrv4
ifList == 0 && private ipv4 i/f found (or'd)
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)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)