1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // net_udp.c
21 
22 #include "quakedef.h"
23 
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <netdb.h>
28 #include <arpa/inet.h> /* for inet_addr() */
29 #include <sys/param.h>
30 #include <sys/ioctl.h>
31 #include <errno.h>
32 
33 #ifdef __sun__
34 #include <sys/filio.h>
35 #endif
36 
37 #if defined(NeXT) || defined(__APPLE__) || defined(MACOSX)
38 #include <libc.h>
39 #endif
40 
41 extern int gethostname (char *, int);
42 extern int close (int);
43 
44 extern cvar_t hostname;
45 
46 static int net_acceptsocket = -1;		// socket for fielding new connections
47 static int net_controlsocket;
48 static int net_broadcastsocket = 0;
49 static struct qsockaddr broadcastaddr;
50 
51 static unsigned long myAddr;
52 
53 #include "net_udp.h"
54 
55 //=============================================================================
56 
UDP_Init(void)57 int UDP_Init (void)
58 {
59 	struct hostent *local;
60 	char	buff[MAXHOSTNAMELEN];
61 	struct qsockaddr addr;
62 	char *colon;
63 
64 	if (COM_CheckParm ("-noudp"))
65 		return -1;
66 
67 	// determine my name & address
68 #if !defined(_WIN32)
69 
70 	if (gethostname(buff, MAXHOSTNAMELEN) != 0)
71         {
72             Con_Printf ("UDP init failed. Disabling UDP...\n");
73             return (-1);
74         }
75         local = gethostbyname(buff);
76     	if (local == NULL)
77         {
78             Con_Printf ("UDP init failed. Disabling UDP...\n");
79             return (-1);
80         }
81 
82 #else
83 
84 	gethostname(buff, MAXHOSTNAMELEN);
85 	local = gethostbyname(buff);
86 
87 #endif /* !_WIN32 */
88 
89 	myAddr = *(int *)local->h_addr_list[0];
90 
91 	// if the quake hostname isn't set, set it to the machine name
92 	if (Q_strcmp(hostname.string, "UNNAMED") == 0)
93 	{
94 		buff[15] = 0;
95 		Cvar_Set ("hostname", buff);
96 	}
97 
98 	if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
99 		Sys_Error("UDP_Init: Unable to open control socket\n");
100 
101 	((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
102 	((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
103 	((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
104 
105 #if !defined (_WIN32)
106 
107 	if (UDP_GetSocketAddr (net_controlsocket, &addr) != 0)
108         {
109             Con_Printf ("UDP init failed. Disabling UDP...\n");
110             return (-1);
111         }
112 
113 #else
114 
115         UDP_GetSocketAddr (net_controlsocket, &addr);
116 
117 #endif /* !_WIN32 */
118 
119 	Q_strcpy(my_tcpip_address,  UDP_AddrToString (&addr));
120 	colon = Q_strrchr (my_tcpip_address, ':');
121 	if (colon)
122 		*colon = 0;
123 
124 	Con_Printf("UDP Initialized\n");
125 	tcpipAvailable = true;
126 
127 	return net_controlsocket;
128 }
129 
130 //=============================================================================
131 
UDP_Shutdown(void)132 void UDP_Shutdown (void)
133 {
134 	UDP_Listen (false);
135 	UDP_CloseSocket (net_controlsocket);
136 }
137 
138 //=============================================================================
139 
UDP_Listen(qboolean state)140 void UDP_Listen (qboolean state)
141 {
142 	// enable listening
143 	if (state)
144 	{
145 		if (net_acceptsocket != -1)
146 			return;
147 		if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
148 			Sys_Error ("UDP_Listen: Unable to open accept socket\n");
149 		return;
150 	}
151 
152 	// disable listening
153 	if (net_acceptsocket == -1)
154 		return;
155 	UDP_CloseSocket (net_acceptsocket);
156 	net_acceptsocket = -1;
157 }
158 
159 //=============================================================================
160 
UDP_OpenSocket(int port)161 int UDP_OpenSocket (int port)
162 {
163 	int newsocket;
164 	struct sockaddr_in address;
165 	qboolean _true = true;
166 
167 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
168 		return -1;
169 
170 	if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
171 		goto ErrorReturn;
172 
173 	address.sin_family = AF_INET;
174 	address.sin_addr.s_addr = INADDR_ANY;
175 	address.sin_port = htons(port);
176 	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
177 		goto ErrorReturn;
178 
179 	return newsocket;
180 
181 ErrorReturn:
182 	close (newsocket);
183 	return -1;
184 }
185 
186 //=============================================================================
187 
UDP_CloseSocket(int socket)188 int UDP_CloseSocket (int socket)
189 {
190 	if (socket == net_broadcastsocket)
191 		net_broadcastsocket = 0;
192 	return close (socket);
193 }
194 
195 
196 //=============================================================================
197 /*
198 ============
199 PartialIPAddress
200 
201 this lets you type only as much of the net address as required, using
202 the local network components to fill in the rest
203 ============
204 */
PartialIPAddress(char * in,struct qsockaddr * hostaddr)205 static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
206 {
207 	char buff[256];
208 	char *b;
209 	int addr;
210 	int num;
211 	int mask;
212 	int run;
213 	int port;
214 
215 	buff[0] = '.';
216 	b = buff;
217 	strcpy(buff+1, in);
218 	if (buff[1] == '.')
219 		b++;
220 
221 	addr = 0;
222 	mask=-1;
223 	while (*b == '.')
224 	{
225 		b++;
226 		num = 0;
227 		run = 0;
228 		while (!( *b < '0' || *b > '9'))
229 		{
230 		  num = num*10 + *b++ - '0';
231 		  if (++run > 3)
232 		  	return -1;
233 		}
234 		if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
235 			return -1;
236 		if (num < 0 || num > 255)
237 			return -1;
238 		mask<<=8;
239 		addr = (addr<<8) + num;
240 	}
241 
242 	if (*b++ == ':')
243 		port = Q_atoi(b);
244 	else
245 		port = net_hostport;
246 
247 	hostaddr->sa_family = AF_INET;
248 	((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
249 	((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
250 
251 	return 0;
252 }
253 //=============================================================================
254 
UDP_Connect(int socket,struct qsockaddr * addr)255 int UDP_Connect (int socket, struct qsockaddr *addr)
256 {
257 	return 0;
258 }
259 
260 //=============================================================================
261 
UDP_CheckNewConnections(void)262 int UDP_CheckNewConnections (void)
263 {
264 	unsigned long	available;
265 
266 	if (net_acceptsocket == -1)
267 		return -1;
268 
269 	if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
270 		Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
271 	if (available)
272 		return net_acceptsocket;
273 	return -1;
274 }
275 
276 //=============================================================================
277 
UDP_Read(int socket,byte * buf,int len,struct qsockaddr * addr)278 int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
279 {
280 	int addrlen = sizeof (struct qsockaddr);
281 	int ret;
282 
283 	ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
284 	if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
285 		return 0;
286 	return ret;
287 }
288 
289 //=============================================================================
290 
UDP_MakeSocketBroadcastCapable(int socket)291 int UDP_MakeSocketBroadcastCapable (int socket)
292 {
293 	int				i = 1;
294 
295 	// make this socket broadcast capable
296 	if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
297 		return -1;
298 	net_broadcastsocket = socket;
299 
300 	return 0;
301 }
302 
303 //=============================================================================
304 
UDP_Broadcast(int socket,byte * buf,int len)305 int UDP_Broadcast (int socket, byte *buf, int len)
306 {
307 	int ret;
308 
309 	if (socket != net_broadcastsocket)
310 	{
311 		if (net_broadcastsocket != 0)
312 			Sys_Error("Attempted to use multiple broadcasts sockets\n");
313 		ret = UDP_MakeSocketBroadcastCapable (socket);
314 		if (ret == -1)
315 		{
316 			Con_Printf("Unable to make socket broadcast capable\n");
317 			return ret;
318 		}
319 	}
320 
321 	return UDP_Write (socket, buf, len, &broadcastaddr);
322 }
323 
324 //=============================================================================
325 
UDP_Write(int socket,byte * buf,int len,struct qsockaddr * addr)326 int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
327 {
328 	int ret;
329 
330 	ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
331 	if (ret == -1 && errno == EWOULDBLOCK)
332 		return 0;
333 	return ret;
334 }
335 
336 //=============================================================================
337 
UDP_AddrToString(struct qsockaddr * addr)338 char *UDP_AddrToString (struct qsockaddr *addr)
339 {
340 	static char buffer[22];
341 	int haddr;
342 
343 	haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
344 	sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
345 	return buffer;
346 }
347 
348 //=============================================================================
349 
UDP_StringToAddr(char * string,struct qsockaddr * addr)350 int UDP_StringToAddr (char *string, struct qsockaddr *addr)
351 {
352 	int ha1, ha2, ha3, ha4, hp;
353 	int ipaddr;
354 
355 	sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
356 	ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
357 
358 	addr->sa_family = AF_INET;
359 	((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
360 	((struct sockaddr_in *)addr)->sin_port = htons(hp);
361 	return 0;
362 }
363 
364 //=============================================================================
365 
UDP_GetSocketAddr(int socket,struct qsockaddr * addr)366 int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
367 {
368 	int addrlen = sizeof(struct qsockaddr);
369 	unsigned int a;
370 
371 	Q_memset(addr, 0, sizeof(struct qsockaddr));
372 
373 #if !defined(_WIN32)
374 
375 	if (getsockname(socket, (struct sockaddr *)addr, &addrlen) != 0)
376             return (-1);
377 
378 #else
379 
380 	getsockname(socket, (struct sockaddr *)addr, &addrlen);
381 
382 #endif /* !_WIN32 */
383 
384 	a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
385 	if (a == 0 || a == inet_addr("127.0.0.1"))
386 		((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
387 
388 	return 0;
389 }
390 
391 //=============================================================================
392 
UDP_GetNameFromAddr(struct qsockaddr * addr,char * name)393 int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
394 {
395 	struct hostent *hostentry;
396 
397 	hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
398 	if (hostentry)
399 	{
400 		Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
401 		return 0;
402 	}
403 
404 	Q_strcpy (name, UDP_AddrToString (addr));
405 	return 0;
406 }
407 
408 //=============================================================================
409 
UDP_GetAddrFromName(char * name,struct qsockaddr * addr)410 int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
411 {
412 	struct hostent *hostentry;
413 
414 	if (name[0] >= '0' && name[0] <= '9')
415 		return PartialIPAddress (name, addr);
416 
417 	hostentry = gethostbyname (name);
418 	if (!hostentry)
419 		return -1;
420 
421 	addr->sa_family = AF_INET;
422 	((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
423 	((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
424 
425 	return 0;
426 }
427 
428 //=============================================================================
429 
UDP_AddrCompare(struct qsockaddr * addr1,struct qsockaddr * addr2)430 int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
431 {
432 	if (addr1->sa_family != addr2->sa_family)
433 		return -1;
434 
435 	if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
436 		return -1;
437 
438 	if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
439 		return 1;
440 
441 	return 0;
442 }
443 
444 //=============================================================================
445 
UDP_GetSocketPort(struct qsockaddr * addr)446 int UDP_GetSocketPort (struct qsockaddr *addr)
447 {
448 	return ntohs(((struct sockaddr_in *)addr)->sin_port);
449 }
450 
451 
UDP_SetSocketPort(struct qsockaddr * addr,int port)452 int UDP_SetSocketPort (struct qsockaddr *addr, int port)
453 {
454 	((struct sockaddr_in *)addr)->sin_port = htons(port);
455 	return 0;
456 }
457 
458 //=============================================================================
459