• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_main.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 <sys/param.h>
29 #include <sys/ioctl.h>
30 #include <sys/uio.h>
31 #include <arpa/inet.h>
32 #include <errno.h>
33 
34 #if defined(sun)
35 #include <unistd.h>
36 #endif
37 
38 #ifdef sun
39 #include <sys/filio.h>
40 #endif
41 
42 #ifdef NeXT
43 #include <libc.h>
44 #endif
45 
46 netadr_t	net_local_adr;
47 
48 netadr_t	net_from;
49 sizebuf_t	net_message;
50 int			net_socket;			// non blocking, for receives
51 int			net_send_socket;	// blocking, for sends
52 
53 #define	MAX_UDP_PACKET	8192
54 byte		net_message_buffer[MAX_UDP_PACKET];
55 
56 // int gethostname (char *, int);
57 int close (int);
58 
59 //=============================================================================
60 
NetadrToSockadr(netadr_t * a,struct sockaddr_in * s)61 void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
62 {
63 	memset (s, 0, sizeof(*s));
64 	s->sin_family = AF_INET;
65 
66 	*(int *)&s->sin_addr = *(int *)&a->ip;
67 	s->sin_port = a->port;
68 }
69 
SockadrToNetadr(struct sockaddr_in * s,netadr_t * a)70 void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
71 {
72 	*(int *)&a->ip = *(int *)&s->sin_addr;
73 	a->port = s->sin_port;
74 }
75 
NET_CompareBaseAdr(netadr_t a,netadr_t b)76 qboolean	NET_CompareBaseAdr (netadr_t a, netadr_t b)
77 {
78 	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
79 		return true;
80 	return false;
81 }
82 
83 
NET_CompareAdr(netadr_t a,netadr_t b)84 qboolean	NET_CompareAdr (netadr_t a, netadr_t b)
85 {
86 	if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
87 		return true;
88 	return false;
89 }
90 
NET_AdrToString(netadr_t a)91 char	*NET_AdrToString (netadr_t a)
92 {
93 	static	char	s[64];
94 
95 	sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port));
96 
97 	return s;
98 }
99 
NET_BaseAdrToString(netadr_t a)100 char	*NET_BaseAdrToString (netadr_t a)
101 {
102 	static	char	s[64];
103 
104 	sprintf (s, "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
105 
106 	return s;
107 }
108 
109 /*
110 =============
111 NET_StringToAdr
112 
113 idnewt
114 idnewt:28000
115 192.246.40.70
116 192.246.40.70:28000
117 =============
118 */
NET_StringToAdr(char * s,netadr_t * a)119 qboolean	NET_StringToAdr (char *s, netadr_t *a)
120 {
121 	struct hostent	*h;
122 	struct sockaddr_in sadr;
123 	char	*colon;
124 	char	copy[128];
125 
126 
127 	memset (&sadr, 0, sizeof(sadr));
128 	sadr.sin_family = AF_INET;
129 
130 	sadr.sin_port = 0;
131 
132 	strcpy (copy, s);
133 	// strip off a trailing :port if present
134 	for (colon = copy ; *colon ; colon++)
135 		if (*colon == ':')
136 		{
137 			*colon = 0;
138 			sadr.sin_port = htons(atoi(colon+1));
139 		}
140 
141 	if (copy[0] >= '0' && copy[0] <= '9')
142 	{
143 		*(int *)&sadr.sin_addr = inet_addr(copy);
144 	}
145 	else
146 	{
147 		if (! (h = gethostbyname(copy)) )
148 			return 0;
149 		*(int *)&sadr.sin_addr = *(int *)h->h_addr_list[0];
150 	}
151 
152 	SockadrToNetadr (&sadr, a);
153 
154 	return true;
155 }
156 
157 // Returns true if we can't bind the address locally--in other words,
158 // the IP is NOT one of our interfaces.
NET_IsClientLegal(netadr_t * adr)159 qboolean NET_IsClientLegal(netadr_t *adr)
160 {
161 	struct sockaddr_in sadr;
162 	int newsocket;
163 
164 #if 0
165 	if (adr->ip[0] == 127)
166 		return false; // no local connections period
167 
168 	NetadrToSockadr (adr, &sadr);
169 
170 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
171 		Sys_Error ("NET_IsClientLegal: socket:", strerror(errno));
172 
173 	sadr.sin_port = 0;
174 
175 	if( bind (newsocket, (void *)&sadr, sizeof(sadr)) == -1)
176 	{
177 		// It is not a local address
178 		close(newsocket);
179 		return true;
180 	}
181 	close(newsocket);
182 	return false;
183 #else
184 	return true;
185 #endif
186 }
187 
188 
189 //=============================================================================
190 
NET_GetPacket(void)191 qboolean NET_GetPacket (void)
192 {
193 	int 	ret;
194 	struct sockaddr_in	from;
195 	socklen_t		fromlen;
196 
197 	fromlen = sizeof(from);
198 	ret = recvfrom (net_socket, net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen);
199 	if (ret == -1) {
200 		if (errno == EWOULDBLOCK)
201 			return false;
202 		if (errno == ECONNREFUSED)
203 			return false;
204 		Sys_Printf ("NET_GetPacket: %s\n", strerror(errno));
205 		return false;
206 	}
207 
208 	net_message.cursize = ret;
209 	SockadrToNetadr (&from, &net_from);
210 
211 	return ret;
212 }
213 
214 //=============================================================================
215 
NET_SendPacket(int length,void * data,netadr_t to)216 void NET_SendPacket (int length, void *data, netadr_t to)
217 {
218 	int ret;
219 	struct sockaddr_in	addr;
220 
221 	NetadrToSockadr (&to, &addr);
222 
223 	ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
224 	if (ret == -1) {
225 		if (errno == EWOULDBLOCK)
226 			return;
227 		if (errno == ECONNREFUSED)
228 			return;
229 		Sys_Printf ("NET_SendPacket: %s\n", strerror(errno));
230 	}
231 }
232 
233 //=============================================================================
234 
UDP_OpenSocket(int port)235 int UDP_OpenSocket (int port)
236 {
237 	int newsocket;
238 	struct sockaddr_in address;
239 	qboolean _true = true;
240 	int i;
241 
242 	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
243 		Sys_Error ("UDP_OpenSocket: socket:", strerror(errno));
244 	if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
245 		Sys_Error ("UDP_OpenSocket: ioctl FIONBIO:", strerror(errno));
246 	address.sin_family = AF_INET;
247 //ZOID -- check for interface binding option
248 	if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) {
249 		address.sin_addr.s_addr = inet_addr(com_argv[i+1]);
250 		Con_Printf("Binding to IP Interface Address of %s\n",
251 				inet_ntoa(address.sin_addr));
252 	} else
253 		address.sin_addr.s_addr = INADDR_ANY;
254 	if (port == PORT_ANY)
255 		address.sin_port = 0;
256 	else
257 		address.sin_port = htons((short)port);
258 	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
259 		Sys_Error ("UDP_OpenSocket: bind: %s", strerror(errno));
260 
261 	return newsocket;
262 }
263 
NET_GetLocalAddress(void)264 void NET_GetLocalAddress (void)
265 {
266 	char	buff[MAXHOSTNAMELEN];
267 	struct sockaddr_in	address;
268 	socklen_t namelen;
269 
270 	gethostname(buff, MAXHOSTNAMELEN);
271 	buff[MAXHOSTNAMELEN-1] = 0;
272 
273 	NET_StringToAdr (buff, &net_local_adr);
274 
275 	namelen = sizeof(address);
276 	if (getsockname (net_socket, (struct sockaddr *)&address, &namelen) == -1)
277 		Sys_Error ("NET_Init: getsockname:", strerror(errno));
278 	net_local_adr.port = address.sin_port;
279 
280 	Con_Printf("IP address %s\n", NET_AdrToString (net_local_adr) );
281 }
282 
283 /*
284 ====================
285 NET_Init
286 ====================
287 */
NET_Init(int port)288 void NET_Init (int port)
289 {
290 	//
291 	// open the single socket to be used for all communications
292 	//
293 	net_socket = UDP_OpenSocket (port);
294 
295 	//
296 	// init the message buffer
297 	//
298 	net_message.maxsize = sizeof(net_message_buffer);
299 	net_message.data = net_message_buffer;
300 
301 	//
302 	// determine my name & address
303 	//
304 	NET_GetLocalAddress ();
305 
306 	Con_Printf("UDP Initialized\n");
307 }
308 
309 /*
310 ====================
311 NET_Shutdown
312 ====================
313 */
NET_Shutdown(void)314 void	NET_Shutdown (void)
315 {
316 	close (net_socket);
317 }
318 
319