Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/programs/ipconfig/ipconfig.c
4389 views
1
/*
2
* IP configuration utility
3
*
4
* Copyright 2008 Andrew Riedi
5
* Copyright 2010 Andrew Nguyen
6
*
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20
*/
21
22
#include <stdio.h>
23
#include <winsock2.h>
24
#include <windows.h>
25
#include <iphlpapi.h>
26
27
#include "ipconfig.h"
28
29
static int ipconfig_vprintfW(const WCHAR *msg, va_list va_args)
30
{
31
int wlen;
32
DWORD count;
33
WCHAR msg_buffer[8192];
34
35
wlen = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, msg_buffer,
36
ARRAY_SIZE(msg_buffer), &va_args);
37
38
if (!WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), msg_buffer, wlen, &count, NULL))
39
{
40
DWORD len;
41
char *msgA;
42
43
/* On Windows WriteConsoleW() fails if the output is redirected. So fall
44
* back to WriteFile() with OEM code page.
45
*/
46
len = WideCharToMultiByte(GetOEMCP(), 0, msg_buffer, wlen,
47
NULL, 0, NULL, NULL);
48
msgA = malloc(len);
49
if (!msgA)
50
return 0;
51
52
WideCharToMultiByte(GetOEMCP(), 0, msg_buffer, wlen, msgA, len, NULL, NULL);
53
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE);
54
free(msgA);
55
}
56
57
return count;
58
}
59
60
static int WINAPIV ipconfig_printfW(const WCHAR *msg, ...)
61
{
62
va_list va_args;
63
int len;
64
65
va_start(va_args, msg);
66
len = ipconfig_vprintfW(msg, va_args);
67
va_end(va_args);
68
69
return len;
70
}
71
72
static int WINAPIV ipconfig_message_printfW(int msg, ...)
73
{
74
va_list va_args;
75
WCHAR msg_buffer[8192];
76
int len;
77
78
LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
79
80
va_start(va_args, msg);
81
len = ipconfig_vprintfW(msg_buffer, va_args);
82
va_end(va_args);
83
84
return len;
85
}
86
87
static int ipconfig_message(int msg)
88
{
89
WCHAR msg_buffer[8192];
90
91
LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
92
93
return ipconfig_printfW(L"%1", msg_buffer);
94
}
95
96
static const WCHAR *iftype_to_string(DWORD type)
97
{
98
static WCHAR msg_buffer[50];
99
100
int msg;
101
102
switch (type)
103
{
104
case IF_TYPE_ETHERNET_CSMACD:
105
/* The loopback adapter appears as an Ethernet device. */
106
case IF_TYPE_SOFTWARE_LOOPBACK:
107
msg = STRING_ETHERNET;
108
break;
109
default:
110
msg = STRING_UNKNOWN;
111
}
112
113
LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
114
115
return msg_buffer;
116
}
117
118
static void print_field(int msg, const WCHAR *value)
119
{
120
WCHAR field[] = L". . . . . . . . . . . . . . . . . ";
121
WCHAR name_buffer[ARRAY_SIZE(field)];
122
123
LoadStringW(GetModuleHandleW(NULL), msg, name_buffer, ARRAY_SIZE(name_buffer));
124
memcpy(field, name_buffer, sizeof(WCHAR) * min(lstrlenW(name_buffer), ARRAY_SIZE(field) - 1));
125
126
ipconfig_printfW(L" %1: %2\n", field, value);
127
}
128
129
static void print_value(const WCHAR *value)
130
{
131
ipconfig_printfW(L" %1\n", value);
132
}
133
134
static BOOL socket_address_to_string(WCHAR *buf, DWORD len, SOCKET_ADDRESS *addr)
135
{
136
return WSAAddressToStringW(addr->lpSockaddr,
137
addr->iSockaddrLength, NULL,
138
buf, &len) == 0;
139
}
140
141
static IP_ADAPTER_ADDRESSES *get_adapters(void)
142
{
143
ULONG err, size = 4096;
144
IP_ADAPTER_ADDRESSES *tmp, *ret;
145
146
if (!(ret = malloc( size ))) return NULL;
147
err = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_INCLUDE_GATEWAYS, NULL, ret, &size );
148
while (err == ERROR_BUFFER_OVERFLOW)
149
{
150
if (!(tmp = realloc( ret, size ))) break;
151
ret = tmp;
152
err = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_INCLUDE_GATEWAYS, NULL, ret, &size );
153
}
154
if (err == ERROR_SUCCESS) return ret;
155
free( ret );
156
return NULL;
157
}
158
159
static void print_basic_information(void)
160
{
161
IP_ADAPTER_ADDRESSES *adapters, *p;
162
163
adapters = get_adapters();
164
if (!adapters)
165
exit(1);
166
167
for (p = adapters; p; p = p->Next)
168
{
169
IP_ADAPTER_UNICAST_ADDRESS *addr;
170
IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
171
WCHAR addr_buf[54];
172
173
ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
174
ipconfig_printfW(L"\n");
175
print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
176
177
for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
178
{
179
if (addr->Address.lpSockaddr->sa_family == AF_INET &&
180
socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
181
print_field(STRING_IP_ADDRESS, addr_buf);
182
else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
183
socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
184
print_field(STRING_IP6_ADDRESS, addr_buf);
185
/* FIXME: Output corresponding subnet mask. */
186
}
187
188
if (p->FirstGatewayAddress)
189
{
190
if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &p->FirstGatewayAddress->Address))
191
print_field(STRING_DEFAULT_GATEWAY, addr_buf);
192
193
for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
194
{
195
if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &gateway->Address))
196
print_value(addr_buf);
197
}
198
}
199
else
200
print_field(STRING_DEFAULT_GATEWAY, L"");
201
202
ipconfig_printfW(L"\n");
203
}
204
free(adapters);
205
}
206
207
static const WCHAR *nodetype_to_string(DWORD type)
208
{
209
static WCHAR msg_buffer[50];
210
211
int msg;
212
213
switch (type)
214
{
215
case BROADCAST_NODETYPE:
216
msg = STRING_BROADCAST;
217
break;
218
case PEER_TO_PEER_NODETYPE:
219
msg = STRING_PEER_TO_PEER;
220
break;
221
case MIXED_NODETYPE:
222
msg = STRING_MIXED;
223
break;
224
case HYBRID_NODETYPE:
225
msg = STRING_HYBRID;
226
break;
227
default:
228
msg = STRING_UNKNOWN;
229
}
230
231
LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
232
233
return msg_buffer;
234
}
235
236
static WCHAR *physaddr_to_string(WCHAR *buf, BYTE *addr, DWORD len)
237
{
238
if (!len)
239
*buf = '\0';
240
else
241
{
242
WCHAR *p = buf;
243
DWORD i;
244
245
for (i = 0; i < len - 1; i++)
246
{
247
swprintf(p, 4, L"%02X-", addr[i]);
248
p += 3;
249
}
250
swprintf(p, 3, L"%02X", addr[i]);
251
}
252
253
return buf;
254
}
255
256
static const WCHAR *boolean_to_string(int value)
257
{
258
static WCHAR msg_buffer[15];
259
260
LoadStringW(GetModuleHandleW(NULL), value ? STRING_YES : STRING_NO,
261
msg_buffer, ARRAY_SIZE(msg_buffer));
262
263
return msg_buffer;
264
}
265
266
static void print_full_information(void)
267
{
268
FIXED_INFO *info;
269
IP_ADAPTER_ADDRESSES *adapters, *p;
270
ULONG out;
271
272
if (GetNetworkParams(NULL, &out) == ERROR_BUFFER_OVERFLOW)
273
{
274
info = malloc(out);
275
if (!info)
276
exit(1);
277
278
if (GetNetworkParams(info, &out) == ERROR_SUCCESS)
279
{
280
WCHAR hostnameW[MAX_HOSTNAME_LEN + 4];
281
WCHAR dnssuffixW[MAX_DOMAIN_NAME_LEN + 4];
282
283
MultiByteToWideChar(CP_ACP, 0, info->HostName, -1, hostnameW, ARRAY_SIZE(hostnameW));
284
print_field(STRING_HOSTNAME, hostnameW);
285
286
MultiByteToWideChar(CP_ACP, 0, info->DomainName, -1, dnssuffixW, ARRAY_SIZE(dnssuffixW));
287
print_field(STRING_PRIMARY_DNS_SUFFIX, dnssuffixW);
288
289
print_field(STRING_NODE_TYPE, nodetype_to_string(info->NodeType));
290
print_field(STRING_IP_ROUTING, boolean_to_string(info->EnableRouting));
291
292
/* FIXME: Output WINS proxy status and DNS suffix search list. */
293
294
ipconfig_printfW(L"\n");
295
}
296
297
free(info);
298
}
299
300
adapters = get_adapters();
301
if (!adapters)
302
exit(1);
303
304
for (p = adapters; p; p = p->Next)
305
{
306
IP_ADAPTER_UNICAST_ADDRESS *addr;
307
WCHAR physaddr_buf[3 * MAX_ADAPTER_ADDRESS_LENGTH], addr_buf[54];
308
IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
309
310
ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
311
ipconfig_printfW(L"\n");
312
print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
313
print_field(STRING_DESCRIPTION, p->Description);
314
print_field(STRING_PHYS_ADDR, physaddr_to_string(physaddr_buf, p->PhysicalAddress, p->PhysicalAddressLength));
315
print_field(STRING_DHCP_ENABLED, boolean_to_string(p->Flags & IP_ADAPTER_DHCP_ENABLED));
316
317
/* FIXME: Output autoconfiguration status. */
318
319
for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
320
{
321
if (addr->Address.lpSockaddr->sa_family == AF_INET &&
322
socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
323
print_field(STRING_IP_ADDRESS, addr_buf);
324
else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
325
socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
326
print_field(STRING_IP6_ADDRESS, addr_buf);
327
/* FIXME: Output corresponding subnet mask. */
328
}
329
330
if (p->FirstGatewayAddress)
331
{
332
if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &p->FirstGatewayAddress->Address))
333
print_field(STRING_DEFAULT_GATEWAY, addr_buf);
334
335
for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
336
{
337
if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &gateway->Address))
338
print_value(addr_buf);
339
}
340
}
341
else
342
print_field(STRING_DEFAULT_GATEWAY, L"");
343
344
ipconfig_printfW(L"\n");
345
}
346
free(adapters);
347
}
348
349
int __cdecl wmain(int argc, WCHAR *argv[])
350
{
351
WSADATA data;
352
353
if (WSAStartup(MAKEWORD(2, 2), &data))
354
return 1;
355
356
if (argc > 1)
357
{
358
if (!lstrcmpW(L"/?", argv[1]))
359
{
360
ipconfig_message(STRING_USAGE);
361
WSACleanup();
362
return 1;
363
}
364
else if (!wcsicmp(L"/all", argv[1]))
365
{
366
if (argv[2])
367
{
368
ipconfig_message(STRING_INVALID_CMDLINE);
369
ipconfig_message(STRING_USAGE);
370
WSACleanup();
371
return 1;
372
}
373
374
print_full_information();
375
}
376
else
377
{
378
ipconfig_message(STRING_INVALID_CMDLINE);
379
ipconfig_message(STRING_USAGE);
380
WSACleanup();
381
return 1;
382
}
383
}
384
else
385
print_basic_information();
386
387
WSACleanup();
388
return 0;
389
}
390
391