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 <sys/param.h> 29 #include <sys/ioctl.h> 30 #include <errno.h> 31 #include <unistd.h> 32 33 #include <arpa/inet.h> 34 35 #ifdef __sun__ 36 #include <sys/filio.h> 37 #endif 38 39 #ifdef NeXT 40 #include <libc.h> 41 #endif 42 43 extern cvar_t hostname; 44 45 static int net_acceptsocket = -1; // socket for fielding new connections 46 static int net_controlsocket; 47 static int net_broadcastsocket = 0; 48 static struct qsockaddr broadcastaddr; 49 50 static unsigned long myAddr; 51 52 #include "net_udp.h" 53 54 // **** Start of Android-specific code **** 55 // copied from ifc_utils.c 56 // 57 // This isn't a good long-term solution: 58 // 1) It is hard-wired to a particular wireless driver 59 // 2) It doesn't handle the IP address changing over time 60 61 #include <sys/ioctl.h> 62 #include <net/if.h> 63 64 static int ifc_ctl_sock = -1; 65 66 int ifc_init(void) 67 { 68 if (ifc_ctl_sock == -1) { 69 ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); 70 if (ifc_ctl_sock < 0) { 71 Con_Printf("socket() failed: %s\n", strerror(errno)); 72 } 73 } 74 return ifc_ctl_sock < 0 ? -1 : 0; 75 } 76 77 void ifc_close(void) 78 { 79 if (ifc_ctl_sock != -1) { 80 (void)close(ifc_ctl_sock); 81 ifc_ctl_sock = -1; 82 } 83 } 84 85 static void ifc_init_ifr(const char *name, struct ifreq *ifr) 86 { 87 memset(ifr, 0, sizeof(struct ifreq)); 88 strncpy(ifr->ifr_name, name, IFNAMSIZ); 89 ifr->ifr_name[IFNAMSIZ - 1] = 0; 90 } 91 92 int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *flags) 93 { 94 struct ifreq ifr; 95 ifc_init_ifr(name, &ifr); 96 97 if (addr != NULL) { 98 if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) { 99 *addr = 0; 100 } else { 101 *addr = ((struct sockaddr_in*) (void*) &ifr.ifr_addr)->sin_addr.s_addr; 102 } 103 } 104 105 if (mask != NULL) { 106 if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { 107 *mask = 0; 108 } else { 109 *mask = ((struct sockaddr_in*) (void*) &ifr.ifr_addr)->sin_addr.s_addr; 110 } 111 } 112 113 if (flags != NULL) { 114 if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) { 115 *flags = 0; 116 } else { 117 *flags = ifr.ifr_flags; 118 } 119 } 120 121 return 0; 122 } 123 124 void AndroidGetAddr() { 125 if (ifc_init()) { 126 return; 127 } 128 in_addr_t addr; 129 ifc_get_info("tiwlan0", &addr, 0, 0); 130 myAddr = addr; 131 ifc_close(); 132 } 133 134 135 // **** End of Android-specific code **** 136 137 //============================================================================= 138 139 int UDP_Init (void) 140 { 141 struct hostent *local; 142 char buff[MAXHOSTNAMELEN]; 143 struct qsockaddr addr; 144 char *colon; 145 146 if (COM_CheckParm ("-noudp")) 147 return -1; 148 149 #if 1 // Android 150 AndroidGetAddr(); 151 #else 152 // determine my name & address 153 gethostname(buff, MAXHOSTNAMELEN); 154 local = gethostbyname(buff); 155 156 if(!local) 157 { 158 Con_Printf("Could not gethostbyname(\"%s\")\n", buff); 159 return -1; 160 } 161 162 myAddr = *(int *)local->h_addr_list[0]; 163 164 // if the quake hostname isn't set, set it to the machine name 165 if (Q_strcmp(hostname.string, "UNNAMED") == 0) 166 { 167 buff[15] = 0; 168 Cvar_Set ("hostname", buff); 169 } 170 #endif 171 if ((net_controlsocket = UDP_OpenSocket (0)) == -1) 172 Sys_Error("UDP_Init: Unable to open control socket\n"); 173 174 sockaddr_in temp; 175 176 memcpy(&temp, &broadcastaddr, sizeof(temp)); 177 178 temp.sin_family = AF_INET; 179 temp.sin_addr.s_addr = INADDR_BROADCAST; 180 temp.sin_port = htons(net_hostport); 181 182 memcpy(&broadcastaddr, &temp, sizeof(temp)); 183 184 UDP_GetSocketAddr (net_controlsocket, &addr); 185 Q_strcpy(my_tcpip_address, UDP_AddrToString (&addr)); 186 colon = Q_strrchr (my_tcpip_address, ':'); 187 if (colon) 188 *colon = 0; 189 190 Con_Printf("UDP Initialized\n"); 191 tcpipAvailable = true; 192 193 return net_controlsocket; 194 } 195 196 //============================================================================= 197 198 void UDP_Shutdown (void) 199 { 200 UDP_Listen (false); 201 UDP_CloseSocket (net_controlsocket); 202 } 203 204 //============================================================================= 205 206 void UDP_Listen (qboolean state) 207 { 208 // enable listening 209 if (state) 210 { 211 if (net_acceptsocket != -1) 212 return; 213 if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1) 214 Sys_Error ("UDP_Listen: Unable to open accept socket\n"); 215 return; 216 } 217 218 // disable listening 219 if (net_acceptsocket == -1) 220 return; 221 UDP_CloseSocket (net_acceptsocket); 222 net_acceptsocket = -1; 223 } 224 225 //============================================================================= 226 227 int UDP_OpenSocket (int port) 228 { 229 int newsocket; 230 union { 231 struct sockaddr_in in; 232 struct sockaddr sockaddr; 233 } address; 234 qboolean _true = true; 235 236 if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 237 return -1; 238 239 if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1) 240 goto ErrorReturn; 241 242 address.in.sin_family = AF_INET; 243 address.in.sin_addr.s_addr = INADDR_ANY; 244 address.in.sin_port = htons(port); 245 if( bind (newsocket, &address.sockaddr, sizeof(address.in)) == -1) 246 goto ErrorReturn; 247 248 return newsocket; 249 250 ErrorReturn: 251 close (newsocket); 252 return -1; 253 } 254 255 //============================================================================= 256 257 int UDP_CloseSocket (int socket) 258 { 259 if (socket == net_broadcastsocket) 260 net_broadcastsocket = 0; 261 return close (socket); 262 } 263 264 265 //============================================================================= 266 /* 267 ============ 268 PartialIPAddress 269 270 this lets you type only as much of the net address as required, using 271 the local network components to fill in the rest 272 ============ 273 */ 274 static int PartialIPAddress (const char *in, struct qsockaddr *hostaddr) 275 { 276 char buff[256]; 277 char *b; 278 int addr; 279 int num; 280 int mask; 281 int run; 282 int port; 283 284 buff[0] = '.'; 285 b = buff; 286 strcpy(buff+1, in); 287 if (buff[1] == '.') 288 b++; 289 290 addr = 0; 291 mask=-1; 292 while (*b == '.') 293 { 294 b++; 295 num = 0; 296 run = 0; 297 while (!( *b < '0' || *b > '9')) 298 { 299 num = num*10 + *b++ - '0'; 300 if (++run > 3) 301 return -1; 302 } 303 if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) 304 return -1; 305 if (num < 0 || num > 255) 306 return -1; 307 mask<<=8; 308 addr = (addr<<8) + num; 309 } 310 311 if (*b++ == ':') 312 port = Q_atoi(b); 313 else 314 port = net_hostport; 315 316 hostaddr->sa_family = AF_INET; 317 ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); 318 ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); 319 320 return 0; 321 } 322 //============================================================================= 323 324 int UDP_Connect (int socket, struct qsockaddr *addr) 325 { 326 return 0; 327 } 328 329 //============================================================================= 330 331 int UDP_CheckNewConnections (void) 332 { 333 unsigned long available; 334 335 if (net_acceptsocket == -1) 336 return -1; 337 338 if (ioctl (net_acceptsocket, FIONREAD, &available) == -1) 339 Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n"); 340 if (available) 341 return net_acceptsocket; 342 return -1; 343 } 344 345 //============================================================================= 346 347 int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr) 348 { 349 int addrlen = sizeof (struct qsockaddr); 350 int ret; 351 352 ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, (socklen_t*) &addrlen); 353 if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED)) 354 return 0; 355 return ret; 356 } 357 358 //============================================================================= 359 360 int UDP_MakeSocketBroadcastCapable (int socket) 361 { 362 int i = 1; 363 364 // make this socket broadcast capable 365 if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) 366 return -1; 367 net_broadcastsocket = socket; 368 369 return 0; 370 } 371 372 //============================================================================= 373 374 int UDP_Broadcast (int socket, byte *buf, int len) 375 { 376 int ret; 377 378 if (socket != net_broadcastsocket) 379 { 380 if (net_broadcastsocket != 0) 381 Sys_Error("Attempted to use multiple broadcasts sockets\n"); 382 ret = UDP_MakeSocketBroadcastCapable (socket); 383 if (ret == -1) 384 { 385 Con_Printf("Unable to make socket broadcast capable\n"); 386 return ret; 387 } 388 } 389 390 return UDP_Write (socket, buf, len, &broadcastaddr); 391 } 392 393 //============================================================================= 394 395 int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr) 396 { 397 int ret; 398 399 ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); 400 if (ret == -1 && errno == EWOULDBLOCK) 401 return 0; 402 return ret; 403 } 404 405 //============================================================================= 406 407 char *UDP_AddrToString (struct qsockaddr *addr) 408 { 409 static char buffer[22]; 410 int haddr; 411 412 haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); 413 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)); 414 return buffer; 415 } 416 417 //============================================================================= 418 419 int UDP_StringToAddr (const char *string, struct qsockaddr *addr) 420 { 421 int ha1, ha2, ha3, ha4, hp; 422 int ipaddr; 423 424 sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); 425 ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; 426 427 addr->sa_family = AF_INET; 428 ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); 429 ((struct sockaddr_in *)addr)->sin_port = htons(hp); 430 return 0; 431 } 432 433 //============================================================================= 434 435 int UDP_GetSocketAddr (int socket, struct qsockaddr *addr) 436 { 437 int addrlen = sizeof(struct qsockaddr); 438 unsigned int a; 439 440 Q_memset(addr, 0, sizeof(struct qsockaddr)); 441 getsockname(socket, (struct sockaddr *)addr, (socklen_t*) &addrlen); 442 a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; 443 if (a == 0 || (in_addr_t) a == inet_addr("127.0.0.1")) 444 ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; 445 446 return 0; 447 } 448 449 //============================================================================= 450 451 int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name) 452 { 453 struct hostent *hostentry; 454 455 hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); 456 if (hostentry) 457 { 458 Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); 459 return 0; 460 } 461 462 Q_strcpy (name, UDP_AddrToString (addr)); 463 return 0; 464 } 465 466 //============================================================================= 467 468 int UDP_GetAddrFromName(const char *name, struct qsockaddr *addr) 469 { 470 struct hostent *hostentry; 471 472 if (name[0] >= '0' && name[0] <= '9') 473 return PartialIPAddress (name, addr); 474 475 hostentry = gethostbyname (name); 476 if (!hostentry) 477 return -1; 478 479 addr->sa_family = AF_INET; 480 ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport); 481 ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; 482 483 return 0; 484 } 485 486 //============================================================================= 487 488 int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) 489 { 490 if (addr1->sa_family != addr2->sa_family) 491 return -1; 492 493 if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) 494 return -1; 495 496 if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) 497 return 1; 498 499 return 0; 500 } 501 502 //============================================================================= 503 504 int UDP_GetSocketPort (struct qsockaddr *addr) 505 { 506 return ntohs(((struct sockaddr_in *)addr)->sin_port); 507 } 508 509 510 int UDP_SetSocketPort (struct qsockaddr *addr, int port) 511 { 512 ((struct sockaddr_in *)addr)->sin_port = htons(port); 513 return 0; 514 } 515 516 //============================================================================= 517