@Peter I'm attaching the patch I've written again, so everyone can find it. It tries to find out the public IP by walkind the Interfaces available through the Kernel.
@Pavel I think that such a patch should be applied, Peter just said what I wanted to hear :-) Windows just acts different in this, and wine should act exactly the same. You can't expect every Linux-user to specially hand-write his /etc/hosts so that his windows-programs/games work. :) greetings Am Dienstag, 13. Dezember 2005 16:57 schrieb Peter Åstrand: > On Tue, 13 Dec 2005, Pavel Troller wrote: > >> 127.0.0.1 localhost.localdomain localhost Zwirch > > > > Yes, I know that *MANY* well-known distros are wrong with /etc/hosts and > > similar files.. > > > > I think that it is NOT GOOD to patch wine to fix this case; it behaves > > absolutely correctly and all the problem should be solved by correctly > > configuring your Linux networking. Please see any good document about > > naming principles of network interfaces. > > I haven't followed the whole thread, so sorry if I've missed something > obvious, but: > > I think you are wrong. POSIX does not say that it's wrong to have the > computer name associated with 127.0.0.1 in /etc/hosts, and it doesn't say > that gethostbyname(my_name) should return a "real" IP. If I remember > correctly, though, Microsoft, specifies that gethostbyname(my_name) > *should* return real IP. > > This subtle difference means that Wine must take extra care. Fetching a > real IP on a UNIX host is not trivial, but doable. > > Instead of just fetching the IP by looking up the hostname, I suggest > using the approach below instead. It will fail if there is no route to > 192.168.1.1 (typically this means that you don't have a default gateway). > When this happens, you can resolv the hostname as a fallback. > > #include <stdio.h> > #include <stdlib.h> > #include <sys/socket.h> > #include <netinet/in.h> > #include <arpa/inet.h> > > int main() > { > int s, c, got_sockname = 0; > struct sockaddr_in serv_addr; > struct sockaddr_in my_addr; > char *my_ip; > > serv_addr.sin_family = AF_INET; > serv_addr.sin_port = htons(1); > /* Even better: Use the server you will connect to */ > inet_aton("192.168.1.1", &serv_addr.sin_addr); > > s = socket (PF_INET, SOCK_DGRAM, 0); > if (s < 0) { > perror("socket"); > exit(EXIT_FAILURE); > } > > /* connect fails if if server is unreachable, for example */ > if ((c = connect(s, (struct sockaddr*) &serv_addr, sizeof(serv_addr))) > >= 0) { socklen_t my_addrlen; > my_addrlen = sizeof(my_addr); > if (getsockname(s, (struct sockaddr*)&my_addr, &my_addrlen) >= 0) > { got_sockname = 1; > } > } > > if (!got_sockname) > /* Use 127.0.0.1 as a fallback. Even better: Resolv the > hostname. */ > inet_aton("127.0.0.1", &my_addr.sin_addr); > > my_ip = inet_ntoa(my_addr.sin_addr); > printf("%s\n", my_ip); > > return 0; > } > > Regards,
Index: dlls/winsock/socket.c =================================================================== RCS file: /home/wine/wine/dlls/winsock/socket.c,v retrieving revision 1.203 diff -b -B -c -r1.203 socket.c *** dlls/winsock/socket.c 12 Dec 2005 12:49:05 -0000 1.203 --- dlls/winsock/socket.c 13 Dec 2005 12:26:18 -0000 *************** *** 2927,2932 **** --- 2927,2991 ---- return retval; } + + /*********************************************************************** + * getpublicIP (Internal) + * + * Tries to guess the public IP-Adress by enumerating the available Interfaces + * target needs to be a buffer with the maximum size given in "size" + */ + + + BOOL getpublicIP(char* target,int size) + { + char buff[1024]; + char buffer[1024]; + struct ifconf ifc; + struct ifreq *ifr; + int skfd; + int i; + + skfd = socket(AF_INET, SOCK_DGRAM, 0); + if (skfd < 0) + { + WARN("A socket could not be created"); + return FALSE; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) + { + WARN("ioctl(SIOCGIFCONF) failed"); + close(skfd); + return FALSE; + } + + close(skfd); + + ifr = ifc.ifc_req; + + for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++) + { + struct sockaddr_in* addr=(struct sockaddr_in*)&ifr[i].ifr_addr; + unsigned char* ip = ((unsigned char*)&addr->sin_addr); + + if(strcmp(ifr[i].ifr_name,"lo")==0)continue; /*Exclude loopback-device by Name "lo"*/ + + if(ip[0]==127&&ip[1]==0&&ip[2]==0&&ip[3]==0)continue; /*Exclude 127.0.0.1*/ + + sprintf(buffer,"%i.%i.%i.%i", (int)ip[0],(int)ip[1],(int)ip[2],(int)ip[3]); + + if(size>strlen(buffer))strcpy(target,buffer); + + return TRUE; + } + + return FALSE; + } + + + /*********************************************************************** * gethostbyname (WS2_32.52) */ *************** *** 2930,2937 **** --- 2989,3000 ---- /*********************************************************************** * gethostbyname (WS2_32.52) */ + struct WS_hostent* WINAPI WS_gethostbyname(const char* name) { + char myname[1000]; + struct in_addr newaddr; + struct WS_hostent *retval = NULL; struct hostent* host; #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6 *************** *** 2941,2946 **** --- 3004,3012 ---- int locerr = ENOBUFS; #endif char buf[100]; + + gethostname(myname,(size_t)1000); + if( !name) { name = buf; if( gethostname( buf, 100) == -1) { *************** *** 2961,2969 **** #else EnterCriticalSection( &csWSgetXXXbyYYY ); host = gethostbyname(name); if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno)); #endif ! if (host) retval = WS_dup_he(host); #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6 HeapFree(GetProcessHeap(),0,extrabuf); #else --- 3029,3055 ---- #else EnterCriticalSection( &csWSgetXXXbyYYY ); host = gethostbyname(name); + if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno)); #endif ! if (host){ ! if(strcmp(myname,name)==0){ ! /*Replace the gotten Adress*/ ! char buffer[400]; ! if(getpublicIP(buffer,400)&&host->h_length==4) /*Make sure that it really is an IPv4 Adress by checking h_length==4*/ ! { ! inet_aton(buffer,&newaddr); ! ! memcpy(((struct in_addr *)host->h_addr_list[0]),&newaddr,4); ! ! TRACE("Using %s as public Adress for local Host %s\n",inet_ntoa(*((struct in_addr *)host->h_addr_list[0])),name); ! }else{ ! WARN("Public IP-Adress of local Host could not be recognized"); ! } ! } ! ! retval = WS_dup_he(host); ! } #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6 HeapFree(GetProcessHeap(),0,extrabuf); #else