host.cpp

Go to the documentation of this file.
00001 /* $Id: host.cpp 15718 2009-03-15 00:32:18Z rubidium $ */
00002 
00005 #ifdef ENABLE_NETWORK
00006 
00007 #include "../../stdafx.h"
00008 #include "../../debug.h"
00009 #include "os_abstraction.h"
00010 #include "../../core/alloc_func.hpp"
00011 
00018 static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit);
00019 
00020 #if defined(PSP)
00021 static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // PSP implementation
00022 {
00023   return 0;
00024 }
00025 
00026 #elif defined(BEOS_NET_SERVER) /* doesn't have neither getifaddrs or net/if.h */
00027 /* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */
00028 int _netstat(int fd, char **output, int verbose);
00029 
00030 int seek_past_header(char **pos, const char *header)
00031 {
00032   char *new_pos = strstr(*pos, header);
00033   if (new_pos == 0) {
00034     return B_ERROR;
00035   }
00036   *pos += strlen(header) + new_pos - *pos + 1;
00037   return B_OK;
00038 }
00039 
00040 static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // BEOS implementation
00041 {
00042   int sock = socket(AF_INET, SOCK_DGRAM, 0);
00043 
00044   if (sock < 0) {
00045     DEBUG(net, 0, "[core] error creating socket");
00046     return 0;
00047   }
00048 
00049   char *output_pointer = NULL;
00050   int output_length = _netstat(sock, &output_pointer, 1);
00051   if (output_length < 0) {
00052     DEBUG(net, 0, "[core] error running _netstat");
00053     return 0;
00054   }
00055 
00056   int index;
00057   char **output = &output_pointer;
00058   if (seek_past_header(output, "IP Interfaces:") == B_OK) {
00059     while (index != limit) {
00060 
00061       uint32 n, fields, read;
00062       uint8 i1, i2, i3, i4, j1, j2, j3, j4;
00063       struct in_addr inaddr;
00064       uint32 ip;
00065       uint32 netmask;
00066 
00067       fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n",
00068                         &n, &i1, &i2, &i3, &i4, &j1, &j2, &j3, &j4, &read);
00069       read += 1;
00070       if (fields != 9) {
00071         break;
00072       }
00073 
00074       ip      = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4;
00075       netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4;
00076 
00077       if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) {
00078         inaddr.s_addr = htonl(ip | ~netmask);
00079         broadcast[index] = inaddr.s_addr;
00080         index++;
00081       }
00082       if (read < 0) {
00083         break;
00084       }
00085       *output += read;
00086     }
00087     closesocket(sock);
00088   }
00089 
00090   return index;
00091 }
00092 
00093 #elif defined(HAVE_GETIFADDRS)
00094 static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // GETIFADDRS implementation
00095 {
00096   struct ifaddrs *ifap, *ifa;
00097 
00098   if (getifaddrs(&ifap) != 0) return 0;
00099 
00100   int index = 0;
00101   for (ifa = ifap; ifa != NULL && index != limit; ifa = ifa->ifa_next) {
00102     if (!(ifa->ifa_flags & IFF_BROADCAST)) continue;
00103     if (ifa->ifa_broadaddr == NULL) continue;
00104     if (ifa->ifa_broadaddr->sa_family != AF_INET) continue;
00105 
00106     broadcast[index] = ((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr;
00107     index++;
00108   }
00109   freeifaddrs(ifap);
00110 
00111   return index;
00112 }
00113 
00114 #elif defined(WIN32)
00115 static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // Win32 implementation
00116 {
00117   SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
00118   if (sock == INVALID_SOCKET) return 0;
00119 
00120   DWORD len = 0;
00121   INTERFACE_INFO *ifo = AllocaM(INTERFACE_INFO, limit);
00122   memset(ifo, 0, limit * sizeof(*ifo));
00123   if ((WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, &ifo[0], limit * sizeof(*ifo), &len, NULL, NULL)) != 0) {
00124     closesocket(sock);
00125     return 0;
00126   }
00127 
00128   int index = 0;
00129   for (uint j = 0; j < len / sizeof(*ifo) && index != limit; j++) {
00130     if (ifo[j].iiFlags & IFF_LOOPBACK) continue;
00131     if (!(ifo[j].iiFlags & IFF_BROADCAST)) continue;
00132 
00133     /* iiBroadcast is unusable, because it always seems to be set to 255.255.255.255. */
00134     broadcast[index++] = ifo[j].iiAddress.AddressIn.sin_addr.s_addr | ~ifo[j].iiNetmask.AddressIn.sin_addr.s_addr;
00135   }
00136 
00137   closesocket(sock);
00138   return index;
00139 }
00140 
00141 #else /* not HAVE_GETIFADDRS */
00142 
00143 #include "../../string_func.h"
00144 
00145 static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // !GETIFADDRS implementation
00146 {
00147   SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
00148   if (sock == INVALID_SOCKET) return 0;
00149 
00150   char buf[4 * 1024]; // Arbitrary buffer size
00151   struct ifconf ifconf;
00152 
00153   ifconf.ifc_len = sizeof(buf);
00154   ifconf.ifc_buf = buf;
00155   if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1) {
00156     closesocket(sock);
00157     return 0;
00158   }
00159 
00160   const char *buf_end = buf + ifconf.ifc_len;
00161   int index = 0;
00162   for (const char *p = buf; p < buf_end && index != limit;) {
00163     const struct ifreq *req = (const struct ifreq*)p;
00164 
00165     if (req->ifr_addr.sa_family == AF_INET) {
00166       struct ifreq r;
00167 
00168       strecpy(r.ifr_name, req->ifr_name, lastof(r.ifr_name));
00169       if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 &&
00170           r.ifr_flags & IFF_BROADCAST &&
00171           ioctl(sock, SIOCGIFBRDADDR, &r) != -1) {
00172         broadcast[index++] = ((struct sockaddr_in*)&r.ifr_broadaddr)->sin_addr.s_addr;
00173       }
00174     }
00175 
00176     p += sizeof(struct ifreq);
00177 #if defined(AF_LINK) && !defined(SUNOS)
00178     p += req->ifr_addr.sa_len - sizeof(struct sockaddr);
00179 #endif
00180   }
00181 
00182   closesocket(sock);
00183 
00184   return index;
00185 }
00186 #endif /* all NetworkFindBroadcastIPsInternals */
00187 
00193 void NetworkFindBroadcastIPs(uint32 *broadcast, int limit)
00194 {
00195   int count = NetworkFindBroadcastIPsInternal(broadcast, limit);
00196 
00197   /* Make sure the list is terminated. */
00198   broadcast[count] = 0;
00199 
00200   /* Now display to the debug all the detected ips */
00201   DEBUG(net, 3, "Detected broadcast addresses:");
00202   for (int i = 0; broadcast[i] != 0; i++) {
00203     DEBUG(net, 3, "%d) %s", i, inet_ntoa(*(struct in_addr *)&broadcast[i])); // inet_ntoa(inaddr));
00204   }
00205 }
00206 
00207 
00213 uint32 NetworkResolveHost(const char *hostname)
00214 {
00215   /* Is this an IP address? */
00216   in_addr_t ip = inet_addr(hostname);
00217 
00218   if (ip != INADDR_NONE) return ip;
00219 
00220   /* No, try to resolve the name */
00221   struct in_addr addr;
00222 #if !defined(PSP)
00223   struct hostent *he = gethostbyname(hostname);
00224   if (he == NULL) {
00225     DEBUG(net, 0, "[NET] Cannot resolve %s", hostname);
00226     return 0;
00227   }
00228   addr = *(struct in_addr *)he->h_addr_list[0];
00229 #else
00230   int rid = -1;
00231   char buf[1024];
00232 
00233   /* Create a resolver */
00234   if (sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0) {
00235     DEBUG(net, 0, "[NET] Error connecting resolver");
00236     return 0;
00237   }
00238 
00239   /* Try to resolve the name */
00240   if (sceNetResolverStartNtoA(rid, hostname, &addr, 2, 3) < 0) {
00241     DEBUG(net, 0, "[NET] Cannot resolve %s", hostname);
00242     sceNetResolverDelete(rid);
00243     return 0;
00244   }
00245   sceNetResolverDelete(rid);
00246 #endif /* PSP */
00247 
00248   DEBUG(net, 1, "[NET] Resolved %s to %s", hostname, inet_ntoa(addr));
00249   ip = addr.s_addr;
00250   return ip;
00251 }
00252 
00253 #endif /* ENABLE_NETWORK */

Generated on Sun Nov 15 15:40:12 2009 for OpenTTD by  doxygen 1.5.6