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