Using the base Quake source as an example:
Open net_wins.c:
Step 1: Above "void WINS_GetLocalAddress()", add this:
Step #2: Find the "void WINS_GetLocalAddress()" procedure and replace the full procedure with the following:
FAQ about the above:
#1 What is the difference between the previous DSL fix and this?
It was missing an important "else" condition.
#2 What is the "DSL" fix?
There are a number of situations where Quake can't use the internet because it tries to use the wrong IP address. This is particularly a problem for DSL without a router and for DSL when the router isn't doing the PPPOE authentication itself. It can also affect dialup + LAN or even in rare circumstances cable with some network setups.
The result is that with this fix, Quake will figure out which IP address represents the current internet connection.
Open net_wins.c:
Step 1: Above "void WINS_GetLocalAddress()", add this:
Code:
int WINS_iptype(unsigned long ipaddr) { // Baker: 3.99e - workaround for mostly DSL/dialup // Return 1 if unresolvable/invalid // Return 2 if private network (router, LAN, whatever) // Return 3 if internet ip // TCP/IP addresses reserved for 'private' networks are: //10.0.0.0 to 10.255.255.255 //172.16.0.0 to 172.31.255.255 //192.168.0.0 to 192.168.255.255 // //and as of July 2001 // //169.254.0.0 to 169.254.255.255 rfc if (((ipaddr >> 24) & 0xff) == 0) return 1; // Invalid ip if (((ipaddr >> 24) & 0xff) == 169 && ((ipaddr >> 16) & 0xff) == 254) return 1; // Unresolvable private ip if (((ipaddr >> 24) & 0xff) == 10) return 2; // Private ip if (((ipaddr >> 24) & 0xff) == 172 && ((ipaddr >> 16) & 0xff) >= 16 && ((ipaddr >> 16) & 0xff) <= 31) return 2; // Private ip if (((ipaddr >> 24) & 0xff) == 192 && ((ipaddr >> 16) & 0xff) == 168) return 2; // Private ip return 3; }
Code:
void WINS_GetLocalAddress() { struct hostent *local = NULL; char buff[MAXHOSTNAMELEN]; unsigned long addr; if (myAddr != INADDR_ANY) return; if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) return; blocktime = Sys_DoubleTime(); WSASetBlockingHook(BlockingHook); local = pgethostbyname(buff); WSAUnhookBlockingHook(); if (local == NULL) return; if (COM_CheckParm("-oldnet") || isDedicated) { // Baker: screens for unresolvable ips like 169.254.x.x (dsl modem at best, unresponsive device at worst) myAddr = *(int *)local->h_addr_list[0]; addr = ntohl(myAddr); sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); // Baker: is ip address #0 = 169.254.x.x ? if (WINS_iptype(addr) == 1) { // Unresolvable private IP or invalid ip Con_DPrintf ("WINS_GetLocalAddress: ip address #0 (%s) is invalid, checking next ...\n", my_tcpip_address); if (local->h_addr_list[1]) { // ip address #1 exists, use it. myAddr = *(int *)local->h_addr_list[1]; addr = ntohl(myAddr); sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); Con_DPrintf ("WINS_GetLocalAddress: ip address #1 (%s) found. Using.\n", my_tcpip_address); } else { Con_DPrintf("WINS_GetLocalAddress: ip address #1 does not exist\n"); Con_DPrintf("WINS_GetLocalAddress: Warning continuing with #0\n"); Con_Printf("Invalid IP (%s): Is internet/network connected?\n", my_tcpip_address); } } return; } // Baker 3.99e: New: use internet ip over private network ip over unresolvable/invalid ip { unsigned long addr0, addr1, addr2; int choice = 0, addrtype0 = 0, addrtype1 = 0, addrtype2 = 0; char tcpip0[NET_NAMELEN]; char tcpip1[NET_NAMELEN]; char tcpip2[NET_NAMELEN]; // Baker: get ip addresses myAddr = *(int *)local->h_addr_list[0]; addr0 = ntohl(myAddr); addrtype0 = WINS_iptype(addr0); sprintf(tcpip0, "%d.%d.%d.%d", (addr0 >> 24) & 0xff, (addr0 >> 16) & 0xff, (addr0 >> 8) & 0xff, addr0 & 0xff); if (local->h_addr_list[1]) { Con_Printf("\nMultiple IPs found\n%s", Con_Quakebar(36)); Con_Printf("ip #0: %s %s\n", ((addrtype0 == 3) ? "internet " : ((addrtype0 == 2) ? "local network" : ((addrtype0 == 1) ? "unresolvable " : "no device "))), tcpip0); myAddr = *(int *)local->h_addr_list[1]; addr1 = ntohl(myAddr); addrtype1 = WINS_iptype(addr1); sprintf(tcpip1, "%d.%d.%d.%d", (addr1 >> 24) & 0xff, (addr1 >> 16) & 0xff, (addr1 >> 8) & 0xff, addr1 & 0xff); Con_Printf("ip #1: %s %s\n", ((addrtype1 == 3) ? "internet " : ((addrtype1 == 2) ? "local network" : ((addrtype1 == 1) ? "unresolvable " : "no device "))), tcpip1); if (addrtype1 >= addrtype0) choice = 1; if (local->h_addr_list[2]) { myAddr = *(int *)local->h_addr_list[2]; addr2 = ntohl(myAddr); addrtype2 = WINS_iptype(addr2); sprintf(tcpip2, "%d.%d.%d.%d", (addr2 >> 24) & 0xff, (addr2 >> 16) & 0xff, (addr2 >> 8) & 0xff, addr2 & 0xff); Con_Printf("ip #2: %s %s\n", ((addrtype2 == 3) ? "internet " : ((addrtype2 == 2) ? "local network" : ((addrtype2 == 1) ? "unresolvable " : "no device "))), tcpip2); if (addrtype2 >= (choice == 0 ? addrtype0 : addrtype1)) choice = 2; // else the above stands } myAddr = *(int *)local->h_addr_list[choice]; addr = ntohl(myAddr); sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); Con_Printf("%s", Con_Quakebar(36)); Con_Printf("Using ip %s\n", my_tcpip_address); Con_Printf("%s\n", Con_Quakebar(36)); } else { myAddr = *(int *)local->h_addr_list[0]; addr = ntohl(myAddr); sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); } } }
FAQ about the above:
#1 What is the difference between the previous DSL fix and this?
It was missing an important "else" condition.
#2 What is the "DSL" fix?
There are a number of situations where Quake can't use the internet because it tries to use the wrong IP address. This is particularly a problem for DSL without a router and for DSL when the router isn't doing the PPPOE authentication itself. It can also affect dialup + LAN or even in rare circumstances cable with some network setups.
The result is that with this fix, Quake will figure out which IP address represents the current internet connection.