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;
69const char sMask[hasNum] = {hasPub4, hasPrv4, hasPub6, hasPrv6};
70const char *sName[hasNum] = {
"pub4 ",
"prv4 ",
"pub6 ",
"prv6"};
110const char *XrdNetIF::myDomain = XrdNetIF::GetDomain();
112char *XrdNetIF::ifCfg[2] = {0,0};
114const char *XrdNetIF::ifTName[ifMax] = {
"public IPv4",
128const char *XrdNetIF::ifMaskVec = ifMaskLocal;
132int XrdNetIF::dfPort = 1094;
134XrdNetIF::ifData XrdNetIF::ifNull;
136bool 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),
234bool 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))
269bool 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;}
287for (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);
411#define prtaddr(x) std::cerr <<"Addr!!! " << *x <<std::endl;
419 short ifIdx = 0, sval[4] = {0, 0, 0, 0};
423#ifdef HAVE_GETIFADDRS
428 struct ifaddrs *ifBase, *ifP;
431 bool anyIF = (ifCfg[0] == 0 && ifCfg[1] == 0);
433 if (getifaddrs(&ifBase) < 0)
435 if (ifList) *ifList = 0;
436 if (
eDest)
eDest->
Emsg(
"GetIF", errno,
"get interface addresses.");
445 {
if ((ifP->ifa_addr != 0)
446 && (!ifList || anyIF || IsOkName(ifP->ifa_name, ifIdx))
447 && (ifP->ifa_flags & (IFF_UP))
448 && (ifP->ifa_flags & (IFF_RUNNING))
449 && !(ifP->ifa_flags & (IFF_LOOPBACK))
450 && ((ifP->ifa_addr->sa_family == AF_INET &&
451 !V4LinkLocal(ifP->ifa_addr))
453 (ifP->ifa_addr->sa_family == AF_INET6 &&
454 !(IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6 *)(ifP->ifa_addr))->sin6_addr)))
457 {
if (ifP->ifa_addr->sa_family == AF_INET){haveIF |=
haveIPv4;ifT=0;}
460 {netAddr.
Set(ifP->ifa_addr);
461 if ((iLen = netAddr.
Format(ipBuff,
sizeof(ipBuff),
463 {sval[2] = (anyIF ? 3 : ifIdx);
466 haveIF |= (sval[1] ? prvIF[ifT] : pubIF[ifT]);
468 if (tList) tLast->next = tLP;
474 netAddr.
Set(ifP->ifa_addr);
475 haveIF |= (netAddr.
isPrivate() ? prvIF[ifT] : pubIF[ifT]);
483 if (ifBase) freeifaddrs(ifBase);
484 if (eText) *eText = 0;
485 if (!ifList)
return haveIF;
501 if ((iLen = netAddr.
Format(ipBuff,
sizeof(ipBuff),
503 {
if (eText) *eText = 0;
511 if (eText) *eText =
"unknown error";
512 if (
eDest)
eDest->
Emsg(
"GetIF",
"Unable to get interface address; "
513 "check if IPV6 enabled!");
523 const char *ifName[3] = {ifCfg[0], ifCfg[1],
"anon"};
525 int n, bLeft = blen-8;
526 bool ifOK[3] = {
false,
false,
false};
528#ifndef HAVE_GETIFADDRS
532 eDest->
Say(
"Config Warning: using DNS registered address as interface!");
538 if (
GetIF(&ifN, eText))
542 {
if (bP != buff) {*bP++ =
' '; bLeft--;}
543 strcpy(bP, ifP->
text);
544 bP += n; bLeft -= (n+1);
546 ifOK[ifP->sval[2]] =
true;
548 {
const char *kind = (ifP->sval[1] ?
" private" :
" public ");
549 eDest->
Say(
"Config ", ifName[ifP->sval[2]], kind,
550 " network interface: ", ifP->
text);
552 ifN = ifP->
next;
delete ifP;
559 {
for (n = 0; n < 2; n++)
560 {
if (!ifOK[n] && ifCfg[n])
562 " interface not found or is not usable.");
578 if ((n =
GetIF(buff,
sizeof(buff), eText, show))) ifline = strdup(buff);
583 if (!ifline && show &&
eDest)
584 eDest->
Say(
"Config ",
"No usable interfaces; using DNS registered "
585 "address as the interface.");
593const char *XrdNetIF::GetDomain()
599 return (dnP ? dnP+1 : 0);
616 if (!myDomain || !(hnP = epaddr->
Name(0)) || !(hnP = index(hnP,
'.')))
621 return strcmp(myDomain, hnP+1) == 0;
628bool XrdNetIF::IsOkName(
const char *ifn,
short &ifIdx)
630 if (!ifn)
return false;
631 if (ifCfg[0] && !strcmp(ifn, ifCfg[0])) ifIdx = 0;
632 else if (ifCfg[1] && !strcmp(ifn, ifCfg[1])) ifIdx = 1;
643 int prevport = ifPort;
648 if (pnum == prevport)
return prevport;
652 portSfx.len = sprintf(portSfx.val,
":%d", pnum);
679 if (netRoutes ==
netLocal) ifMaskVec = ifMaskLocal;
680 else if (netRoutes ==
netSplit) ifMaskVec = ifMaskSplit;
681 else ifMaskVec = ifMaskComm;
689 netType nettype,
const char *xName)
693 const char *ifErr = 0, *ifBeg = ifList, *ifEnd, *ifAdr, *ifBad = 0;
699 if (port >= 0)
Port((port ? port : dfPort));
703 ifRoute =
static_cast<short>(nettype ==
netDefault ? netRoutes : nettype);
707 if (!ifList || !(*ifList))
710 const char *hName = src->
Name();
715 || !ifCnt)
return SetIF64(GenIF(&src, 1));
716 if (ifCnt > 8) ifCnt = 8;
717 for (i = 0; i < ifCnt; i++) ifVec[i] = &iP[i];
718 bool aOK = GenIF(ifVec, ifCnt, hName);
732 do {
while (*ifBeg && *ifBeg ==
' ') ifBeg++;
733 if ( !(*ifBeg))
break;
734 if (!(ifEnd = index(ifBeg,
' '))) {ifAdr = ifBeg; ifBeg =
"";}
735 else {n = ifEnd - ifBeg;
736 if (n >= (
int)
sizeof(abuff))
737 {ifAdr = 0; ifBad = ifBeg; ifErr =
"invalid";}
738 else {strncpy(abuff, ifBeg, n); abuff[n] = 0; ifAdr = abuff;}
741 if (!ifAdr || (ifErr = netAdr[ifCnt].Set(ifAdr, ifPort)))
743 {
if (!ifAdr) ifAdr = ifBad;
744 eDest->
Emsg(
"SetIF",
"Unable to use interface", ifAdr, ifErr);
749 netAdr[ifCnt].isMapped() ? 0 : 2);
750 if (netAdr[ifCnt].isPrivate()) i |= 1;
751 if (!netIF[i]) netIF[i] = &netAdr[ifCnt--];
756 return SetIF64(GenIF(netIF, 4));
769 if ((comma = index(ifnames,
',')))
770 {
if (comma == ifnames || !(*(comma+1)))
771 {
if (
eDest)
eDest->
Say(
"Config",
"Invalid interface name - ",ifnames);
778 if (ifCfg[0]) free(ifCfg[0]);
779 if (ifCfg[1]) free(ifCfg[1]);
785 ifCfg[1] = (strcmp(ifnames, comma+1) ? strdup(comma+1) : 0);
788 ifCfg[0] = strdup(ifnames);
796void XrdNetIF::SetIFPP()
807 do {
if (ifName[i] == &ifNull) {ifName[i]=ifName[j]; ifxDNS[i]=ifxDNS[j];}
808 if (ifDest[i] == &ifNull) ifDest[i]=ifDest[j];
820 do {
if (ifName[i] == &ifNull) {ifName[i]=ifName[j]; ifxDNS[i]=ifxDNS[j];}
821 if (ifDest[i] == &ifNull) ifDest[i]=ifDest[j];
831bool XrdNetIF::SetIF64(
bool retVal)
833 static const int ifN46= 4;
846 for (
int i = 0; i < ifN46; i++)
847 {ifName[ifSet[i]] = (ifName[ifChk[i]] == &ifNull ? ifName[eqSel[i]]
849 ifDest[ifSet[i]] = (ifDest[ifChk[i]] == &ifNull ? ifDest[eqSel[i]]
851 ifxDNS[ifSet[i]] = ifName[ifSet[i]] != &ifNull &&
852 isalpha(*(ifName[ifSet[i]]->iVal));
853 if (ifDest[ifChk[i]] != &ifNull) ifMask |= sMask[i];
859 else ifAvail =
static_cast<char>(
Private64);
882bool XrdNetIF::V4LinkLocal(
struct sockaddr *saP)
886 ipV4 = (
unsigned char *)&((sockaddr_in *)(saP))->sin_addr.s_addr;
887 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)
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)