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