186 lines
4.6 KiB
Text
186 lines
4.6 KiB
Text
$NetBSD: patch-aj,v 1.2 2011/12/05 22:46:12 joerg Exp $
|
|
|
|
--- uquake/net_udp.c.orig 2000-01-10 16:59:39.000000000 +0000
|
|
+++ uquake/net_udp.c
|
|
@@ -32,12 +32,17 @@ Foundation, Inc., 59 Temple Place - Suit
|
|
#include <sys/param.h>
|
|
#include <sys/ioctl.h>
|
|
#include <errno.h>
|
|
+#include <net/if.h>
|
|
|
|
#ifdef __sun__
|
|
#include <sys/filio.h>
|
|
#undef model_t
|
|
#endif
|
|
|
|
+#ifndef INADDR_LOOPBACK
|
|
+#define INADDR_LOOPBACK (u_int32_t)0x7f000001
|
|
+#endif
|
|
+
|
|
#if defined(sgi) && defined(sa_family)
|
|
/* Get rid of problematic SGI #def */
|
|
#undef sa_family
|
|
@@ -62,6 +67,91 @@ static unsigned long myAddr;
|
|
#include "net_udp.h"
|
|
|
|
//=============================================================================
|
|
+/* get any of my non-loopback addr. */
|
|
+static int
|
|
+grab_myaddr(family, sa)
|
|
+ int family;
|
|
+ struct sockaddr *sa;
|
|
+{
|
|
+ int s;
|
|
+ unsigned int maxif;
|
|
+ struct ifreq *iflist;
|
|
+ struct ifconf ifconf;
|
|
+ struct ifreq *ifr, *ifr_end;
|
|
+ struct myaddrs *p;
|
|
+ struct sockaddr_in *sin;
|
|
+ struct sockaddr_in6 *sin6;
|
|
+
|
|
+#if 0
|
|
+ maxif = if_maxindex() + 1;
|
|
+#else
|
|
+ maxif = 10;
|
|
+#endif
|
|
+ iflist = (struct ifreq *)malloc(maxif * BUFSIZ); /* XXX */
|
|
+ if (!iflist) {
|
|
+ Sys_Error("grab_myaddr: not enough core\n");
|
|
+ /*NOTREACHED*/
|
|
+ }
|
|
+
|
|
+ if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
+ Sys_Error("socket(SOCK_DGRAM)\n");
|
|
+ /*NOTREACHED*/
|
|
+ }
|
|
+ memset(&ifconf, 0, sizeof(ifconf));
|
|
+ ifconf.ifc_req = iflist;
|
|
+ ifconf.ifc_len = maxif * BUFSIZ; /* XXX */
|
|
+ if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
|
|
+ Sys_Error("ioctl(SIOCGIFCONF)\n");
|
|
+ /*NOTREACHED*/
|
|
+ }
|
|
+ close(s);
|
|
+
|
|
+ /* Look for this interface in the list */
|
|
+ ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
|
|
+ for (ifr = ifconf.ifc_req;
|
|
+ ifr < ifr_end;
|
|
+ ifr = (struct ifreq *) ((char *) &ifr->ifr_addr
|
|
+ + ifr->ifr_addr.sa_len)) {
|
|
+ switch (ifr->ifr_addr.sa_family) {
|
|
+ case AF_INET:
|
|
+ sin = (struct sockaddr_in *)&ifr->ifr_addr;
|
|
+ if (sin->sin_addr.s_addr == htonl(0))
|
|
+ continue;
|
|
+ if (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
|
|
+ continue;
|
|
+ break;
|
|
+ case AF_INET6:
|
|
+ sin6 = (struct sockaddr_in6 *)&ifr->ifr_addr;
|
|
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
|
|
+ continue;
|
|
+ if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
|
|
+ continue;
|
|
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
|
|
+ continue;
|
|
+ if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
|
|
+ continue;
|
|
+ break;
|
|
+ }
|
|
+ if (ifr->ifr_addr.sa_family != family)
|
|
+ continue;
|
|
+
|
|
+ memcpy(sa, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
|
|
+
|
|
+ {
|
|
+ char hbuf[NI_MAXHOST];
|
|
+ if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
|
|
+ NI_NUMERICHOST) == 0)
|
|
+ printf("got %s as local address\n", hbuf);
|
|
+ else {
|
|
+ printf("non-printable local address, family %d\n",
|
|
+ family);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ free(iflist);
|
|
+}
|
|
|
|
int UDP_Init (void)
|
|
{
|
|
@@ -74,9 +164,18 @@ int UDP_Init (void)
|
|
return -1;
|
|
|
|
// determine my name & address
|
|
+ memset(&myAddr, 0, sizeof(myAddr));
|
|
+#if 0
|
|
gethostname(buff, MAXHOSTNAMELEN);
|
|
local = gethostbyname(buff);
|
|
myAddr = *(int *)local->h_addr_list[0];
|
|
+#else
|
|
+ {
|
|
+ struct sockaddr_in sin;
|
|
+ if (grab_myaddr(AF_INET, (struct sockaddr *)&sin) == 0)
|
|
+ memcpy(&myAddr, &sin.sin_addr, sizeof(myAddr));
|
|
+ }
|
|
+#endif
|
|
|
|
// if the quake hostname isn't set, set it to the machine name
|
|
if (Q_strcmp(hostname.string, "UNNAMED") == 0)
|
|
@@ -137,25 +236,45 @@ void UDP_Listen (qboolean state)
|
|
|
|
int UDP_OpenSocket (int port)
|
|
{
|
|
+ struct addrinfo hints, *res = NULL;
|
|
+ int error;
|
|
+ char pbuf[NI_MAXSERV];
|
|
int newsocket;
|
|
- struct sockaddr_in address;
|
|
qboolean _true = true;
|
|
+ const int wrong = 0;
|
|
|
|
- if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
|
+ snprintf(pbuf, sizeof(pbuf), "%d", port);
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_family = PF_INET6;
|
|
+ hints.ai_socktype = SOCK_DGRAM;
|
|
+ hints.ai_flags = AI_PASSIVE;
|
|
+ error = getaddrinfo(NULL, pbuf, &hints, &res);
|
|
+ if (error)
|
|
return -1;
|
|
|
|
- if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
|
|
+ if ((newsocket = socket (res->ai_family, res->ai_socktype,
|
|
+ res->ai_protocol)) < 0)
|
|
+ return -1;
|
|
+
|
|
+ if (ioctl (newsocket, FIONBIO, (char *)&_true) < 0)
|
|
goto ErrorReturn;
|
|
|
|
- address.sin_family = AF_INET;
|
|
- address.sin_addr.s_addr = INADDR_ANY;
|
|
- address.sin_port = htons(port);
|
|
- if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
|
|
+#ifdef IPV6_BINDV6ONLY
|
|
+ if (setsockopt(newsocket, IPPROTO_IPV6, IPV6_BINDV6ONLY, &wrong,
|
|
+ sizeof(wrong)) < 0) {
|
|
+ /* I don't care */
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ if (bind (newsocket, res->ai_addr, res->ai_addrlen) < 0)
|
|
goto ErrorReturn;
|
|
|
|
+ freeaddrinfo(res);
|
|
return newsocket;
|
|
|
|
ErrorReturn:
|
|
+ if (res)
|
|
+ freeaddrinfo(res);
|
|
close (newsocket);
|
|
return -1;
|
|
}
|