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