1 /*
2 	net_udp.c
3 
4 	UDP lan driver.
5 
6 	Copyright (C) 1996-1997  Id Software, Inc.
7 
8 	This program is free software; you can redistribute it and/or
9 	modify it under the terms of the GNU General Public License
10 	as published by the Free Software Foundation; either version 2
11 	of the License, or (at your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 	See the GNU General Public License for more details.
18 
19 	You should have received a copy of the GNU General Public License
20 	along with this program; if not, write to:
21 
22 		Free Software Foundation, Inc.
23 		59 Temple Place - Suite 330
24 		Boston, MA  02111-1307, USA
25 
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 #include <sys/types.h>
32 #ifdef HAVE_STRING_H
33 # include <string.h>
34 #endif
35 #ifdef HAVE_STRINGS_H
36 # include <strings.h>
37 #endif
38 #ifdef HAVE_SYS_SOCKET_H
39 # include <sys/socket.h>
40 #endif
41 #ifdef HAVE_NETINET_IN_H
42 # define model_t sun_model_t
43 # include <netinet/in.h>
44 # undef model_t
45 #endif
46 #ifdef HAVE_ARPA_INET_H
47 # include <arpa/inet.h>
48 #endif
49 #ifdef HAVE_NETDB_H
50 # include <netdb.h>
51 #endif
52 #ifdef HAVE_IFADDRS_H
53 # include <ifaddrs.h>
54 #endif
55 #ifdef HAVE_SYS_PARAM_H
56 # include <sys/param.h>
57 #endif
58 #ifdef HAVE_SYS_IOCTL_H
59 # include <sys/ioctl.h>
60 #endif
61 #ifdef HAVE_WINDOWS_H
62 # include <windows.h>
63 #endif
64 #ifdef HAVE_WINSOCK_H
65 # include <winsock.h>
66 #endif
67 #ifdef HAVE_UNISTD_H
68 # include <unistd.h>
69 #endif
70 #ifdef HAVE_FCNTL_H
71 # include <fcntl.h>
72 #endif
73 #ifdef __sun__
74 # include <sys/filio.h>
75 #endif
76 #ifdef NeXT
77 # include <libc.h>
78 #endif
79 
80 #include <errno.h>
81 #include <stdlib.h>
82 #include <sys/types.h>
83 #ifdef HAVE_SYS_IOCTL_H
84 #include <sys/ioctl.h>
85 #endif
86 #ifdef HAVE_NET_IF_H
87 #include <net/if.h>
88 #endif
89 
90 #include "QF/cvar.h"
91 #include "QF/dstring.h"
92 #include "QF/qargs.h"
93 #include "QF/sys.h"
94 #include "QF/va.h"
95 
96 #include "compat.h"
97 #include "netmain.h"
98 #include "net_udp.h"
99 
100 #ifdef _WIN32
101 # undef EWOULDBLOCK
102 # define EWOULDBLOCK    WSAEWOULDBLOCK
103 # undef ECONNREFUSED
104 # define ECONNREFUSED   WSAECONNREFUSED
105 #endif
106 
107 #ifndef MAXHOSTNAMELEN
108 # define MAXHOSTNAMELEN 512
109 #endif
110 
111 #ifndef HAVE_SOCKLEN_T
112 # ifdef _WIN64
113 	typedef int socklen_t;
114 # else
115 #  ifdef HAVE_SIZE
116 	typedef size_t socklen_t;
117 #  else
118 	typedef unsigned int socklen_t;
119 #  endif
120 # endif
121 #endif
122 
123 #define ADDR_SIZE 4
124 
125 typedef union address {
126 #ifdef HAVE_SS_LEN
127 	struct sockaddr_storage ss;
128 #endif
129 	struct sockaddr         sa;
130 	struct sockaddr_in      s4;
131 } AF_address_t;
132 
133 #undef SA_LEN
134 #undef SS_LEN
135 
136 #ifdef HAVE_SA_LEN
137 #define SA_LEN(sa) (sa)->sa_len
138 #else
139 #define SA_LEN(sa) (sizeof(struct sockaddr_in))
140 #endif
141 
142 #ifdef HAVE_SS_LEN
143 #define SS_LEN(ss) (ss)->ss_len
144 #else
145 #define SS_LEN(ss) (sizeof(struct sockaddr_in))
146 #endif
147 
148 
149 static void
NetadrToSockadr(netadr_t * a,AF_address_t * s)150 NetadrToSockadr (netadr_t *a, AF_address_t *s)
151 {
152 	memset (s, 0, sizeof (*s));
153 	s->s4.sin_family = AF_INET;
154 
155 	memcpy (&s->s4.sin_addr, &a->ip, ADDR_SIZE);
156 	s->s4.sin_port = a->port;
157 }
158 
159 static void
SockadrToNetadr(AF_address_t * s,netadr_t * a)160 SockadrToNetadr (AF_address_t *s, netadr_t *a)
161 {
162 	memcpy (&a->ip, &s->s4.sin_addr, ADDR_SIZE);
163 	a->port = s->s4.sin_port;
164 	a->family = s->s4.sin_family;
165 }
166 
167 static int  net_acceptsocket = -1;		// socket for fielding new
168 										// connections
169 static int  net_controlsocket;
170 static int  net_broadcastsocket = 0;
171 static netadr_t broadcastaddr;
172 
173 static uint32_t myAddr;
174 
175 static int num_ifaces;
176 uint32_t *ifaces;
177 uint32_t *default_iface;
178 uint32_t *last_iface;
179 
180 static int
get_iface_list(int sock)181 get_iface_list (int sock)
182 {
183 #ifdef HAVE_GETIFADDRS
184 	struct ifaddrs *ifa_head;
185 	struct ifaddrs *ifa;
186 	int         index;
187 
188 	if (getifaddrs (&ifa_head) < 0)
189 		goto no_ifaddrs;
190 	for (ifa = ifa_head; ifa; ifa = ifa->ifa_next) {
191 		if (!ifa->ifa_flags & IFF_UP)
192 			continue;
193 		if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
194 			continue;
195 		index = if_nametoindex (ifa->ifa_name);
196 		if (index > num_ifaces)
197 			num_ifaces = index;
198 	}
199 	ifaces = malloc (num_ifaces * sizeof (uint32_t));
200 	Sys_MaskPrintf (SYS_NET, "%d interfaces\n", num_ifaces);
201 	for (ifa = ifa_head; ifa; ifa = ifa->ifa_next) {
202 		struct sockaddr_in *sa;
203 
204 		if (!ifa->ifa_flags & IFF_UP)
205 			continue;
206 		if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
207 			continue;
208 		index = if_nametoindex (ifa->ifa_name) - 1;
209 		sa = (struct sockaddr_in *) ifa->ifa_addr;
210 		memcpy (&ifaces[index], &sa->sin_addr, sizeof (uint32_t));
211 		Sys_MaskPrintf (SYS_NET, "    %-10s %s\n", ifa->ifa_name,
212 						inet_ntoa (sa->sin_addr));
213 		if (!default_iface && ifaces[index] != htonl (0x7f000001))
214 			default_iface = &ifaces[index];
215 	}
216 	freeifaddrs (ifa_head);
217 	return 0;
218 no_ifaddrs:
219 #endif
220 	ifaces = &myAddr;
221 	default_iface = &ifaces[0];
222 	num_ifaces = 1;
223 	return 0;
224 }
225 
226 int
UDP_Init(void)227 UDP_Init (void)
228 {
229 	struct hostent *local = 0;
230 	char        buff[MAXHOSTNAMELEN];
231 	netadr_t    addr;
232 	char       *colon;
233 #ifdef _WIN32
234 	WSADATA winsockdata;
235 	int	r;
236 
237 	r = WSAStartup (MAKEWORD (1, 1), &winsockdata);
238 	if (r)
239 		Sys_Error ("Winsock initialization failed.");
240 #endif
241 	if (COM_CheckParm ("-noudp"))
242 		return -1;
243 
244 	// determine my name & address
245 #ifdef HAVE_GETHOSTNAME	//FIXME
246 	gethostname (buff, MAXHOSTNAMELEN);
247 	local = gethostbyname (buff);
248 #endif
249 	if (local)
250 		myAddr = *(uint32_t *) local->h_addr_list[0];
251 	else
252 		myAddr = 0;
253 
254 	// if the quake hostname isn't set, set it to the machine name
255 	if (strcmp (hostname->string, "UNNAMED") == 0) {
256 		buff[15] = 0;
257 		Cvar_Set (hostname, buff);
258 	}
259 
260 	if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
261 		Sys_Error ("UDP_Init: Unable to open control socket");
262 
263 	get_iface_list (net_controlsocket);
264 
265 	{
266 		AF_address_t t;
267 		t.s4.sin_family = AF_INET;
268 		t.s4.sin_addr.s_addr = INADDR_BROADCAST;
269 		t.s4.sin_port = htons (net_hostport);
270 		SockadrToNetadr (&t, &broadcastaddr);
271 	}
272 
273 	UDP_GetSocketAddr (net_controlsocket, &addr);
274 	strcpy (my_tcpip_address, UDP_AddrToString (&addr));
275 	colon = strrchr (my_tcpip_address, ':');
276 	if (colon)
277 		*colon = 0;
278 
279 	Sys_Printf ("UDP (IPv4) Initialized\n");
280 	tcpipAvailable = true;
281 
282 	return net_controlsocket;
283 }
284 
285 void
UDP_Shutdown(void)286 UDP_Shutdown (void)
287 {
288 	UDP_Listen (false);
289 
290 	UDP_CloseSocket (net_controlsocket);
291 }
292 
293 void
UDP_Listen(qboolean state)294 UDP_Listen (qboolean state)
295 {
296 	// enable listening
297 	if (state) {
298 		if (net_acceptsocket != -1)
299 			return;
300 		if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
301 			Sys_Error ("UDP_Listen: Unable to open accept socket");
302 		return;
303 	}
304 	// disable listening
305 	if (net_acceptsocket == -1)
306 		return;
307 	UDP_CloseSocket (net_acceptsocket);
308 	net_acceptsocket = -1;
309 }
310 
311 int
UDP_OpenSocket(int port)312 UDP_OpenSocket (int port)
313 {
314 	int         newsocket;
315 	struct sockaddr_in address;
316 #ifdef _WIN32
317 #define ioctl ioctlsocket
318 	unsigned long flags;
319 #else
320 	int         flags;
321 #endif
322 #ifdef HAVE_IN_PKTINFO
323 	int         ip_pktinfo = 1;
324 #endif
325 
326 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
327 		return -1;
328 
329 #if defined (HAVE_IOCTL) || defined (_WIN32)
330 	flags = 1;
331 	if (ioctl (newsocket, FIONBIO, &flags) == -1)
332 		goto ErrorReturn;
333 #else
334 	flags = fcntl (newsocket, F_GETFL, 0);
335 	if (fcntl (newsocket, F_SETFL, flags | O_NONBLOCK) == -1)
336 		goto ErrorReturn;
337 #endif
338 #ifdef HAVE_IN_PKTINFO
339 	if (setsockopt (newsocket, SOL_IP, IP_PKTINFO, &ip_pktinfo,
340 					sizeof (ip_pktinfo)) == -1) {
341 		close (newsocket);
342 		return -1;
343 	}
344 #endif
345 
346 	address.sin_family = AF_INET;
347 	address.sin_addr.s_addr = INADDR_ANY;
348 	address.sin_port = htons (port);
349 	if (bind (newsocket, (void *) &address, sizeof (address)) == -1)
350 		goto ErrorReturn;
351 
352 	return newsocket;
353 
354   ErrorReturn:
355 	UDP_CloseSocket (newsocket);
356 	return -1;
357 }
358 
359 int
UDP_CloseSocket(int socket)360 UDP_CloseSocket (int socket)
361 {
362 	if (socket == net_broadcastsocket)
363 		net_broadcastsocket = 0;
364 #ifdef _WIN32
365 	closesocket (socket);
366 	WSACleanup ();
367 	return 0;
368 #else
369 	return close (socket);
370 #endif
371 }
372 
373 /*
374   PartialIPAddress
375 
376   this lets you type only as much of the net address as required, using
377   the local network components to fill in the rest
378 */
379 static int
PartialIPAddress(const char * in,netadr_t * hostaddr)380 PartialIPAddress (const char *in, netadr_t *hostaddr)
381 {
382 	char       *buff;
383 	char       *b;
384 	int         addr, mask, num, port, run;
385 
386 	buff = nva (".%s", in);
387 	b = buff;
388 	if (buff[1] == '.')
389 		b++;
390 
391 	addr = 0;
392 	mask = -1;
393 	while (*b == '.') {
394 		b++;
395 		num = 0;
396 		run = 0;
397 		while (!(*b < '0' || *b > '9')) {
398 			num = num * 10 + *b++ - '0';
399 			if (++run > 3)
400 				goto error;
401 		}
402 		if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
403 			goto error;
404 		if (num < 0 || num > 255)
405 			goto error;
406 		mask <<= 8;
407 		addr = (addr << 8) + num;
408 	}
409 
410 	if (*b++ == ':')
411 		port = atoi (b);
412 	else
413 		port = net_hostport;
414 
415 	hostaddr->family = AF_INET;
416 	hostaddr->port = htons ((short) port);
417 	{
418 		int32_t     t = myAddr & htonl (mask);
419 		t |= htonl (addr);
420 		memcpy (hostaddr->ip, &t, ADDR_SIZE);
421 	}
422 
423 	free (buff);
424 	return 0;
425 error:
426 	free (buff);
427 	return -1;
428 }
429 
430 int
UDP_Connect(int socket,netadr_t * addr)431 UDP_Connect (int socket, netadr_t *addr)
432 {
433 	return 0;
434 }
435 
436 int
UDP_CheckNewConnections(void)437 UDP_CheckNewConnections (void)
438 {
439 #if defined (HAVE_IOCTL) || defined (_WIN32)
440 # ifdef _WIN64
441 	u_long      available;
442 # else
443 	int         available;
444 # endif
445 	AF_address_t from;
446 	socklen_t   fromlen = sizeof (from);
447 	char        buff[1];
448 #endif
449 
450 	if (net_acceptsocket == -1)
451 		return -1;
452 #if defined (HAVE_IOCTL) || defined (_WIN32)
453 	if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
454 		Sys_Error ("UDP: ioctlsocket (FIONREAD) failed");
455 	if (available)
456 		return net_acceptsocket;
457 	// quietly absorb empty packets
458 	// there is no way to tell between an empty packet and no packets, but
459 	// as non-blocking io is used, this is not a problem.
460 	// we don't care about the interface on which the packet arrived
461 	recvfrom (net_acceptsocket, buff, 0, 0, &from.sa, &fromlen);
462 	return -1;
463 #else
464 	return net_acceptsocket;
465 #endif
466 }
467 
468 int
UDP_Read(int socket,byte * buf,int len,netadr_t * from)469 UDP_Read (int socket, byte *buf, int len, netadr_t *from)
470 {
471 	int         ret;
472 	AF_address_t addr;
473 #ifdef HAVE_IN_PKTINFO
474 	char        ancillary[CMSG_SPACE (sizeof (struct in_pktinfo))];
475 	struct msghdr msghdr = {
476 		&addr,
477 		sizeof (addr),
478 		0, 0,
479 		ancillary,
480 		sizeof (ancillary),
481 		0
482 	};
483 	struct iovec iovec = {buf, len};
484 	struct cmsghdr *cmsg;
485 	struct in_pktinfo *info = 0;
486 
487 	memset (&addr, 0, sizeof (addr));
488 	msghdr.msg_iov = &iovec;
489 	msghdr.msg_iovlen = 1;
490 	ret = recvmsg (socket, &msghdr, 0);
491 	if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
492 		return 0;
493 	for (cmsg = CMSG_FIRSTHDR (&msghdr); cmsg;
494 		 cmsg = CMSG_NXTHDR (&msghdr, cmsg)) {
495 		Sys_MaskPrintf (SYS_NET, "%d\n", cmsg->cmsg_type);
496 		if (cmsg->cmsg_type == IP_PKTINFO) {
497 			info = (struct in_pktinfo *) CMSG_DATA (cmsg);
498 			break;
499 		}
500 	}
501 	last_iface = 0;
502 	if (info) {
503 		/* Our iterface list is 0 based, but the pktinfo interface index is 1
504 		 * based.
505 		 */
506 		last_iface = &ifaces[info->ipi_ifindex - 1];
507 	}
508 	SockadrToNetadr (&addr, from);
509 	Sys_MaskPrintf (SYS_NET, "got %d bytes from %s on iface %d (%s)\n", ret,
510 					UDP_AddrToString (from), info ? info->ipi_ifindex - 1 : -1,
511 					last_iface ? inet_ntoa (info->ipi_addr) : "?");
512 #else
513 	socklen_t   addrlen = sizeof (AF_address_t);
514 
515 	memset (&addr, 0, sizeof (addr));
516 	ret = recvfrom (socket, (void *) buf, len, 0, (struct sockaddr *) &addr,
517 					&addrlen);
518 	if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
519 		return 0;
520 	SockadrToNetadr (&addr, from);
521 	Sys_MaskPrintf (SYS_NET, "got %d bytes from %s\n", ret,
522 					UDP_AddrToString (from));
523 	last_iface = default_iface;
524 #endif
525 	return ret;
526 }
527 
528 static int
UDP_MakeSocketBroadcastCapable(int socket)529 UDP_MakeSocketBroadcastCapable (int socket)
530 {
531 	int         i = 1;
532 
533 	// make this socket broadcast capable
534 	if (setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) &i,
535 					sizeof (i)) < 0)
536 		return -1;
537 	net_broadcastsocket = socket;
538 
539 	return 0;
540 }
541 
542 int
UDP_Broadcast(int socket,byte * buf,int len)543 UDP_Broadcast (int socket, byte *buf, int len)
544 {
545 	int         ret;
546 
547 	if (socket != net_broadcastsocket) {
548 		if (net_broadcastsocket != 0)
549 			Sys_Error ("Attempted to use multiple broadcasts sockets");
550 		ret = UDP_MakeSocketBroadcastCapable (socket);
551 		if (ret == -1) {
552 			Sys_Printf ("Unable to make socket broadcast capable\n");
553 			return ret;
554 		}
555 	}
556 
557 	return UDP_Write (socket, buf, len, &broadcastaddr);
558 }
559 
560 int
UDP_Write(int socket,byte * buf,int len,netadr_t * to)561 UDP_Write (int socket, byte *buf, int len, netadr_t *to)
562 {
563 	int         ret;
564 	AF_address_t addr;
565 
566 	NetadrToSockadr (to, &addr);
567 	ret = sendto (socket, (const void *) buf, len, 0, &addr.sa,
568 				  SA_LEN (&addr.sa));
569 	if (ret == -1 && errno == EWOULDBLOCK)
570 		return 0;
571 	Sys_MaskPrintf (SYS_NET, "sent %d bytes to %s\n", ret,
572 					UDP_AddrToString (to));
573 	return ret;
574 }
575 
576 const char *
UDP_AddrToString(netadr_t * addr)577 UDP_AddrToString (netadr_t *addr)
578 {
579 	static dstring_t *buffer;
580 
581 	if (!buffer)
582 		buffer = dstring_new ();
583 
584 	dsprintf (buffer, "%d.%d.%d.%d:%d", addr->ip[0],
585 			  addr->ip[1], addr->ip[2], addr->ip[3],
586 			  ntohs (addr->port));
587 	return buffer->str;
588 }
589 
590 int
UDP_GetSocketAddr(int socket,netadr_t * na)591 UDP_GetSocketAddr (int socket, netadr_t *na)
592 {
593 	unsigned int a;
594 	socklen_t    addrlen = sizeof (AF_address_t);
595 	AF_address_t addr;
596 
597 	memset (&addr, 0, sizeof (AF_address_t));
598 
599 	getsockname (socket, &addr.sa, &addrlen);
600 	SockadrToNetadr (&addr, na);
601 	memcpy (&a, na->ip, ADDR_SIZE);
602 	if (a == 0 || a == inet_addr ("127.0.0.1")) {
603 		if (default_iface)
604 			memcpy (na->ip, default_iface, ADDR_SIZE);
605 		if (last_iface)
606 			memcpy (na->ip, last_iface, ADDR_SIZE);
607 	}
608 
609 	return 0;
610 }
611 
612 int
UDP_GetNameFromAddr(netadr_t * addr,char * name)613 UDP_GetNameFromAddr (netadr_t *addr, char *name)
614 {
615 	struct hostent *hostentry;
616 
617 	//FIXME the cast is an evil hack for android
618 	hostentry = gethostbyaddr ((char *) &addr->ip, ADDR_SIZE, AF_INET);
619 
620 	if (hostentry) {
621 		strncpy (name, (char *) hostentry->h_name, NET_NAMELEN - 1);
622 		return 0;
623 	}
624 
625 	strcpy (name, UDP_AddrToString (addr));
626 	return 0;
627 }
628 
629 int
UDP_GetAddrFromName(const char * name,netadr_t * addr)630 UDP_GetAddrFromName (const char *name, netadr_t *addr)
631 {
632 	struct hostent *hostentry;
633 
634 	if (name[0] >= '0' && name[0] <= '9')
635 		return PartialIPAddress (name, addr);
636 
637 	hostentry = gethostbyname (name);
638 	if (!hostentry)
639 		return -1;
640 
641 	addr->family = AF_INET;
642 	addr->port = htons (net_hostport);
643 	memcpy (addr->ip, hostentry->h_addr_list[0], ADDR_SIZE);
644 
645 	return 0;
646 }
647 
648 int
UDP_AddrCompare(netadr_t * addr1,netadr_t * addr2)649 UDP_AddrCompare (netadr_t *addr1, netadr_t *addr2)
650 {
651 	if (addr1->family != addr2->family)
652 		return -2;
653 
654 	if (memcmp (addr1->ip, addr2->ip, ADDR_SIZE))
655 		return -1;
656 
657 	if (addr1->port != addr2->port)
658 		return 1;
659 
660 	return 0;
661 }
662 
663 int
UDP_GetSocketPort(netadr_t * addr)664 UDP_GetSocketPort (netadr_t *addr)
665 {
666 	return ntohs (addr->port);
667 }
668 
669 int
UDP_SetSocketPort(netadr_t * addr,int port)670 UDP_SetSocketPort (netadr_t *addr, int port)
671 {
672 	addr->port = htons (port);
673 	return 0;
674 }
675