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
25 #include <wine/unicode.h>
29 static int ipconfig_vprintfW(const WCHAR
*msg
, __ms_va_list va_args
)
33 WCHAR msg_buffer
[8192];
35 wlen
= FormatMessageW(FORMAT_MESSAGE_FROM_STRING
, msg
, 0, 0, msg_buffer
,
36 sizeof(msg_buffer
)/sizeof(*msg_buffer
), &va_args
);
38 ret
= WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE
), msg_buffer
, wlen
, &count
, NULL
);
44 /* On Windows WriteConsoleW() fails if the output is redirected. So fall
45 * back to WriteFile(), assuming the console encoding is still the right
48 len
= WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer
, wlen
,
50 msgA
= HeapAlloc(GetProcessHeap(), 0, len
);
54 WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer
, wlen
, msgA
, len
,
56 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE
), msgA
, len
, &count
, FALSE
);
57 HeapFree(GetProcessHeap(), 0, msgA
);
63 static int CDECL
ipconfig_printfW(const WCHAR
*msg
, ...)
68 __ms_va_start(va_args
, msg
);
69 len
= ipconfig_vprintfW(msg
, va_args
);
75 static int CDECL
ipconfig_message_printfW(int msg
, ...)
78 WCHAR msg_buffer
[8192];
81 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
82 sizeof(msg_buffer
)/sizeof(WCHAR
));
84 __ms_va_start(va_args
, msg
);
85 len
= ipconfig_vprintfW(msg_buffer
, va_args
);
91 static int ipconfig_message(int msg
)
93 static const WCHAR formatW
[] = {'%','1',0};
94 WCHAR msg_buffer
[8192];
96 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
97 sizeof(msg_buffer
)/sizeof(WCHAR
));
99 return ipconfig_printfW(formatW
, msg_buffer
);
102 static const WCHAR
*iftype_to_string(DWORD type
)
104 static WCHAR msg_buffer
[50];
110 case IF_TYPE_ETHERNET_CSMACD
:
111 /* The loopback adapter appears as an Ethernet device. */
112 case IF_TYPE_SOFTWARE_LOOPBACK
:
113 msg
= STRING_ETHERNET
;
116 msg
= STRING_UNKNOWN
;
119 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
120 sizeof(msg_buffer
)/sizeof(WCHAR
));
125 static void print_field(int msg
, const WCHAR
*value
)
127 static const WCHAR formatW
[] = {' ',' ',' ',' ','%','1',':',' ','%','2','\n',0};
129 WCHAR field
[] = {'.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',
130 ' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ',0};
131 WCHAR name_buffer
[sizeof(field
)/sizeof(WCHAR
)];
133 LoadStringW(GetModuleHandleW(NULL
), msg
, name_buffer
, sizeof(name_buffer
)/sizeof(WCHAR
));
134 memcpy(field
, name_buffer
, sizeof(WCHAR
) * min(strlenW(name_buffer
), sizeof(field
)/sizeof(WCHAR
) - 1));
136 ipconfig_printfW(formatW
, field
, value
);
139 static void print_value(const WCHAR
*value
)
141 static const WCHAR formatW
[] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
142 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
143 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
144 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
147 ipconfig_printfW(formatW
, value
);
150 static BOOL
socket_address_to_string(WCHAR
*buf
, DWORD len
, SOCKET_ADDRESS
*addr
)
152 return WSAAddressToStringW(addr
->lpSockaddr
,
153 addr
->iSockaddrLength
, NULL
,
157 static void print_basic_information(void)
159 IP_ADAPTER_ADDRESSES
*adapters
;
162 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
163 NULL
, NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
165 adapters
= HeapAlloc(GetProcessHeap(), 0, out
);
169 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
170 NULL
, adapters
, &out
) == ERROR_SUCCESS
)
172 IP_ADAPTER_ADDRESSES
*p
;
174 for (p
= adapters
; p
; p
= p
->Next
)
176 static const WCHAR newlineW
[] = {'\n',0};
177 static const WCHAR emptyW
[] = {0};
179 IP_ADAPTER_UNICAST_ADDRESS
*addr
;
180 IP_ADAPTER_GATEWAY_ADDRESS_LH
*gateway
;
183 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY
, iftype_to_string(p
->IfType
), p
->FriendlyName
);
184 ipconfig_printfW(newlineW
);
185 print_field(STRING_CONN_DNS_SUFFIX
, p
->DnsSuffix
);
187 for (addr
= p
->FirstUnicastAddress
; addr
; addr
= addr
->Next
)
189 if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET
&&
190 socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &addr
->Address
))
191 print_field(STRING_IP_ADDRESS
, addr_buf
);
192 else if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET6
&&
193 socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &addr
->Address
))
194 print_field(STRING_IP6_ADDRESS
, addr_buf
);
195 /* FIXME: Output corresponding subnet mask. */
198 if (p
->FirstGatewayAddress
)
200 if (socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &p
->FirstGatewayAddress
->Address
))
201 print_field(STRING_DEFAULT_GATEWAY
, addr_buf
);
203 for (gateway
= p
->FirstGatewayAddress
->Next
; gateway
; gateway
= gateway
->Next
)
205 if (socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &gateway
->Address
))
206 print_value(addr_buf
);
210 print_field(STRING_DEFAULT_GATEWAY
, emptyW
);
212 ipconfig_printfW(newlineW
);
216 HeapFree(GetProcessHeap(), 0, adapters
);
220 static const WCHAR
*nodetype_to_string(DWORD type
)
222 static WCHAR msg_buffer
[50];
228 case BROADCAST_NODETYPE
:
229 msg
= STRING_BROADCAST
;
231 case PEER_TO_PEER_NODETYPE
:
232 msg
= STRING_PEER_TO_PEER
;
237 case HYBRID_NODETYPE
:
241 msg
= STRING_UNKNOWN
;
244 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
245 sizeof(msg_buffer
)/sizeof(WCHAR
));
250 static WCHAR
*physaddr_to_string(WCHAR
*buf
, BYTE
*addr
, DWORD len
)
252 static const WCHAR fmtW
[] = {'%','0','2','X','-',0};
253 static const WCHAR fmt2W
[] = {'%','0','2','X',0};
262 for (i
= 0; i
< len
- 1; i
++)
264 sprintfW(p
, fmtW
, addr
[i
]);
267 sprintfW(p
, fmt2W
, addr
[i
]);
273 static const WCHAR
*boolean_to_string(int value
)
275 static WCHAR msg_buffer
[15];
277 LoadStringW(GetModuleHandleW(NULL
), value
? STRING_YES
: STRING_NO
,
278 msg_buffer
, sizeof(msg_buffer
)/sizeof(WCHAR
));
283 static void print_full_information(void)
285 static const WCHAR newlineW
[] = {'\n',0};
286 static const WCHAR emptyW
[] = {0};
289 IP_ADAPTER_ADDRESSES
*adapters
;
292 if (GetNetworkParams(NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
294 info
= HeapAlloc(GetProcessHeap(), 0, out
);
298 if (GetNetworkParams(info
, &out
) == ERROR_SUCCESS
)
300 WCHAR hostnameW
[MAX_HOSTNAME_LEN
+ 4];
302 MultiByteToWideChar(CP_ACP
, 0, info
->HostName
, -1, hostnameW
, sizeof(hostnameW
)/sizeof(hostnameW
[0]));
303 print_field(STRING_HOSTNAME
, hostnameW
);
305 /* FIXME: Output primary DNS suffix. */
307 print_field(STRING_NODE_TYPE
, nodetype_to_string(info
->NodeType
));
308 print_field(STRING_IP_ROUTING
, boolean_to_string(info
->EnableRouting
));
310 /* FIXME: Output WINS proxy status and DNS suffix search list. */
312 ipconfig_printfW(newlineW
);
315 HeapFree(GetProcessHeap(), 0, info
);
318 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
319 NULL
, NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
321 adapters
= HeapAlloc(GetProcessHeap(), 0, out
);
325 if (GetAdaptersAddresses(AF_UNSPEC
, GAA_FLAG_INCLUDE_ALL_GATEWAYS
,
326 NULL
, adapters
, &out
) == ERROR_SUCCESS
)
328 IP_ADAPTER_ADDRESSES
*p
;
330 for (p
= adapters
; p
; p
= p
->Next
)
332 IP_ADAPTER_UNICAST_ADDRESS
*addr
;
333 WCHAR physaddr_buf
[3 * MAX_ADAPTER_ADDRESS_LENGTH
];
334 IP_ADAPTER_GATEWAY_ADDRESS_LH
*gateway
;
337 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY
, iftype_to_string(p
->IfType
), p
->FriendlyName
);
338 ipconfig_printfW(newlineW
);
339 print_field(STRING_CONN_DNS_SUFFIX
, p
->DnsSuffix
);
340 print_field(STRING_DESCRIPTION
, p
->Description
);
341 print_field(STRING_PHYS_ADDR
, physaddr_to_string(physaddr_buf
, p
->PhysicalAddress
, p
->PhysicalAddressLength
));
342 print_field(STRING_DHCP_ENABLED
, boolean_to_string(p
->Flags
& IP_ADAPTER_DHCP_ENABLED
));
344 /* FIXME: Output autoconfiguration status. */
346 for (addr
= p
->FirstUnicastAddress
; addr
; addr
= addr
->Next
)
348 if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET
&&
349 socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &addr
->Address
))
350 print_field(STRING_IP_ADDRESS
, addr_buf
);
351 else if (addr
->Address
.lpSockaddr
->sa_family
== AF_INET6
&&
352 socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &addr
->Address
))
353 print_field(STRING_IP6_ADDRESS
, addr_buf
);
354 /* FIXME: Output corresponding subnet mask. */
357 if (p
->FirstGatewayAddress
)
359 if (socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &p
->FirstGatewayAddress
->Address
))
360 print_field(STRING_DEFAULT_GATEWAY
, addr_buf
);
362 for (gateway
= p
->FirstGatewayAddress
->Next
; gateway
; gateway
= gateway
->Next
)
364 if (socket_address_to_string(addr_buf
, sizeof(addr_buf
)/sizeof(WCHAR
), &gateway
->Address
))
365 print_value(addr_buf
);
369 print_field(STRING_DEFAULT_GATEWAY
, emptyW
);
371 ipconfig_printfW(newlineW
);
375 HeapFree(GetProcessHeap(), 0, adapters
);
379 int wmain(int argc
, WCHAR
*argv
[])
381 static const WCHAR slashHelp
[] = {'/','?',0};
382 static const WCHAR slashAll
[] = {'/','a','l','l',0};
386 if (WSAStartup(MAKEWORD(2, 2), &data
))
391 if (!strcmpW(slashHelp
, argv
[1]))
393 ipconfig_message(STRING_USAGE
);
397 else if (!strcmpiW(slashAll
, argv
[1]))
401 ipconfig_message(STRING_INVALID_CMDLINE
);
402 ipconfig_message(STRING_USAGE
);
407 print_full_information();
411 ipconfig_message(STRING_INVALID_CMDLINE
);
412 ipconfig_message(STRING_USAGE
);
418 print_basic_information();