XRootD
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"
43 #include "XrdNet/XrdNetIdentity.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 
55 namespace
56 {
57 // Selection mask values
58 //
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;
65 const int hasNum = 4;
66 
67 // Name translation table
68 //
69 const char sMask[hasNum] = {hasPub4, hasPrv4, hasPub6, hasPrv6};
70 const 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 
108 XrdSysError *XrdNetIF::eDest = 0;
109 
110 const char *XrdNetIF::myDomain = XrdNetIF::GetDomain();
111 
112 char *XrdNetIF::ifCfg[2] = {0,0}; // public, private
113 
114 const 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 //
128 const char *XrdNetIF::ifMaskVec = ifMaskLocal;
129 
130 XrdNetIF::netType XrdNetIF::netRoutes = XrdNetIF::netLocal;
131 
132 int XrdNetIF::dfPort = 1094;
133 
134 XrdNetIF::ifData XrdNetIF::ifNull;
135 
136 bool XrdNetIF::rPIPA = false;
137 
138 /******************************************************************************/
139 /* D i s p l a y */
140 /******************************************************************************/
141 
142 void 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 
190 bool 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;
199  if (src->isIPType(XrdNetAddrInfo::IPv4))
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 
234 bool 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 
269 bool 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 
287 for (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 
389 int 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 
412 int 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 
429 int 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 
536 int 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 
589 int 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 
609 const 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 
644 bool 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 
657 int 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 
680 void 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 
704 bool 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 
779 bool 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 
812 void 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 
847 bool 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 
887 
888 /******************************************************************************/
889 /* S e t R P I P A */
890 /******************************************************************************/
891 
892 void XrdNetIF::SetRPIPA(bool rval) {rPIPA = rval;}
893 
894 /******************************************************************************/
895 /* Private: V 4 L i n k L o c a l */
896 /******************************************************************************/
897 
898 bool 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)
Definition: XrdNetAddr.cc:216
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
@ Public46
Definition: XrdNetIF.hh:71
@ PublicV4
Definition: XrdNetIF.hh:65
@ Private64
Definition: XrdNetIF.hh:74
@ Public64
Definition: XrdNetIF.hh:73
@ Private46
Definition: XrdNetIF.hh:72
@ PrivateV6
Definition: XrdNetIF.hh:68
@ PublicV6
Definition: XrdNetIF.hh:67
static const int havePrv6
ifList == 0 && private ipv6 i/f found (or'd)
Definition: XrdNetIF.hh:202
@ netSplit
Definition: XrdNetIF.hh:364
@ netDefault
Definition: XrdNetIF.hh:364
@ netCommon
Definition: XrdNetIF.hh:364
@ netLocal
Definition: XrdNetIF.hh:364
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)
Definition: XrdNetUtils.cc:239
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
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)
Definition: XrdSysError.cc:141
const char * myDomain