From 003f4be021810c88dc19d1fc6ba4c3539940c6ca Mon Sep 17 00:00:00 2001 From: Pontus Lidman Date: Tue, 8 Feb 2000 21:33:33 +0000 Subject: [PATCH] Now correctly handles IPv4 addresses returned by getaddrinfo(); also parses RFC 2732 IPv6 address/port numbers in the connect command etc. --- qw_common/net_udp6.c | 101 +++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 22 deletions(-) diff --git a/qw_common/net_udp6.c b/qw_common/net_udp6.c index d302c53..7b2c5cc 100644 --- a/qw_common/net_udp6.c +++ b/qw_common/net_udp6.c @@ -29,9 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* Sun's model_t in sys/model.h conflicts w/ Quake's model_t */ #define model_t quakeforgemodel_t -#ifdef HAVE_UNISTD_H #include -#endif #include #ifdef HAVE_SYS_IOCTL_H @@ -124,20 +122,24 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b) char *NET_AdrToString (netadr_t a) { static char s[64]; - unsigned short *addr16=(unsigned short *) &(a.ip); - - snprintf(s, sizeof(s), "%x:%x:%x:%x:%x:%x:%x:%x.%x", ntohs(addr16[0]), ntohs(addr16[1]), ntohs(addr16[2]), ntohs(addr16[3]),ntohs(addr16[4]), ntohs(addr16[5]), ntohs(addr16[6]), ntohs(addr16[7]), ntohs(a.port)); + char *base; + base=NET_BaseAdrToString(a); + sprintf(s,"[%s]:%d",base,ntohs(a.port)); return s; } char *NET_BaseAdrToString (netadr_t a) { static char s[64]; - unsigned short *addr16=(unsigned short *) &(a.ip); - - snprintf(s, sizeof(s), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(addr16[0]), ntohs(addr16[1]), ntohs(addr16[2]), ntohs(addr16[3]),ntohs(addr16[4]), ntohs(addr16[5]), ntohs(addr16[6]), ntohs(addr16[7])); + struct sockaddr_in6 sa; + int err; + NetadrToSockadr(&a,&sa); + + if ((err=getnameinfo((struct sockaddr *) &sa,sizeof(sa),s,sizeof(s),NULL,0,NI_NUMERICHOST))) { + strcpy(s,""); + } return s; } @@ -159,29 +161,66 @@ qboolean NET_StringToAdr (char *s, netadr_t *a) char *space; char *ports=NULL; char copy[128]; + char *addrs; int err; + struct sockaddr_storage ss; + struct sockaddr_in6 *ss6; + struct sockaddr_in *ss4; - bzero(&hints,sizeof(hints)); + memset(&hints,0,sizeof(hints)); hints.ai_socktype=SOCK_DGRAM; - hints.ai_family=PF_INET6; + hints.ai_family=PF_UNSPEC; strcpy(copy,s); - for (space=copy; *space; space++) { - if (*space==' ') + addrs=space=copy; + if (*addrs=='[') { + addrs++; + for (; *space && *space!=']'; space++); + if (!*space) { + Con_Printf ("NET_StringToAdr: invalid IPv6 address %s\n",s); + return 0; + } + *space++='\0'; + } + + for (; *space; space++) { + if (*space==':') { - *space=0; + *space='\0'; ports=space+1; } } - if ((err=getaddrinfo(copy,ports,&hints,&resultp))) + // Con_Printf ("NET_StringToAdr: addrs %s ports %s\n",addrs, ports); + + if ((err=getaddrinfo(addrs,ports,&hints,&resultp))) { // Error - Sys_Error ("NET_StringToAdr: string %s: %s",s, gai_strerror(err)); + Con_Printf ("NET_StringToAdr: string %s:\n%s\n",s, gai_strerror(err)); return 0; } - - SockadrToNetadr ((struct sockaddr_in6 *) resultp->ai_addr, a); + + switch (resultp->ai_family) { + case AF_INET: + // convert to ipv6 addr + memset(&ss,0,sizeof(ss)); + ss6=(struct sockaddr_in6 *) &ss; + ss4=(struct sockaddr_in *) resultp->ai_addr; + ss6->sin6_family=AF_INET6; + ss6->sin6_addr.in6_u.u6_addr32[0]=0; + ss6->sin6_addr.in6_u.u6_addr32[1]=0; + ss6->sin6_addr.in6_u.u6_addr32[2]=htonl(0xffff); + ss6->sin6_addr.in6_u.u6_addr32[3]=ss4->sin_addr.s_addr; + ss6->sin6_port=ss4->sin_port; + break; + case AF_INET6: + memcpy(&ss,resultp->ai_addr,sizeof(struct sockaddr_in6)); + break; + default: + Con_Printf ("NET_StringToAdr: string %s:\nprotocol family %d not supported\n",s, resultp->ai_family); + return 0; + } + SockadrToNetadr ((struct sockaddr_in6 *) &ss, a); return true; } @@ -299,8 +338,10 @@ int UDP_OpenSocket (int port) int err; int newsocket; struct sockaddr_in6 address; + struct sockaddr_in *ss4; struct addrinfo hints; struct addrinfo *resultp; + char addrbuf[128]; #ifdef _WIN32 #define ioctl ioctlsocket unsigned long _true = true; @@ -313,23 +354,39 @@ int UDP_OpenSocket (int port) Sys_Error ("UDP_OpenSocket: socket: %s", strerror(errno)); if (ioctl (newsocket, FIONBIO, &_true) == -1) Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(errno)); + memset(&address,0,sizeof(address)); address.sin6_family = AF_INET6; //ZOID -- check for interface binding option if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) { - bzero(&hints,sizeof(hints)); + memset(&hints,0,sizeof(hints)); hints.ai_socktype=SOCK_DGRAM; - hints.ai_family=PF_INET6; + hints.ai_family=PF_UNSPEC; if ((err=getaddrinfo(com_argv[i+1],NULL,&hints,&resultp))) { Sys_Error ("UDP_OpenSocket: addr %s: %s",com_argv[i+1], gai_strerror(err)); } - memcpy((void *) &address,(void *) resultp->ai_addr,sizeof(address)); + switch(resultp->ai_family) { + case AF_INET: + ss4=(struct sockaddr_in *) resultp->ai_addr; + address.sin6_family=AF_INET6; + address.sin6_addr.in6_u.u6_addr32[0]=0; + address.sin6_addr.in6_u.u6_addr32[1]=0; + address.sin6_addr.in6_u.u6_addr32[2]=htonl(0xffff); + address.sin6_addr.in6_u.u6_addr32[3]=ss4->sin_addr.s_addr; + break; + case AF_INET6: + memcpy((void *) &address,(void *) resultp->ai_addr,sizeof(address)); + break; + default: + Sys_Error ("UDP_OpenSocket: address family %d not supported",com_argv[i+1], resultp->ai_family); + } + // address.sin_addr.s_addr = inet_addr(com_argv[i+1]); - // Con_Printf("Binding to IP Interface Address of %s\n", - // inet_ntop(address.sin6_addr)); + Con_Printf("Binding to IP Interface Address of %s\n", + inet_ntop(AF_INET6,&address.sin6_addr,addrbuf,sizeof(addrbuf))); } else address.sin6_addr = in6addr_any;