~ubuntu-branches/debian/squeeze/openttd/squeeze

« back to all changes in this revision

Viewing changes to src/network/core/host.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jordi Mallach, Matthijs Kooijman, Jordi Mallach
  • Date: 2009-04-15 18:22:10 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090415182210-22ktb8kdbp2tf3bm
[ Matthijs Kooijman ]
* New upstream release.
* Remove Debian specific desktop file, upstream provides one now. 
* Add debian/watch file.

[ Jordi Mallach ]
* Bump Standards-Version to 3.8.1, with no changes required.
* Move to debhelper compat 7. Bump Build-Depends accordingly.
* Use dh_prep.
* Add "set -e" to config script.
* Remove a few extra doc files that get installed by upstream Makefile.
* Add more complete copyright information.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: host.cpp 15718 2009-03-15 00:32:18Z rubidium $ */
 
2
 
 
3
/** @file host.cpp Functions related to getting host specific data (IPs). */
 
4
 
 
5
#ifdef ENABLE_NETWORK
 
6
 
 
7
#include "../../stdafx.h"
 
8
#include "../../debug.h"
 
9
#include "os_abstraction.h"
 
10
#include "../../core/alloc_func.hpp"
 
11
 
 
12
/**
 
13
 * Internal implementation for finding the broadcast IPs.
 
14
 * This function is implemented multiple times for multiple targets.
 
15
 * @param broadcast the list of broadcasts to write into.
 
16
 * @param limit     the maximum number of items to add.
 
17
 */
 
18
static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit);
 
19
 
 
20
#if defined(PSP)
 
21
static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // PSP implementation
 
22
{
 
23
        return 0;
 
24
}
 
25
 
 
26
#elif defined(BEOS_NET_SERVER) /* doesn't have neither getifaddrs or net/if.h */
 
27
/* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */
 
28
int _netstat(int fd, char **output, int verbose);
 
29
 
 
30
int seek_past_header(char **pos, const char *header)
 
31
{
 
32
        char *new_pos = strstr(*pos, header);
 
33
        if (new_pos == 0) {
 
34
                return B_ERROR;
 
35
        }
 
36
        *pos += strlen(header) + new_pos - *pos + 1;
 
37
        return B_OK;
 
38
}
 
39
 
 
40
static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // BEOS implementation
 
41
{
 
42
        int sock = socket(AF_INET, SOCK_DGRAM, 0);
 
43
 
 
44
        if (sock < 0) {
 
45
                DEBUG(net, 0, "[core] error creating socket");
 
46
                return 0;
 
47
        }
 
48
 
 
49
        char *output_pointer = NULL;
 
50
        int output_length = _netstat(sock, &output_pointer, 1);
 
51
        if (output_length < 0) {
 
52
                DEBUG(net, 0, "[core] error running _netstat");
 
53
                return 0;
 
54
        }
 
55
 
 
56
        int index;
 
57
        char **output = &output_pointer;
 
58
        if (seek_past_header(output, "IP Interfaces:") == B_OK) {
 
59
                while (index != limit) {
 
60
 
 
61
                        uint32 n, fields, read;
 
62
                        uint8 i1, i2, i3, i4, j1, j2, j3, j4;
 
63
                        struct in_addr inaddr;
 
64
                        uint32 ip;
 
65
                        uint32 netmask;
 
66
 
 
67
                        fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n",
 
68
                                                                                                &n, &i1, &i2, &i3, &i4, &j1, &j2, &j3, &j4, &read);
 
69
                        read += 1;
 
70
                        if (fields != 9) {
 
71
                                break;
 
72
                        }
 
73
 
 
74
                        ip      = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4;
 
75
                        netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4;
 
76
 
 
77
                        if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) {
 
78
                                inaddr.s_addr = htonl(ip | ~netmask);
 
79
                                broadcast[index] = inaddr.s_addr;
 
80
                                index++;
 
81
                        }
 
82
                        if (read < 0) {
 
83
                                break;
 
84
                        }
 
85
                        *output += read;
 
86
                }
 
87
                closesocket(sock);
 
88
        }
 
89
 
 
90
        return index;
 
91
}
 
92
 
 
93
#elif defined(HAVE_GETIFADDRS)
 
94
static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // GETIFADDRS implementation
 
95
{
 
96
        struct ifaddrs *ifap, *ifa;
 
97
 
 
98
        if (getifaddrs(&ifap) != 0) return 0;
 
99
 
 
100
        int index = 0;
 
101
        for (ifa = ifap; ifa != NULL && index != limit; ifa = ifa->ifa_next) {
 
102
                if (!(ifa->ifa_flags & IFF_BROADCAST)) continue;
 
103
                if (ifa->ifa_broadaddr == NULL) continue;
 
104
                if (ifa->ifa_broadaddr->sa_family != AF_INET) continue;
 
105
 
 
106
                broadcast[index] = ((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr;
 
107
                index++;
 
108
        }
 
109
        freeifaddrs(ifap);
 
110
 
 
111
        return index;
 
112
}
 
113
 
 
114
#elif defined(WIN32)
 
115
static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // Win32 implementation
 
116
{
 
117
        SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
 
118
        if (sock == INVALID_SOCKET) return 0;
 
119
 
 
120
        DWORD len = 0;
 
121
        INTERFACE_INFO *ifo = AllocaM(INTERFACE_INFO, limit);
 
122
        memset(ifo, 0, limit * sizeof(*ifo));
 
123
        if ((WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, &ifo[0], limit * sizeof(*ifo), &len, NULL, NULL)) != 0) {
 
124
                closesocket(sock);
 
125
                return 0;
 
126
        }
 
127
 
 
128
        int index = 0;
 
129
        for (uint j = 0; j < len / sizeof(*ifo) && index != limit; j++) {
 
130
                if (ifo[j].iiFlags & IFF_LOOPBACK) continue;
 
131
                if (!(ifo[j].iiFlags & IFF_BROADCAST)) continue;
 
132
 
 
133
                /* iiBroadcast is unusable, because it always seems to be set to 255.255.255.255. */
 
134
                broadcast[index++] = ifo[j].iiAddress.AddressIn.sin_addr.s_addr | ~ifo[j].iiNetmask.AddressIn.sin_addr.s_addr;
 
135
        }
 
136
 
 
137
        closesocket(sock);
 
138
        return index;
 
139
}
 
140
 
 
141
#else /* not HAVE_GETIFADDRS */
 
142
 
 
143
#include "../../string_func.h"
 
144
 
 
145
static int NetworkFindBroadcastIPsInternal(uint32 *broadcast, int limit) // !GETIFADDRS implementation
 
146
{
 
147
        SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
 
148
        if (sock == INVALID_SOCKET) return 0;
 
149
 
 
150
        char buf[4 * 1024]; // Arbitrary buffer size
 
151
        struct ifconf ifconf;
 
152
 
 
153
        ifconf.ifc_len = sizeof(buf);
 
154
        ifconf.ifc_buf = buf;
 
155
        if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1) {
 
156
                closesocket(sock);
 
157
                return 0;
 
158
        }
 
159
 
 
160
        const char *buf_end = buf + ifconf.ifc_len;
 
161
        int index = 0;
 
162
        for (const char *p = buf; p < buf_end && index != limit;) {
 
163
                const struct ifreq *req = (const struct ifreq*)p;
 
164
 
 
165
                if (req->ifr_addr.sa_family == AF_INET) {
 
166
                        struct ifreq r;
 
167
 
 
168
                        strecpy(r.ifr_name, req->ifr_name, lastof(r.ifr_name));
 
169
                        if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 &&
 
170
                                        r.ifr_flags & IFF_BROADCAST &&
 
171
                                        ioctl(sock, SIOCGIFBRDADDR, &r) != -1) {
 
172
                                broadcast[index++] = ((struct sockaddr_in*)&r.ifr_broadaddr)->sin_addr.s_addr;
 
173
                        }
 
174
                }
 
175
 
 
176
                p += sizeof(struct ifreq);
 
177
#if defined(AF_LINK) && !defined(SUNOS)
 
178
                p += req->ifr_addr.sa_len - sizeof(struct sockaddr);
 
179
#endif
 
180
        }
 
181
 
 
182
        closesocket(sock);
 
183
 
 
184
        return index;
 
185
}
 
186
#endif /* all NetworkFindBroadcastIPsInternals */
 
187
 
 
188
/**
 
189
 * Find the IPs to broadcast.
 
190
 * @param broadcast the list of broadcasts to write into.
 
191
 * @param limit     the maximum number of items to add.
 
192
 */
 
193
void NetworkFindBroadcastIPs(uint32 *broadcast, int limit)
 
194
{
 
195
        int count = NetworkFindBroadcastIPsInternal(broadcast, limit);
 
196
 
 
197
        /* Make sure the list is terminated. */
 
198
        broadcast[count] = 0;
 
199
 
 
200
        /* Now display to the debug all the detected ips */
 
201
        DEBUG(net, 3, "Detected broadcast addresses:");
 
202
        for (int i = 0; broadcast[i] != 0; i++) {
 
203
                DEBUG(net, 3, "%d) %s", i, inet_ntoa(*(struct in_addr *)&broadcast[i])); // inet_ntoa(inaddr));
 
204
        }
 
205
}
 
206
 
 
207
 
 
208
/**
 
209
 * Resolve a hostname to an ip.
 
210
 * @param hsotname the hostname to resolve
 
211
 * @return the IP belonging to that hostname, or 0 on failure.
 
212
 */
 
213
uint32 NetworkResolveHost(const char *hostname)
 
214
{
 
215
        /* Is this an IP address? */
 
216
        in_addr_t ip = inet_addr(hostname);
 
217
 
 
218
        if (ip != INADDR_NONE) return ip;
 
219
 
 
220
        /* No, try to resolve the name */
 
221
        struct in_addr addr;
 
222
#if !defined(PSP)
 
223
        struct hostent *he = gethostbyname(hostname);
 
224
        if (he == NULL) {
 
225
                DEBUG(net, 0, "[NET] Cannot resolve %s", hostname);
 
226
                return 0;
 
227
        }
 
228
        addr = *(struct in_addr *)he->h_addr_list[0];
 
229
#else
 
230
        int rid = -1;
 
231
        char buf[1024];
 
232
 
 
233
        /* Create a resolver */
 
234
        if (sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0) {
 
235
                DEBUG(net, 0, "[NET] Error connecting resolver");
 
236
                return 0;
 
237
        }
 
238
 
 
239
        /* Try to resolve the name */
 
240
        if (sceNetResolverStartNtoA(rid, hostname, &addr, 2, 3) < 0) {
 
241
                DEBUG(net, 0, "[NET] Cannot resolve %s", hostname);
 
242
                sceNetResolverDelete(rid);
 
243
                return 0;
 
244
        }
 
245
        sceNetResolverDelete(rid);
 
246
#endif /* PSP */
 
247
 
 
248
        DEBUG(net, 1, "[NET] Resolved %s to %s", hostname, inet_ntoa(addr));
 
249
        ip = addr.s_addr;
 
250
        return ip;
 
251
}
 
252
 
 
253
#endif /* ENABLE_NETWORK */