pkgsrc/games/quake6/patches/patch-aj
2011-12-05 22:46:12 +00:00

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;
}