35 #include <arpa/inet.h>
36 #include <sys/types.h>
52 #if defined(__solaris__)
53 #define s6_addr32 _S6_un._S6_u32
54 #elif defined(__APPLE__) || defined(__FreeBSD__)
55 #define s6_addr32 __u6_addr.__u6_addr32
71 if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) >= 0)
close(fd);
72 else if (errno == EAFNOSUPPORT)
80 struct addrinfo *XrdNetAddr::hostHints = XrdNetAddr::Hints(0, 0);
82 struct addrinfo *XrdNetAddr::huntHintsTCP = XrdNetAddr::Hints(1, SOCK_STREAM);
84 struct addrinfo *XrdNetAddr::huntHintsUDP = XrdNetAddr::Hints(2, SOCK_DGRAM);
88 bool XrdNetAddr::useIPV4 = OnlyIPV4();
89 bool XrdNetAddr::dynDNS =
false;
104 if (!fqn ||
Set(fqn, port))
105 {
Set(
"localhost", port);
117 struct addrinfo *XrdNetAddr::Hints(
int htype,
int stype)
119 static struct addrinfo theHints[3];
124 memset(&theHints[htype], 0,
sizeof(
struct addrinfo));;
125 if (htype) theHints[htype].ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
126 else theHints[htype].ai_flags = AI_V4MAPPED | AI_CANONNAME;
127 theHints[htype].ai_family = AF_UNSPEC;
128 theHints[htype].ai_socktype = stype;
129 return &theHints[htype];
136 bool XrdNetAddr::Map64()
141 if (!IN6_IS_ADDR_V4MAPPED(&
IP.
v6.sin6_addr))
return false;
145 IP.
v4.sin_addr.s_addr =
IP.
v6.sin6_addr.s6_addr32[3];
146 IP.
v4.sin_family = AF_INET;
160 if (
IP.
Addr.sa_family != AF_INET &&
IP.
Addr.sa_family != AF_INET6)
166 if (pNum < 0)
return ntohs(
IP.
v6.sin6_port);
171 if (pNum > 0xffff)
return -1;
172 IP.
v6.sin6_port = htons(
static_cast<short>(pNum));
198 for (i = 0; i < aListNum; i++) {
if (
Same(&aListVec[i]))
break;}
203 if (i >= aListNum)
return false;
218 static const char *badIPv4 =
"invalid IPv4 address";
219 static const char *badIPv6 =
"invalid IPv6 address";
220 static const char *badIP64 =
"IPv6 address not IPv4 representable";
221 static const char *badName =
"invalid host name";
222 static const int map46ID = htonl(0x0000ffff);
224 const char *Colon, *iP;
225 char aBuff[NI_MAXHOST+INET6_ADDRSTRLEN];
232 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
233 memset(&
IP, 0,
sizeof(
IP));
240 {
IP.
v4.sin_family = AF_INET;
241 IP.
v4.sin_addr.s_addr = INADDR_ANY;
245 IP.
v6.sin6_family = AF_INET6;
246 IP.
v6.sin6_addr = in6addr_any;
249 if (pNum < 0) pNum= -pNum;
250 IP.
v6.sin6_port = htons(
static_cast<short>(pNum));
257 {
if (strlen(hSpec) >=
sizeof(unixPipe->sun_path))
return "path too long";
258 unixPipe =
new sockaddr_un;
259 strcpy(unixPipe->sun_path, hSpec);
260 unixPipe->sun_family =
IP.
Addr.sa_family = AF_UNIX;
268 aLen = strlen(hSpec);
269 if (aLen >= (
int)
sizeof(aBuff))
return "host id too long";
275 {
const char *Brak = index(hSpec+1,
']');
276 if (!Brak)
return badIPv6;
278 if (!(*Colon)) Colon = 0;
279 else if (*Colon !=
':')
return badIPv6;
280 aLen = Brak - (hSpec+1);
281 if (aLen >= INET6_ADDRSTRLEN)
return badIPv6;
282 mapIt = (*(hSpec+1) ==
':' && *(hSpec+2) ==
':'
283 && *(hSpec+3) >=
'0' && *(hSpec+3) <=
'9'
284 && (iP = index(hSpec+4,
'.')) && iP < Brak);
285 strncpy(aBuff, hSpec+1, aLen); aBuff[aLen] = 0;
286 if (inet_pton(AF_INET6,aBuff,&
IP.
v6.sin6_addr) != 1)
return badIPv6;
287 if (mapIt)
IP.
v6.sin6_addr.s6_addr32[2] = map46ID;
288 IP.
v6.sin6_family = AF_INET6;
290 if (useIPV4 && !Map64())
return badIP64;
293 {
if ((Colon = index(hSpec,
':')))
294 {aLen = Colon - hSpec;
295 if (aLen >= INET_ADDRSTRLEN)
return badIPv4;
296 strncpy(aBuff, hSpec, aLen); aBuff[aLen] = 0; iP = aBuff;
298 if (inet_pton(AF_INET ,iP, &
IP.
v6.sin6_addr.s6_addr32[3]) != 1)
300 IP.
v6.sin6_addr.s6_addr32[2] = map46ID;
301 IP.
v6.sin6_family = AF_INET6;
303 if (useIPV4 && !Map64())
return badIPv4;
305 else if (*hSpec == 0)
return badName;
307 else {
struct addrinfo *rP = 0;
308 if ((Colon = index(hSpec,
':')))
309 {aLen = Colon - hSpec;
310 if (aLen > MAXHOSTNAMELEN)
return badName;
311 strncpy(aBuff, hSpec, aLen); aBuff[aLen] = 0; iP = aBuff;
313 n = getaddrinfo(iP, 0, hostHints, &rP);
315 {
if (rP) freeaddrinfo(rP);
316 if (n == EAI_NONAME && dynDNS)
317 return "Dynamic name or service not yet registered";
318 return (n ? gai_strerror(n) :
"host not found");
320 memcpy(&
IP.
Addr, rP->ai_addr, rP->ai_addrlen);
321 protType = (
IP.
v6.sin6_family == AF_INET6 ? PF_INET6 : PF_INET);
328 if (pNum ==
PortInSpec && !Colon)
return "port not specified";
329 if (pNum <= 0 && Colon)
331 pNum = strtol(Colon+1, &eP, 10);
332 if (pNum < 0 || pNum > 0xffff || *eP)
return "invalid port number";
333 }
else if (pNum < 0) pNum = -pNum;
334 IP.
v6.sin6_port = htons(
static_cast<short>(pNum));
344 int pNum,
bool optUDP)
346 struct addrinfo *hP, *rP = 0, *pP, *nP;
348 const char *hnBeg, *hnEnd, *pnBeg, *pnEnd;
349 char hBuff[MAXHOSTNAMELEN+8];
354 if (!hSpec || !isalpha(*hSpec) || maxIP < 2)
355 {
const char *
eMsg =
Set(hSpec, pNum);
356 numIP = (
eMsg ? 0 : 1);
363 return "invalid host specification";
364 hLen = hnEnd - hnBeg;
365 if (hLen > MAXHOSTNAMELEN)
return "host name too long";
366 strncpy(hBuff, hSpec, hLen); hBuff[hLen] = 0;
371 {
if (pNum ==
PortInSpec)
return "port not specified";
372 if (pNum < 0) pNum = -pNum;
375 return "invalid port";
376 if (pNum < 0) pNum = n;
381 hP = (optUDP ? huntHintsUDP : huntHintsTCP);
382 n = getaddrinfo(hBuff, 0, hP, &rP);
384 {
if (rP) freeaddrinfo(rP);
385 return (n ? gai_strerror(n) :
"host not found");
390 n = 0; pP = 0; nP = rP;
391 do {
if (!pP || pP->ai_addrlen != nP->ai_addrlen
392 || memcmp((
const void *)pP->ai_addr, (
const void *)nP->ai_addr,
393 nP->ai_addrlen)) {aVec[n].
Set(nP, pNum); n++;}
394 pP = nP; nP = nP->ai_next;
395 }
while(n < maxIP && nP);
400 if (rP) freeaddrinfo(rP);
411 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
416 if (sockP->sa_family == AF_INET6) {
addrSize =
sizeof(
IP.
v6);
419 else if (sockP->sa_family == AF_INET) {
addrSize =
sizeof(
IP.
v4);
422 else if (sockP->sa_family == AF_UNIX)
423 {unixPipe =
new sockaddr_un;
424 memcpy(unixPipe, sockP,
sizeof(
struct sockaddr_un));
425 unixPipe->sun_path[
sizeof(unixPipe->sun_path)-1] = 0;
427 memset(&
IP, 0,
sizeof(
IP));
428 IP.
Addr.sa_family = AF_UNIX;
432 else return "invalid address family";
450 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
455 if (peer) rc = getpeername(sockFD, &
IP.
Addr, &aSize);
456 else rc = getsockname(sockFD, &
IP.
Addr, &aSize);
476 static const int map46ID = htonl(0x0000ffff);
480 if (mapit && rP->ai_family == AF_INET)
482 IP.
v6.sin6_family = AF_INET6;
483 memcpy(&
IP.
v6.sin6_addr.s6_addr32[3], (rP->ai_addr->sa_data)+2, 4);
484 IP.
v6.sin6_addr.s6_addr32[2] = map46ID;
488 memcpy(&
IP.
Addr, rP->ai_addr, rP->ai_addrlen);
497 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
498 IP.
v6.sin6_port = htons(
static_cast<short>(
Port));
533 hostHints->ai_flags = AI_CANONNAME;
534 hostHints->ai_family = AF_INET;
536 huntHintsTCP->ai_flags = AI_ADDRCONFIG;
537 huntHintsTCP->ai_family = AF_INET;
539 huntHintsUDP->ai_flags = AI_ADDRCONFIG;
540 huntHintsUDP->ai_family = AF_INET;
559 hostHints->ai_flags = AI_V4MAPPED | AI_CANONNAME;
560 hostHints->ai_family = AF_INET6;
562 huntHintsTCP->ai_flags = AI_V4MAPPED | AI_ALL;
563 huntHintsTCP->ai_family = AF_INET6;
565 huntHintsUDP->ai_flags = AI_V4MAPPED | AI_ALL;
566 huntHintsUDP->ai_family = AF_INET6;
const char * XrdSysE2T(int errcode)
static XrdNetCache * dnsCache
static bool isHostName(const char *name)
int Same(const XrdNetAddrInfo *ipAddr, bool plusPort=false)
char * LowCase(char *str)
static const char isTLS
Location using TLS.
XrdNetAddr()
Assignment operator and copy constructor are inherited, no need to define.
bool Register(const char *hName)
static void SetCache(int keeptime)
void SetLocation(XrdNetAddrInfo::LocInfo &loc)
static void SetDynDNS(bool onoff)
static const int PortInSpec
const char * Set(const char *hSpec, int pNum=PortInSpec)
static const char * FQN(const char **etext=0)
static const int NoPortRaw
static const char * GetAddrs(const char *hSpec, XrdNetAddr *aListP[], int &aListN, AddrOpts opts=allIPMap, int pNum=PortInSpec)
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
static bool Parse(const char *hSpec, const char **hName, const char **hNend, const char **hPort, const char **hPend)
static int SetAuto(AddrOpts aOpts=allIPMap)