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;
101 if (!fqn) fqn =
"No_DNS_Name!";
109 struct addrinfo *XrdNetAddr::Hints(
int htype,
int stype)
111 static struct addrinfo theHints[3];
116 memset(&theHints[htype], 0,
sizeof(
struct addrinfo));;
117 if (htype) theHints[htype].ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
118 else theHints[htype].ai_flags = AI_V4MAPPED | AI_CANONNAME;
119 theHints[htype].ai_family = AF_UNSPEC;
120 theHints[htype].ai_socktype = stype;
121 return &theHints[htype];
128 bool XrdNetAddr::Map64()
133 if (!IN6_IS_ADDR_V4MAPPED(&
IP.
v6.sin6_addr))
return false;
137 IP.
v4.sin_addr.s_addr =
IP.
v6.sin6_addr.s6_addr32[3];
138 IP.
v4.sin_family = AF_INET;
152 if (
IP.
Addr.sa_family != AF_INET &&
IP.
Addr.sa_family != AF_INET6)
158 if (pNum < 0)
return ntohs(
IP.
v6.sin6_port);
163 if (pNum > 0xffff)
return -1;
164 IP.
v6.sin6_port = htons(
static_cast<short>(pNum));
190 for (i = 0; i < aListNum; i++) {
if (
Same(&aListVec[i]))
break;}
195 if (i >= aListNum)
return false;
210 static const char *badIPv4 =
"invalid IPv4 address";
211 static const char *badIPv6 =
"invalid IPv6 address";
212 static const char *badIP64 =
"IPv6 address not IPv4 representable";
213 static const char *badName =
"invalid host name";
214 static const int map46ID = htonl(0x0000ffff);
216 const char *Colon, *iP;
217 char aBuff[NI_MAXHOST+INET6_ADDRSTRLEN];
224 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
225 memset(&
IP, 0,
sizeof(
IP));
232 {
IP.
v4.sin_family = AF_INET;
233 IP.
v4.sin_addr.s_addr = INADDR_ANY;
237 IP.
v6.sin6_family = AF_INET6;
238 IP.
v6.sin6_addr = in6addr_any;
241 if (pNum < 0) pNum= -pNum;
242 IP.
v6.sin6_port = htons(
static_cast<short>(pNum));
249 {
if (strlen(hSpec) >=
sizeof(unixPipe->sun_path))
return "path too long";
250 unixPipe =
new sockaddr_un;
251 strcpy(unixPipe->sun_path, hSpec);
252 unixPipe->sun_family =
IP.
Addr.sa_family = AF_UNIX;
260 aLen = strlen(hSpec);
261 if (aLen >= (
int)
sizeof(aBuff))
return "host id too long";
267 {
const char *Brak = index(hSpec+1,
']');
268 if (!Brak)
return badIPv6;
270 if (!(*Colon)) Colon = 0;
271 else if (*Colon !=
':')
return badIPv6;
272 aLen = Brak - (hSpec+1);
273 if (aLen >= INET6_ADDRSTRLEN)
return badIPv6;
274 mapIt = (*(hSpec+1) ==
':' && *(hSpec+2) ==
':'
275 && *(hSpec+3) >=
'0' && *(hSpec+3) <=
'9'
276 && (iP = index(hSpec+4,
'.')) && iP < Brak);
277 strncpy(aBuff, hSpec+1, aLen); aBuff[aLen] = 0;
278 if (inet_pton(AF_INET6,aBuff,&
IP.
v6.sin6_addr) != 1)
return badIPv6;
279 if (mapIt)
IP.
v6.sin6_addr.s6_addr32[2] = map46ID;
280 IP.
v6.sin6_family = AF_INET6;
282 if (useIPV4 && !Map64())
return badIP64;
285 {
if ((Colon = index(hSpec,
':')))
286 {aLen = Colon - hSpec;
287 if (aLen >= INET_ADDRSTRLEN)
return badIPv4;
288 strncpy(aBuff, hSpec, aLen); aBuff[aLen] = 0; iP = aBuff;
290 if (inet_pton(AF_INET ,iP, &
IP.
v6.sin6_addr.s6_addr32[3]) != 1)
292 IP.
v6.sin6_addr.s6_addr32[2] = map46ID;
293 IP.
v6.sin6_family = AF_INET6;
295 if (useIPV4 && !Map64())
return badIPv4;
297 else if (*hSpec == 0)
return badName;
299 else {
struct addrinfo *rP = 0;
300 if ((Colon = index(hSpec,
':')))
301 {aLen = Colon - hSpec;
302 if (aLen > MAXHOSTNAMELEN)
return badName;
303 strncpy(aBuff, hSpec, aLen); aBuff[aLen] = 0; iP = aBuff;
305 n = getaddrinfo(iP, 0, hostHints, &rP);
307 {
if (rP) freeaddrinfo(rP);
308 if (n == EAI_NONAME && dynDNS)
309 return "Dynamic name or service not yet registered";
310 return (n ? gai_strerror(n) :
"host not found");
312 memcpy(&
IP.
Addr, rP->ai_addr, rP->ai_addrlen);
313 protType = (
IP.
v6.sin6_family == AF_INET6 ? PF_INET6 : PF_INET);
314 if (rP->ai_canonname)
hostName = strdup(rP->ai_canonname);
320 if (pNum ==
PortInSpec && !Colon)
return "port not specified";
321 if (pNum <= 0 && Colon)
323 pNum = strtol(Colon+1, &eP, 10);
324 if (pNum < 0 || pNum > 0xffff || *eP)
return "invalid port number";
325 }
else if (pNum < 0) pNum = -pNum;
326 IP.
v6.sin6_port = htons(
static_cast<short>(pNum));
336 int pNum,
bool optUDP)
338 struct addrinfo *hP, *rP = 0, *pP, *nP;
340 const char *hnBeg, *hnEnd, *pnBeg, *pnEnd;
341 char hBuff[MAXHOSTNAMELEN+8];
346 if (!hSpec || !isalpha(*hSpec) || maxIP < 2)
347 {
const char *
eMsg =
Set(hSpec, pNum);
348 numIP = (
eMsg ? 0 : 1);
355 return "invalid host specification";
356 hLen = hnEnd - hnBeg;
357 if (hLen > MAXHOSTNAMELEN)
return "host name too long";
358 strncpy(hBuff, hSpec, hLen); hBuff[hLen] = 0;
363 {
if (pNum ==
PortInSpec)
return "port not specified";
364 if (pNum < 0) pNum = -pNum;
367 return "invalid port";
368 if (pNum < 0) pNum = n;
373 hP = (optUDP ? huntHintsUDP : huntHintsTCP);
374 n = getaddrinfo(hBuff, 0, hP, &rP);
376 {
if (rP) freeaddrinfo(rP);
377 return (n ? gai_strerror(n) :
"host not found");
382 n = 0; pP = 0; nP = rP;
383 do {
if (!pP || pP->ai_addrlen != nP->ai_addrlen
384 || memcmp((
const void *)pP->ai_addr, (
const void *)nP->ai_addr,
385 nP->ai_addrlen)) {aVec[n].
Set(nP, pNum); n++;}
386 pP = nP; nP = nP->ai_next;
387 }
while(n < maxIP && nP);
392 if (rP) freeaddrinfo(rP);
403 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
408 if (sockP->sa_family == AF_INET6) {
addrSize =
sizeof(
IP.
v6);
411 else if (sockP->sa_family == AF_INET) {
addrSize =
sizeof(
IP.
v4);
414 else if (sockP->sa_family == AF_UNIX)
415 {unixPipe =
new sockaddr_un;
416 memcpy(unixPipe, sockP,
sizeof(
struct sockaddr_un));
417 unixPipe->sun_path[
sizeof(unixPipe->sun_path)-1] = 0;
419 memset(&
IP, 0,
sizeof(
IP));
420 IP.
Addr.sa_family = AF_UNIX;
424 else return "invalid address family";
442 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
447 if (peer) rc = getpeername(sockFD, &
IP.
Addr, &aSize);
448 else rc = getsockname(sockFD, &
IP.
Addr, &aSize);
468 static const int map46ID = htonl(0x0000ffff);
472 if (mapit && rP->ai_family == AF_INET)
474 IP.
v6.sin6_family = AF_INET6;
475 memcpy(&
IP.
v6.sin6_addr.s6_addr32[3], (rP->ai_addr->sa_data)+2, 4);
476 IP.
v6.sin6_addr.s6_addr32[2] = map46ID;
480 memcpy(&
IP.
Addr, rP->ai_addr, rP->ai_addrlen);
488 hostName = (rP->ai_canonname ? strdup(rP->ai_canonname) : 0);
489 if (sockAddr != &
IP.
Addr) {
delete unixPipe; sockAddr = &
IP.
Addr;}
490 IP.
v6.sin6_port = htons(
static_cast<short>(
Port));
525 hostHints->ai_flags = AI_CANONNAME;
526 hostHints->ai_family = AF_INET;
528 huntHintsTCP->ai_flags = AI_ADDRCONFIG;
529 huntHintsTCP->ai_family = AF_INET;
531 huntHintsUDP->ai_flags = AI_ADDRCONFIG;
532 huntHintsUDP->ai_family = AF_INET;
551 hostHints->ai_flags = AI_V4MAPPED | AI_CANONNAME;
552 hostHints->ai_family = AF_INET6;
554 huntHintsTCP->ai_flags = AI_V4MAPPED | AI_ALL;
555 huntHintsTCP->ai_family = AF_INET6;
557 huntHintsUDP->ai_flags = AI_V4MAPPED | AI_ALL;
558 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)
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)