netstat: Initial implementation
André Hentschel
nerv at dawncrow.de
Wed Dec 26 11:45:18 CST 2012
That's the basic tcp table output when no arguments are given.
more to come... maybe next year
---
configure.ac | 1 +
programs/netstat/Makefile.in | 11 +++
programs/netstat/netstat.c | 206 +++++++++++++++++++++++++++++++++++++++++++
programs/netstat/netstat.h | 39 ++++++++
programs/netstat/netstat.rc | 46 ++++++++++
5 files changed, 303 insertions(+)
create mode 100644 programs/netstat/Makefile.in
create mode 100644 programs/netstat/netstat.c
create mode 100644 programs/netstat/netstat.h
create mode 100644 programs/netstat/netstat.rc
diff --git a/configure.ac b/configure.ac
index 0225edf..9390ca2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3156,6 +3156,7 @@ WINE_CONFIG_PROGRAM(mshta,,[install])
WINE_CONFIG_PROGRAM(msiexec,,[install,installbin,manpage])
WINE_CONFIG_PROGRAM(net,,[install,po])
WINE_CONFIG_PROGRAM(netsh,,[install])
+WINE_CONFIG_PROGRAM(netstat,,[install])
WINE_CONFIG_PROGRAM(ngen,,[install])
WINE_CONFIG_PROGRAM(notepad,,[install,installbin,manpage,po])
WINE_CONFIG_PROGRAM(oleview,,[install,po])
diff --git a/programs/netstat/Makefile.in b/programs/netstat/Makefile.in
new file mode 100644
index 0000000..5e0e7b6
--- /dev/null
+++ b/programs/netstat/Makefile.in
@@ -0,0 +1,11 @@
+MODULE = netstat.exe
+APPMODE = -mconsole -municode
+IMPORTS = iphlpapi user32 ws2_32
+EXTRADEFS = -DWINE_NO_UNICODE_MACROS
+
+C_SRCS = netstat.c
+
+RC_SRCS = netstat.rc
+PO_SRCS = netstat.rc
+
+ at MAKE_PROG_RULES@
diff --git a/programs/netstat/netstat.c b/programs/netstat/netstat.c
new file mode 100644
index 0000000..59d67e7
--- /dev/null
+++ b/programs/netstat/netstat.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2011-2012 André Hentschel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "netstat.h"
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(netstat);
+
+static const WCHAR tcpW[] = {'T', 'C', 'P', 0};
+static const WCHAR fmtport[] = {'%', 'd', 0};
+static const WCHAR fmtip[] = {'%', 'd', '.', '%', 'd', '.', '%', 'd', '.', '%', 'd', 0};
+static const WCHAR fmtn[] = {'\n', 0};
+static const WCHAR fmtnn[] = {'\n', '%', 's', '\n', 0};
+static const WCHAR fmtcolon[] = {'%', 's', ':', '%', 's', 0};
+static const WCHAR fmttcpout[] = {' ', ' ', '%', '-', '6', 's', ' ', '%', '-', '2', '2', 's', ' ', '%', '-', '2', '2', 's', ' ', '%', 's', '\n', 0};
+
+/* =========================================================================
+ * Output a unicode string. Ideally this will go to the console
+ * and hence required WriteConsoleW to output it, however if file i/o is
+ * redirected, it needs to be WriteFile'd using OEM (not ANSI) format
+ * ========================================================================= */
+static int __cdecl NETSTAT_wprintf(const WCHAR *format, ...)
+{
+ static WCHAR *output_bufW = NULL;
+ static char *output_bufA = NULL;
+ static BOOL toConsole = TRUE;
+ static BOOL traceOutput = FALSE;
+#define MAX_WRITECONSOLE_SIZE 65535
+
+ __ms_va_list parms;
+ DWORD nOut;
+ int len;
+ DWORD res = 0;
+
+ /*
+ * Allocate buffer to use when writing to console
+ * Note: Not freed - memory will be allocated once and released when
+ * xcopy ends
+ */
+
+ if (!output_bufW) output_bufW = HeapAlloc(GetProcessHeap(), 0,
+ MAX_WRITECONSOLE_SIZE);
+ if (!output_bufW) {
+ WINE_FIXME("Out of memory - could not allocate 2 x 64K buffers\n");
+ return 0;
+ }
+
+ __ms_va_start(parms, format);
+ len = vsprintfW(output_bufW, format, parms);
+ __ms_va_end(parms);
+
+ /* Try to write as unicode all the time we think its a console */
+ if (toConsole) {
+ res = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
+ output_bufW, len, &nOut, NULL);
+ }
+
+ /* If writing to console has failed (ever) we assume its file
+ i/o so convert to OEM codepage and output */
+ if (!res) {
+ BOOL usedDefaultChar = FALSE;
+ DWORD convertedChars;
+
+ toConsole = FALSE;
+
+ /*
+ * Allocate buffer to use when writing to file. Not freed, as above
+ */
+ if (!output_bufA) output_bufA = HeapAlloc(GetProcessHeap(), 0,
+ MAX_WRITECONSOLE_SIZE);
+ if (!output_bufA) {
+ WINE_FIXME("Out of memory - could not allocate 2 x 64K buffers\n");
+ return 0;
+ }
+
+ /* Convert to OEM, then output */
+ convertedChars = WideCharToMultiByte(GetConsoleOutputCP(), 0, output_bufW,
+ len, output_bufA, MAX_WRITECONSOLE_SIZE,
+ "?", &usedDefaultChar);
+ WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), output_bufA, convertedChars,
+ &nOut, FALSE);
+ }
+
+ /* Trace whether screen or console */
+ if (!traceOutput) {
+ WINE_TRACE("Writing to console? (%d)\n", toConsole);
+ traceOutput = TRUE;
+ }
+ return nOut;
+}
+
+WCHAR *NETSTAT_load_message(UINT id) {
+ static WCHAR msg[2048];
+ static const WCHAR failedW[] = {'F','a','i','l','e','d','!','\0'};
+
+ if (!LoadStringW(GetModuleHandleW(NULL), id, msg, sizeof(msg)/sizeof(WCHAR))) {
+ WINE_FIXME("LoadString failed with %d\n", GetLastError());
+ strcpyW(msg, failedW);
+ }
+ return msg;
+}
+
+WCHAR *NETSTAT_port_name(UINT port, WCHAR name[])
+{
+ /* FIXME: can we get the name? */
+ sprintfW(name, fmtport, htons((WORD)port));
+ return name;
+}
+
+WCHAR *NETSTAT_host_name(UINT ip, WCHAR name[])
+{
+ UINT nip;
+
+ /* FIXME: can we get the name? */
+ nip = htonl(ip);
+ sprintfW(name, fmtip, (nip >> 24) & 0xFF, (nip >> 16) & 0xFF, (nip >> 8) & 0xFF, (nip) & 0xFF);
+ return name;
+}
+
+void NETSTAT_tcp_table(void)
+{
+ PMIB_TCPTABLE table;
+ DWORD err, size, i;
+ WCHAR local[22], remote[22], state[22];
+ WCHAR HostIp[MAX_HOSTNAME_LEN], HostPort[32];
+ WCHAR RemoteIp[MAX_HOSTNAME_LEN], RemotePort[32];
+ WCHAR Host[MAX_HOSTNAME_LEN + 32];
+ WCHAR Remote[MAX_HOSTNAME_LEN + 32];
+
+ size = sizeof(MIB_TCPTABLE);
+ do
+ {
+ table = (PMIB_TCPTABLE)HeapAlloc(GetProcessHeap(), 0, size);
+ err = GetTcpTable(table, &size, TRUE);
+ if (err != NO_ERROR) HeapFree(GetProcessHeap(), 0, table);
+ } while (err == ERROR_INSUFFICIENT_BUFFER);
+
+ if (err) return;
+
+ NETSTAT_wprintf(fmtnn, NETSTAT_load_message(IDS_TCP_ACTIVE_CONN));
+ NETSTAT_wprintf(fmtn);
+ strcpyW(local, NETSTAT_load_message(IDS_TCP_LOCAL_ADDR));
+ strcpyW(remote, NETSTAT_load_message(IDS_TCP_REMOTE_ADDR));
+ strcpyW(state, NETSTAT_load_message(IDS_TCP_STATE));
+ NETSTAT_wprintf(fmttcpout, NETSTAT_load_message(IDS_TCP_PROTO), local, remote, state);
+
+ for (i = 0; i < table->dwNumEntries; i++)
+ {
+ if ((table->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT) ||
+ (table->table[i].dwState == MIB_TCP_STATE_ESTAB) ||
+ (table->table[i].dwState == MIB_TCP_STATE_TIME_WAIT))
+ {
+ NETSTAT_host_name(table->table[i].dwLocalAddr, HostIp);
+ NETSTAT_port_name(table->table[i].dwLocalPort, HostPort);
+ NETSTAT_host_name(table->table[i].dwRemoteAddr, RemoteIp);
+ NETSTAT_port_name(table->table[i].dwRemotePort, RemotePort);
+
+ sprintfW(Host, fmtcolon, HostIp, HostPort);
+ sprintfW(Remote, fmtcolon, RemoteIp, RemotePort);
+ NETSTAT_wprintf(fmttcpout, tcpW, Host, Remote, NETSTAT_load_message(table->table[i].dwState));
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, table);
+}
+
+int wmain(int argc, WCHAR *argv[])
+{
+ WSADATA wsa_data;
+
+ if (argc > 1)
+ {
+ int i;
+ WINE_FIXME("stub:");
+ for (i = 0; i < argc; i++)
+ WINE_FIXME(" %s", wine_dbgstr_w(argv[i]));
+ WINE_FIXME("\n");
+ }
+
+ if (WSAStartup(MAKEWORD(2, 2), &wsa_data))
+ {
+ WINE_ERR("WSAStartup failed: %d\n", WSAGetLastError());
+ return 1;
+ }
+
+ NETSTAT_tcp_table();
+
+ return 0;
+}
diff --git a/programs/netstat/netstat.h b/programs/netstat/netstat.h
new file mode 100644
index 0000000..c05df5d
--- /dev/null
+++ b/programs/netstat/netstat.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 André Hentschel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <windows.h>
+
+#define IDS_TCP_UNKNOWN 0
+#define IDS_TCP_CLOSED 1
+#define IDS_TCP_LISTENING 2
+#define IDS_TCP_SYN_SENT 3
+#define IDS_TCP_SYN_RCVD 4
+#define IDS_TCP_ESTABLISHED 5
+#define IDS_TCP_FIN_WAIT1 6
+#define IDS_TCP_FIN_WAIT2 7
+#define IDS_TCP_CLOSE_WAIT 8
+#define IDS_TCP_CLOSING 9
+#define IDS_TCP_LAST_ACK 10
+#define IDS_TCP_TIME_WAIT 11
+#define IDS_TCP_DELETE_TCB 12
+
+#define IDS_TCP_ACTIVE_CONN 13
+#define IDS_TCP_PROTO 14
+#define IDS_TCP_LOCAL_ADDR 15
+#define IDS_TCP_REMOTE_ADDR 16
+#define IDS_TCP_STATE 17
diff --git a/programs/netstat/netstat.rc b/programs/netstat/netstat.rc
new file mode 100644
index 0000000..45c8ec5
--- /dev/null
+++ b/programs/netstat/netstat.rc
@@ -0,0 +1,46 @@
+/*
+ * NETSTAT resources
+ *
+ * Copyright 2012 André Hentschel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "netstat.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+STRINGTABLE
+{
+ IDS_TCP_UNKNOWN, "???"
+ IDS_TCP_CLOSED, "CLOSED"
+ IDS_TCP_LISTENING, "LISTENING"
+ IDS_TCP_SYN_SENT, "SYN_SENT"
+ IDS_TCP_SYN_RCVD, "SYN_RCVD"
+ IDS_TCP_ESTABLISHED, "ESTABLISHED"
+ IDS_TCP_FIN_WAIT1, "FIN_WAIT1"
+ IDS_TCP_FIN_WAIT2, "FIN_WAIT2"
+ IDS_TCP_CLOSE_WAIT, "CLOSE_WAIT"
+ IDS_TCP_CLOSING, "CLOSING"
+ IDS_TCP_LAST_ACK, "LAST_ACK"
+ IDS_TCP_TIME_WAIT, "TIME_WAIT"
+ IDS_TCP_DELETE_TCB, "DELETE_TCB"
+
+ IDS_TCP_ACTIVE_CONN, "Active Connections"
+ IDS_TCP_PROTO, "Proto"
+ IDS_TCP_LOCAL_ADDR, "Local Address"
+ IDS_TCP_REMOTE_ADDR, "Foreign Address"
+ IDS_TCP_STATE, "State"
+}
--
1.8.0
--
Best Regards, André Hentschel
More information about the wine-patches
mailing list