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
31 static int ipconfig_vprintfW(const WCHAR
*msg
, va_list va_args
)
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 if (!WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE
), msg_buffer
, wlen
, &count
, NULL
))
45 /* On Windows WriteConsoleW() fails if the output is redirected. So fall
46 * back to WriteFile() with OEM code page.
48 len
= WideCharToMultiByte(GetOEMCP(), 0, msg_buffer
, wlen
,
50 msgA
= HeapAlloc(GetProcessHeap(), 0, len
);
54 WideCharToMultiByte(GetOEMCP(), 0, msg_buffer
, wlen
, msgA
, len
, NULL
, NULL
);
55 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE
), msgA
, len
, &count
, FALSE
);
56 HeapFree(GetProcessHeap(), 0, msgA
);
62 static int WINAPIV
ipconfig_printfW(const WCHAR
*msg
, ...)
67 va_start(va_args
, msg
);
68 len
= ipconfig_vprintfW(msg
, va_args
);
74 static int WINAPIV
ipconfig_message_printfW(int msg
, ...)
77 WCHAR msg_buffer
[8192];
80 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
, ARRAY_SIZE(msg_buffer
));
82 va_start(va_args
, msg
);
83 len
= ipconfig_vprintfW(msg_buffer
, va_args
);
89 static int ipconfig_message(int msg
)
91 WCHAR msg_buffer
[8192];
93 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
, ARRAY_SIZE(msg_buffer
));
95 return ipconfig_printfW(L
"%1", msg_buffer
);
98 static const WCHAR
*iftype_to_string(DWORD type
)
100 static WCHAR msg_buffer
[50];
106 case IF_TYPE_ETHERNET_CSMACD
:
107 /* The loopback adapter appears as an Ethernet device. */
108 case IF_TYPE_SOFTWARE_LOOPBACK
:
109 msg
= STRING_ETHERNET
;
112 msg
= STRING_UNKNOWN
;
115 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
, ARRAY_SIZE(msg_buffer
));
120 static void print_field(int msg
, const WCHAR
*value
)
122 WCHAR field
[] = L
". . . . . . . . . . . . . . . . . ";
123 WCHAR name_buffer
[ARRAY_SIZE(field
)];
125 LoadStringW(GetModuleHandleW(NULL
), msg
, name_buffer
, ARRAY_SIZE(name_buffer
));
126 memcpy(field
, name_buffer
, sizeof(WCHAR
) * min(lstrlenW(name_buffer
), ARRAY_SIZE(field
) - 1));
128 ipconfig_printfW(L
" %1: %2\n", field
, value
);
131 static void print_value(const WCHAR
*value
)
133 ipconfig_printfW(L
" %1\n", value
);
136 static BOOL
socket_address_to_string(WCHAR
*buf
, DWORD len
, SOCKET_ADDRESS
*addr
)
138 return WSAAddressToStringW(addr
->lpSockaddr
,
139 addr
->iSockaddrLength
, NULL
,
143 static void print_basic_information(void)
145 IP_ADAPTER_ADDRESSES
*adapters
;
148 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
149 NULL
, NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
151 adapters
= HeapAlloc(GetProcessHeap(), 0, out
);
155 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
156 NULL
, adapters
, &out
) == ERROR_SUCCESS
)
158 IP_ADAPTER_ADDRESSES
*p
;
160 for (p
= adapters
; p
; p
= p
->Next
)
162 IP_ADAPTER_UNICAST_ADDRESS
*addr
;
163 IP_ADAPTER_GATEWAY_ADDRESS_LH
*gateway
;
166 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY
, iftype_to_string(p
->IfType
), p
->FriendlyName
);
167 ipconfig_printfW(L
"\n");
168 print_field(STRING_CONN_DNS_SUFFIX
, p
->DnsSuffix
);
170 for (addr
= p
->FirstUnicastAddress
; addr
; addr
= addr
->Next
)
172 if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET
&&
173 socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &addr
->Address
))
174 print_field(STRING_IP_ADDRESS
, addr_buf
);
175 else if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET6
&&
176 socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &addr
->Address
))
177 print_field(STRING_IP6_ADDRESS
, addr_buf
);
178 /* FIXME: Output corresponding subnet mask. */
181 if (p
->FirstGatewayAddress
)
183 if (socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &p
->FirstGatewayAddress
->Address
))
184 print_field(STRING_DEFAULT_GATEWAY
, addr_buf
);
186 for (gateway
= p
->FirstGatewayAddress
->Next
; gateway
; gateway
= gateway
->Next
)
188 if (socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &gateway
->Address
))
189 print_value(addr_buf
);
193 print_field(STRING_DEFAULT_GATEWAY
, L
"");
195 ipconfig_printfW(L
"\n");
199 HeapFree(GetProcessHeap(), 0, adapters
);
203 static const WCHAR
*nodetype_to_string(DWORD type
)
205 static WCHAR msg_buffer
[50];
211 case BROADCAST_NODETYPE
:
212 msg
= STRING_BROADCAST
;
214 case PEER_TO_PEER_NODETYPE
:
215 msg
= STRING_PEER_TO_PEER
;
220 case HYBRID_NODETYPE
:
224 msg
= STRING_UNKNOWN
;
227 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
, ARRAY_SIZE(msg_buffer
));
232 static WCHAR
*physaddr_to_string(WCHAR
*buf
, BYTE
*addr
, DWORD len
)
241 for (i
= 0; i
< len
- 1; i
++)
243 swprintf(p
, 4, L
"%02X-", addr
[i
]);
246 swprintf(p
, 3, L
"%02X", addr
[i
]);
252 static const WCHAR
*boolean_to_string(int value
)
254 static WCHAR msg_buffer
[15];
256 LoadStringW(GetModuleHandleW(NULL
), value
? STRING_YES
: STRING_NO
,
257 msg_buffer
, ARRAY_SIZE(msg_buffer
));
262 static void print_full_information(void)
265 IP_ADAPTER_ADDRESSES
*adapters
;
268 if (GetNetworkParams(NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
270 info
= HeapAlloc(GetProcessHeap(), 0, out
);
274 if (GetNetworkParams(info
, &out
) == ERROR_SUCCESS
)
276 WCHAR hostnameW
[MAX_HOSTNAME_LEN
+ 4];
277 WCHAR dnssuffixW
[MAX_DOMAIN_NAME_LEN
+ 4];
279 MultiByteToWideChar(CP_ACP
, 0, info
->HostName
, -1, hostnameW
, ARRAY_SIZE(hostnameW
));
280 print_field(STRING_HOSTNAME
, hostnameW
);
282 MultiByteToWideChar(CP_ACP
, 0, info
->DomainName
, -1, dnssuffixW
, ARRAY_SIZE(dnssuffixW
));
283 print_field(STRING_PRIMARY_DNS_SUFFIX
, dnssuffixW
);
285 print_field(STRING_NODE_TYPE
, nodetype_to_string(info
->NodeType
));
286 print_field(STRING_IP_ROUTING
, boolean_to_string(info
->EnableRouting
));
288 /* FIXME: Output WINS proxy status and DNS suffix search list. */
290 ipconfig_printfW(L
"\n");
293 HeapFree(GetProcessHeap(), 0, info
);
296 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
297 NULL
, NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
299 adapters
= HeapAlloc(GetProcessHeap(), 0, out
);
303 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
304 NULL
, adapters
, &out
) == ERROR_SUCCESS
)
306 IP_ADAPTER_ADDRESSES
*p
;
308 for (p
= adapters
; p
; p
= p
->Next
)
310 IP_ADAPTER_UNICAST_ADDRESS
*addr
;
311 WCHAR physaddr_buf
[3 * MAX_ADAPTER_ADDRESS_LENGTH
];
312 IP_ADAPTER_GATEWAY_ADDRESS_LH
*gateway
;
315 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY
, iftype_to_string(p
->IfType
), p
->FriendlyName
);
316 ipconfig_printfW(L
"\n");
317 print_field(STRING_CONN_DNS_SUFFIX
, p
->DnsSuffix
);
318 print_field(STRING_DESCRIPTION
, p
->Description
);
319 print_field(STRING_PHYS_ADDR
, physaddr_to_string(physaddr_buf
, p
->PhysicalAddress
, p
->PhysicalAddressLength
));
320 print_field(STRING_DHCP_ENABLED
, boolean_to_string(p
->u1
.Flags
& IP_ADAPTER_DHCP_ENABLED
));
322 /* FIXME: Output autoconfiguration status. */
324 for (addr
= p
->FirstUnicastAddress
; addr
; addr
= addr
->Next
)
326 if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET
&&
327 socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &addr
->Address
))
328 print_field(STRING_IP_ADDRESS
, addr_buf
);
329 else if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET6
&&
330 socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &addr
->Address
))
331 print_field(STRING_IP6_ADDRESS
, addr_buf
);
332 /* FIXME: Output corresponding subnet mask. */
335 if (p
->FirstGatewayAddress
)
337 if (socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &p
->FirstGatewayAddress
->Address
))
338 print_field(STRING_DEFAULT_GATEWAY
, addr_buf
);
340 for (gateway
= p
->FirstGatewayAddress
->Next
; gateway
; gateway
= gateway
->Next
)
342 if (socket_address_to_string(addr_buf
, ARRAY_SIZE(addr_buf
), &gateway
->Address
))
343 print_value(addr_buf
);
347 print_field(STRING_DEFAULT_GATEWAY
, L
"");
349 ipconfig_printfW(L
"\n");
353 HeapFree(GetProcessHeap(), 0, adapters
);
357 int __cdecl
wmain(int argc
, WCHAR
*argv
[])
361 if (WSAStartup(MAKEWORD(2, 2), &data
))
366 if (!lstrcmpW(L
"/?", argv
[1]))
368 ipconfig_message(STRING_USAGE
);
372 else if (!wcsicmp(L
"/all", argv
[1]))
376 ipconfig_message(STRING_INVALID_CMDLINE
);
377 ipconfig_message(STRING_USAGE
);
382 print_full_information();
386 ipconfig_message(STRING_INVALID_CMDLINE
);
387 ipconfig_message(STRING_USAGE
);
393 print_basic_information();