00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifdef ENABLE_NETWORK
00013
00014 #include "../../stdafx.h"
00015 #include "../../debug.h"
00016 #include "address.h"
00017
00023 static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast);
00024
00025 #if defined(PSP)
00026 static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast)
00027 {
00028 }
00029
00030 #elif defined(BEOS_NET_SERVER) || defined(__HAIKU__)
00031
00032 extern "C" int _netstat(int fd, char **output, int verbose);
00033
00034 int seek_past_header(char **pos, const char *header)
00035 {
00036 char *new_pos = strstr(*pos, header);
00037 if (new_pos == 0) {
00038 return B_ERROR;
00039 }
00040 *pos += strlen(header) + new_pos - *pos + 1;
00041 return B_OK;
00042 }
00043
00044 static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast)
00045 {
00046 int sock = socket(AF_INET, SOCK_DGRAM, 0);
00047
00048 if (sock < 0) {
00049 DEBUG(net, 0, "[core] error creating socket");
00050 return;
00051 }
00052
00053 char *output_pointer = NULL;
00054 int output_length = _netstat(sock, &output_pointer, 1);
00055 if (output_length < 0) {
00056 DEBUG(net, 0, "[core] error running _netstat");
00057 return;
00058 }
00059
00060 char **output = &output_pointer;
00061 if (seek_past_header(output, "IP Interfaces:") == B_OK) {
00062 for (;;) {
00063 uint32 n;
00064 int fields, read;
00065 uint8 i1, i2, i3, i4, j1, j2, j3, j4;
00066 uint32 ip;
00067 uint32 netmask;
00068
00069 fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n",
00070 &n, &i1, &i2, &i3, &i4, &j1, &j2, &j3, &j4, &read);
00071 read += 1;
00072 if (fields != 9) {
00073 break;
00074 }
00075
00076 ip = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4;
00077 netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4;
00078
00079 if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) {
00080 sockaddr_storage address;
00081 memset(&address, 0, sizeof(address));
00082 ((sockaddr_in*)&address)->sin_addr.s_addr = htonl(ip | ~netmask);
00083 NetworkAddress addr(address, sizeof(sockaddr));
00084 if (!broadcast->Contains(addr)) *broadcast->Append() = addr;
00085 }
00086 if (read < 0) {
00087 break;
00088 }
00089 *output += read;
00090 }
00091 closesocket(sock);
00092 }
00093 }
00094
00095 #elif defined(HAVE_GETIFADDRS)
00096 static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast)
00097 {
00098 struct ifaddrs *ifap, *ifa;
00099
00100 if (getifaddrs(&ifap) != 0) return;
00101
00102 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
00103 if (!(ifa->ifa_flags & IFF_BROADCAST)) continue;
00104 if (ifa->ifa_broadaddr == NULL) continue;
00105 if (ifa->ifa_broadaddr->sa_family != AF_INET) continue;
00106
00107 NetworkAddress addr(ifa->ifa_broadaddr, sizeof(sockaddr));
00108 if (!broadcast->Contains(addr)) *broadcast->Append() = addr;
00109 }
00110 freeifaddrs(ifap);
00111 }
00112
00113 #elif defined(WIN32)
00114 static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast)
00115 {
00116 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
00117 if (sock == INVALID_SOCKET) return;
00118
00119 DWORD len = 0;
00120 int num = 2;
00121 INTERFACE_INFO *ifo = CallocT<INTERFACE_INFO>(num);
00122
00123 for (;;) {
00124 if (WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, ifo, num * sizeof(*ifo), &len, NULL, NULL) == 0) break;
00125 free(ifo);
00126 if (WSAGetLastError() != WSAEFAULT) {
00127 closesocket(sock);
00128 return;
00129 }
00130 num *= 2;
00131 ifo = CallocT<INTERFACE_INFO>(num);
00132 }
00133
00134 for (uint j = 0; j < len / sizeof(*ifo); j++) {
00135 if (ifo[j].iiFlags & IFF_LOOPBACK) continue;
00136 if (!(ifo[j].iiFlags & IFF_BROADCAST)) continue;
00137
00138 sockaddr_storage address;
00139 memset(&address, 0, sizeof(address));
00140
00141 memcpy(&address, &ifo[j].iiAddress.Address, sizeof(sockaddr));
00142 ((sockaddr_in*)&address)->sin_addr.s_addr = ifo[j].iiAddress.AddressIn.sin_addr.s_addr | ~ifo[j].iiNetmask.AddressIn.sin_addr.s_addr;
00143 NetworkAddress addr(address, sizeof(sockaddr));
00144 if (!broadcast->Contains(addr)) *broadcast->Append() = addr;
00145 }
00146
00147 free(ifo);
00148 closesocket(sock);
00149 }
00150
00151 #else
00152
00153 #include "../../string_func.h"
00154
00155 static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast)
00156 {
00157 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
00158 if (sock == INVALID_SOCKET) return;
00159
00160 char buf[4 * 1024];
00161 struct ifconf ifconf;
00162
00163 ifconf.ifc_len = sizeof(buf);
00164 ifconf.ifc_buf = buf;
00165 if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1) {
00166 closesocket(sock);
00167 return;
00168 }
00169
00170 const char *buf_end = buf + ifconf.ifc_len;
00171 for (const char *p = buf; p < buf_end;) {
00172 const struct ifreq *req = (const struct ifreq*)p;
00173
00174 if (req->ifr_addr.sa_family == AF_INET) {
00175 struct ifreq r;
00176
00177 strecpy(r.ifr_name, req->ifr_name, lastof(r.ifr_name));
00178 if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 &&
00179 (r.ifr_flags & IFF_BROADCAST) &&
00180 ioctl(sock, SIOCGIFBRDADDR, &r) != -1) {
00181 NetworkAddress addr(&r.ifr_broadaddr, sizeof(sockaddr));
00182 if (!broadcast->Contains(addr)) *broadcast->Append() = addr;
00183 }
00184 }
00185
00186 p += sizeof(struct ifreq);
00187 #if defined(AF_LINK) && !defined(SUNOS)
00188 p += req->ifr_addr.sa_len - sizeof(struct sockaddr);
00189 #endif
00190 }
00191
00192 closesocket(sock);
00193 }
00194 #endif
00195
00201 void NetworkFindBroadcastIPs(NetworkAddressList *broadcast)
00202 {
00203 NetworkFindBroadcastIPsInternal(broadcast);
00204
00205
00206 DEBUG(net, 3, "Detected broadcast addresses:");
00207 int i = 0;
00208 for (NetworkAddress *addr = broadcast->Begin(); addr != broadcast->End(); addr++) {
00209 addr->SetPort(NETWORK_DEFAULT_PORT);
00210 DEBUG(net, 3, "%d) %s", i++, addr->GetHostname());
00211 }
00212 }
00213
00214 #endif