1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, 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 43extern cvar_t hostname; 44 45static int net_acceptsocket = -1; // socket for fielding new connections 46static int net_controlsocket; 47static int net_broadcastsocket = 0; 48static struct qsockaddr broadcastaddr; 49 50static 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 64static int ifc_ctl_sock = -1; 65 66int 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 77void ifc_close(void) 78{ 79 if (ifc_ctl_sock != -1) { 80 (void)close(ifc_ctl_sock); 81 ifc_ctl_sock = -1; 82 } 83} 84 85static 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 92int 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 124void 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 139int 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 198void UDP_Shutdown (void) 199{ 200 UDP_Listen (false); 201 UDP_CloseSocket (net_controlsocket); 202} 203 204//============================================================================= 205 206void 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 227int 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 250ErrorReturn: 251 close (newsocket); 252 return -1; 253} 254 255//============================================================================= 256 257int UDP_CloseSocket (int socket) 258{ 259 if (socket == net_broadcastsocket) 260 net_broadcastsocket = 0; 261 return close (socket); 262} 263 264 265//============================================================================= 266/* 267============ 268PartialIPAddress 269 270this lets you type only as much of the net address as required, using 271the local network components to fill in the rest 272============ 273*/ 274static 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 324int UDP_Connect (int socket, struct qsockaddr *addr) 325{ 326 return 0; 327} 328 329//============================================================================= 330 331int 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 347int 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 360int 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 374int 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 395int 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 407char *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 419int 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 435int 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 451int 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 468int 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 488int 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 504int UDP_GetSocketPort (struct qsockaddr *addr) 505{ 506 return ntohs(((struct sockaddr_in *)addr)->sin_port); 507} 508 509 510int UDP_SetSocketPort (struct qsockaddr *addr, int port) 511{ 512 ((struct sockaddr_in *)addr)->sin_port = htons(port); 513 return 0; 514} 515 516//============================================================================= 517