ws2_32: Use getifaddrs() and if_nametoindex() directly in interface_bind().
[wine.git] / programs / ipconfig / ipconfig.c
bloba056771128ca2b9582b90ede7d2cbcd90e4fb0fe
1 /*
2 * IP configuration utility
4 * Copyright 2008 Andrew Riedi
5 * Copyright 2010 Andrew Nguyen
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.
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.
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
22 #define NONAMELESSUNION
24 #include <stdio.h>
25 #include <winsock2.h>
26 #include <windows.h>
27 #include <iphlpapi.h>
29 #include "ipconfig.h"
31 static int ipconfig_vprintfW(const WCHAR *msg, __ms_va_list va_args)
33 int wlen;
34 DWORD count, ret;
35 WCHAR msg_buffer[8192];
37 wlen = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, msg_buffer,
38 ARRAY_SIZE(msg_buffer), &va_args);
40 ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), msg_buffer, wlen, &count, NULL);
41 if (!ret)
43 DWORD len;
44 char *msgA;
46 /* On Windows WriteConsoleW() fails if the output is redirected. So fall
47 * back to WriteFile(), assuming the console encoding is still the right
48 * one in that case.
50 len = WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer, wlen,
51 NULL, 0, NULL, NULL);
52 msgA = HeapAlloc(GetProcessHeap(), 0, len);
53 if (!msgA)
54 return 0;
56 WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer, wlen, msgA, len,
57 NULL, NULL);
58 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE);
59 HeapFree(GetProcessHeap(), 0, msgA);
62 return count;
65 static int WINAPIV ipconfig_printfW(const WCHAR *msg, ...)
67 __ms_va_list va_args;
68 int len;
70 __ms_va_start(va_args, msg);
71 len = ipconfig_vprintfW(msg, va_args);
72 __ms_va_end(va_args);
74 return len;
77 static int WINAPIV ipconfig_message_printfW(int msg, ...)
79 __ms_va_list va_args;
80 WCHAR msg_buffer[8192];
81 int len;
83 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
85 __ms_va_start(va_args, msg);
86 len = ipconfig_vprintfW(msg_buffer, va_args);
87 __ms_va_end(va_args);
89 return len;
92 static int ipconfig_message(int msg)
94 WCHAR msg_buffer[8192];
96 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
98 return ipconfig_printfW(L"%1", msg_buffer);
101 static const WCHAR *iftype_to_string(DWORD type)
103 static WCHAR msg_buffer[50];
105 int msg;
107 switch (type)
109 case IF_TYPE_ETHERNET_CSMACD:
110 /* The loopback adapter appears as an Ethernet device. */
111 case IF_TYPE_SOFTWARE_LOOPBACK:
112 msg = STRING_ETHERNET;
113 break;
114 default:
115 msg = STRING_UNKNOWN;
118 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
120 return msg_buffer;
123 static void print_field(int msg, const WCHAR *value)
125 WCHAR field[] = L". . . . . . . . . . . . . . . . . ";
126 WCHAR name_buffer[ARRAY_SIZE(field)];
128 LoadStringW(GetModuleHandleW(NULL), msg, name_buffer, ARRAY_SIZE(name_buffer));
129 memcpy(field, name_buffer, sizeof(WCHAR) * min(lstrlenW(name_buffer), ARRAY_SIZE(field) - 1));
131 ipconfig_printfW(L" %1: %2\n", field, value);
134 static void print_value(const WCHAR *value)
136 ipconfig_printfW(L" %1\n", value);
139 static BOOL socket_address_to_string(WCHAR *buf, DWORD len, SOCKET_ADDRESS *addr)
141 return WSAAddressToStringW(addr->lpSockaddr,
142 addr->iSockaddrLength, NULL,
143 buf, &len) == 0;
146 static void print_basic_information(void)
148 IP_ADAPTER_ADDRESSES *adapters;
149 ULONG out = 0;
151 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
152 NULL, NULL, &out) == ERROR_BUFFER_OVERFLOW)
154 adapters = HeapAlloc(GetProcessHeap(), 0, out);
155 if (!adapters)
156 exit(1);
158 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
159 NULL, adapters, &out) == ERROR_SUCCESS)
161 IP_ADAPTER_ADDRESSES *p;
163 for (p = adapters; p; p = p->Next)
165 IP_ADAPTER_UNICAST_ADDRESS *addr;
166 IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
167 WCHAR addr_buf[54];
169 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
170 ipconfig_printfW(L"\n");
171 print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
173 for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
175 if (addr->Address.lpSockaddr->sa_family == AF_INET &&
176 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
177 print_field(STRING_IP_ADDRESS, addr_buf);
178 else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
179 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
180 print_field(STRING_IP6_ADDRESS, addr_buf);
181 /* FIXME: Output corresponding subnet mask. */
184 if (p->FirstGatewayAddress)
186 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &p->FirstGatewayAddress->Address))
187 print_field(STRING_DEFAULT_GATEWAY, addr_buf);
189 for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
191 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &gateway->Address))
192 print_value(addr_buf);
195 else
196 print_field(STRING_DEFAULT_GATEWAY, L"");
198 ipconfig_printfW(L"\n");
202 HeapFree(GetProcessHeap(), 0, adapters);
206 static const WCHAR *nodetype_to_string(DWORD type)
208 static WCHAR msg_buffer[50];
210 int msg;
212 switch (type)
214 case BROADCAST_NODETYPE:
215 msg = STRING_BROADCAST;
216 break;
217 case PEER_TO_PEER_NODETYPE:
218 msg = STRING_PEER_TO_PEER;
219 break;
220 case MIXED_NODETYPE:
221 msg = STRING_MIXED;
222 break;
223 case HYBRID_NODETYPE:
224 msg = STRING_HYBRID;
225 break;
226 default:
227 msg = STRING_UNKNOWN;
230 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
232 return msg_buffer;
235 static WCHAR *physaddr_to_string(WCHAR *buf, BYTE *addr, DWORD len)
237 if (!len)
238 *buf = '\0';
239 else
241 WCHAR *p = buf;
242 DWORD i;
244 for (i = 0; i < len - 1; i++)
246 swprintf(p, 4, L"%02X-", addr[i]);
247 p += 3;
249 swprintf(p, 3, L"%02X", addr[i]);
252 return buf;
255 static const WCHAR *boolean_to_string(int value)
257 static WCHAR msg_buffer[15];
259 LoadStringW(GetModuleHandleW(NULL), value ? STRING_YES : STRING_NO,
260 msg_buffer, ARRAY_SIZE(msg_buffer));
262 return msg_buffer;
265 static void print_full_information(void)
267 FIXED_INFO *info;
268 IP_ADAPTER_ADDRESSES *adapters;
269 ULONG out = 0;
271 if (GetNetworkParams(NULL, &out) == ERROR_BUFFER_OVERFLOW)
273 info = HeapAlloc(GetProcessHeap(), 0, out);
274 if (!info)
275 exit(1);
277 if (GetNetworkParams(info, &out) == ERROR_SUCCESS)
279 WCHAR hostnameW[MAX_HOSTNAME_LEN + 4];
281 MultiByteToWideChar(CP_ACP, 0, info->HostName, -1, hostnameW, ARRAY_SIZE(hostnameW));
282 print_field(STRING_HOSTNAME, hostnameW);
284 /* FIXME: Output primary DNS suffix. */
286 print_field(STRING_NODE_TYPE, nodetype_to_string(info->NodeType));
287 print_field(STRING_IP_ROUTING, boolean_to_string(info->EnableRouting));
289 /* FIXME: Output WINS proxy status and DNS suffix search list. */
291 ipconfig_printfW(L"\n");
294 HeapFree(GetProcessHeap(), 0, info);
297 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
298 NULL, NULL, &out) == ERROR_BUFFER_OVERFLOW)
300 adapters = HeapAlloc(GetProcessHeap(), 0, out);
301 if (!adapters)
302 exit(1);
304 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
305 NULL, adapters, &out) == ERROR_SUCCESS)
307 IP_ADAPTER_ADDRESSES *p;
309 for (p = adapters; p; p = p->Next)
311 IP_ADAPTER_UNICAST_ADDRESS *addr;
312 WCHAR physaddr_buf[3 * MAX_ADAPTER_ADDRESS_LENGTH];
313 IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
314 WCHAR addr_buf[54];
316 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
317 ipconfig_printfW(L"\n");
318 print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
319 print_field(STRING_DESCRIPTION, p->Description);
320 print_field(STRING_PHYS_ADDR, physaddr_to_string(physaddr_buf, p->PhysicalAddress, p->PhysicalAddressLength));
321 print_field(STRING_DHCP_ENABLED, boolean_to_string(p->u1.Flags & IP_ADAPTER_DHCP_ENABLED));
323 /* FIXME: Output autoconfiguration status. */
325 for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
327 if (addr->Address.lpSockaddr->sa_family == AF_INET &&
328 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
329 print_field(STRING_IP_ADDRESS, addr_buf);
330 else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
331 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
332 print_field(STRING_IP6_ADDRESS, addr_buf);
333 /* FIXME: Output corresponding subnet mask. */
336 if (p->FirstGatewayAddress)
338 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &p->FirstGatewayAddress->Address))
339 print_field(STRING_DEFAULT_GATEWAY, addr_buf);
341 for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
343 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &gateway->Address))
344 print_value(addr_buf);
347 else
348 print_field(STRING_DEFAULT_GATEWAY, L"");
350 ipconfig_printfW(L"\n");
354 HeapFree(GetProcessHeap(), 0, adapters);
358 int __cdecl wmain(int argc, WCHAR *argv[])
360 WSADATA data;
362 if (WSAStartup(MAKEWORD(2, 2), &data))
363 return 1;
365 if (argc > 1)
367 if (!lstrcmpW(L"/?", argv[1]))
369 ipconfig_message(STRING_USAGE);
370 WSACleanup();
371 return 1;
373 else if (!wcsicmp(L"/all", argv[1]))
375 if (argv[2])
377 ipconfig_message(STRING_INVALID_CMDLINE);
378 ipconfig_message(STRING_USAGE);
379 WSACleanup();
380 return 1;
383 print_full_information();
385 else
387 ipconfig_message(STRING_INVALID_CMDLINE);
388 ipconfig_message(STRING_USAGE);
389 WSACleanup();
390 return 1;
393 else
394 print_basic_information();
396 WSACleanup();
397 return 0;