qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 4/4] added qga processes and connections enumeration


From: itamar . tal4
Subject: [Qemu-devel] [PATCH 4/4] added qga processes and connections enumeration commands (win/linux)
Date: Tue, 31 Mar 2015 11:34:37 +0300

From: Itamar Tal <address@hidden>

This patch add more missing commands to the qga (both Windows and Linux):
- current active process list
- current active connections list
the abovementioned commands are added to align the guest agent functionality
with other common hypervisor agents.

---
 qga/commands-posix.c    | 608 ++++++++++++++++++++++++++++++++++++++++++++++++
 qga/commands-win32.c    | 404 +++++++++++++++++++++++++++++++-
 qga/qapi-schema.json    |  99 ++++++++
 qga/win32-definitions.h | 110 +++++++++
 qga/win32-iptypes.h     | 412 ++++++++++++++++++++++++++++++++
 5 files changed, 1631 insertions(+), 2 deletions(-)
 create mode 100644 qga/win32-definitions.h
 create mode 100644 qga/win32-iptypes.h

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 38b639c..c4b82eb 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -9,6 +9,7 @@
  *
  * Changes (address@hidden):
  * - file attributes, removal, hashes
+ * - added process and connection enumeration support
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
@@ -50,6 +51,53 @@ extern char **environ;
 #include <sys/socket.h>
 #include <net/if.h>
 
+#define PRG_HASH_SIZE      (211)
+
+typedef
+struct prg_node {
+    struct prg_node *next;
+    int inode;
+    int pid;
+} prg_node;
+
+typedef
+struct prg_hash {
+    struct prg_node *hash[PRG_HASH_SIZE];
+} prg_hash;
+
+#define PRG_LOCAL_ADDRESS "local_address"
+#define PRG_INODE     "inode"
+#define PRG_SOCKET_PFX    "socket:["
+#define PRG_SOCKET_PFXl (strlen(PRG_SOCKET_PFX))
+#define PRG_SOCKET_PFX2   "[0000]:"
+#define PRG_SOCKET_PFX2l  (strlen(PRG_SOCKET_PFX2))
+
+#define PRG_HASHIT(x) ((x) % PRG_HASH_SIZE)
+#ifndef LINE_MAX
+#define LINE_MAX 4096
+#endif
+#define PATH_PROC       "/proc"
+#define PATH_FD_SUFF    "fd"
+#define PATH_FD_SUFFl       strlen(PATH_FD_SUFF)
+#define PATH_PROC_X_FD      PATH_PROC "/%s/" PATH_FD_SUFF
+#define PATH_CMDLINE    "cmdline"
+#define PATH_CMDLINEl       strlen(PATH_CMDLINE)
+
+/* These enums are used by IPX too. :-( */
+enum {
+    TCP_ESTABLISHED = 1,
+    TCP_SYN_SENT,
+    TCP_SYN_RECV,
+    TCP_FIN_WAIT1,
+    TCP_FIN_WAIT2,
+    TCP_TIME_WAIT,
+    TCP_CLOSE,
+    TCP_CLOSE_WAIT,
+    TCP_LAST_ACK,
+    TCP_LISTEN,
+    TCP_CLOSING            /* now a valid state */
+};
+
 #ifdef FIFREEZE
 #define CONFIG_FSFREEZE
 #endif
@@ -2491,4 +2539,564 @@ uint32_t qmp_guest_uptime(Error **errp)
     return sys_info.uptime;
 }
 
+GuestProcessInfoList *qmp_guest_get_process_list(Error **errp)
+{
+    struct dirent *ent = NULL;
+    GuestProcessInfoList *process_list_head = NULL;
+    GuestProcessInfoList *process_list_last = NULL;
+
+    DIR *procfs = opendir("/proc");
+
+    if (NULL == procfs) {
+        error_setg(errp, "Failed opening procfs (error %d)", errno);
+        return NULL;
+    }
+
+    /* read entries until EOD */
+    errno = 0;
+    while (NULL != (ent = readdir(procfs))) {
+        int pid = strtoul(ent->d_name, NULL, 10);
+        GuestProcessInfoList *list_item = NULL;
+        char local_path[256];
+        FILE *info_file = NULL;
+        char info[256];
+        size_t len;
+
+        /* ensure directory name is a number */
+        if ((0 == pid) || (ULONG_MAX == pid)) {
+            continue;
+        }
+
+        list_item = g_malloc0(sizeof(GuestProcessInfoList));
+        if (NULL == process_list_head) {
+            process_list_head = list_item;
+        }
+        if (NULL != process_list_last) {
+            process_list_last->next = list_item;
+        }
+        process_list_last = list_item;
+
+        list_item->next = NULL;
+        list_item->value = g_malloc0(sizeof(GuestProcessInfo));
+        list_item->value->process_id = pid;
+
+        /* read process name */
+        snprintf(local_path, 256, "/proc/%d/comm", pid);
+        info_file = fopen(local_path, "rb");
+        if (NULL != info_file) {
+            len = fread(info, 1, 256, info_file);
+            info[len] = '\0';
+            if ((0 < len) && ('\n' == info[len - 1])) {
+                info[len - 1] = '\0';
+            }
+            list_item->value->process_name = g_strdup(info);
+
+            fclose(info_file);
+        }
+
+        /* read process parent id */
+        snprintf(local_path, 256, "/proc/%d/status", pid);
+        info_file = fopen(local_path, "rb");
+        if (NULL != info_file) {
+            char *line = NULL;
+            size_t line_size = 0;
+
+            /* read lines, search for ppid */
+            for (;;) {
+                len = getline(&line, &line_size, info_file);
+                if (-1 == len) {
+                    break;
+                }
+
+                if (line == strstr(line, "PPid:")) {
+                    list_item->value->parent_id = strtoul(line + 5, NULL, 10);
+                }
+            }
+
+            fclose(info_file);
+        }
+
+        /* read process session id */
+        snprintf(local_path, 256, "/proc/%d/sessionid", pid);
+        info_file = fopen(local_path, "rb");
+        if (NULL != info_file) {
+            len = fread(info, 1, 256, info_file);
+            info[len] = '\0';
+            list_item->value->session_id = strtoul(info, NULL, 10);
+
+            fclose(info_file);
+        }
+
+        /* read process image path */
+        snprintf(local_path, 256, "/proc/%d/exe", pid);
+        len = readlink(local_path, info, sizeof(info) - 1);
+        if (-1 != len) {
+            info[len] = '\0';
+            list_item->value->image_path = g_strdup(info);
+        }
+
+        errno = 0;
+    }
+
+    (void)closedir(procfs);
+
+    if (0 != errno) {
+        error_setg(errp, "Error while reading procfs directory (error %d)",
+                   errno);
+        return NULL;
+    }
+
+    return process_list_head;
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static void prg_cache_add(prg_hash *hash, int inode, int pid)
+{
+    unsigned hi = PRG_HASHIT(inode);
+    struct prg_node **pnp = NULL, *pn = NULL;
+
+    /* look for the inode in the table or find next free entry for the inode */
+    for (pnp = &hash->hash[hi]; (pn = *pnp); pnp = &pn->next) {
+        if (pn->inode == inode) {
+            /* Some warning should be appropriate here
+            as we got multiple processes for one i-node */
+            return;
+        }
+    }
+
+    /* allocate new entry for this inode */
+    *pnp = g_malloc0(sizeof(struct prg_node));
+    if (NULL == *pnp) {
+        return;
+    }
+
+    pn = *pnp;
+    pn->next = NULL;
+    pn->inode = inode;
+    pn->pid = pid;
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static int prg_cache_get(prg_hash *hash, int inode)
+{
+    unsigned hi = PRG_HASHIT(inode);
+    struct prg_node *pn = NULL;
+
+    for (pn = hash->hash[hi]; pn; pn = pn->next) {
+        if (pn->inode == inode) {
+            return pn->pid;
+        }
+    }
+
+    return -1;
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static void prg_cache_clear(prg_hash *hash)
+{
+    struct prg_node **pnp = NULL, *pn = NULL;
+
+
+    for (pnp = hash->hash; pnp < hash->hash + PRG_HASH_SIZE; pnp++) {
+        pn = *pnp;
+        while (NULL != pn) {
+            *pnp = pn->next;
+            free(pn);
+            pn = *pnp;
+        }
+    }
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static void extract_type_1_socket_inode(const char lname[], long *inode_p)
+{
+
+    /* If lname is of the form "socket:[12345]", extract the "12345"
+       as *inode_p.  Otherwise, return -1 as *inode_p.
+     */
+
+    if (strlen(lname) < PRG_SOCKET_PFXl+3) {
+        *inode_p = -1;
+    } else if (memcmp(lname, PRG_SOCKET_PFX, PRG_SOCKET_PFXl)) {
+        *inode_p = -1;
+    } else if (lname[strlen(lname)-1] != ']') {
+        *inode_p = -1;
+    } else {
+        char inode_str[strlen(lname + 1)];  /* e.g. "12345" */
+        const int inode_str_len = strlen(lname) - PRG_SOCKET_PFXl - 1;
+        char *serr = NULL;
+
+        strncpy(inode_str, lname + PRG_SOCKET_PFXl, inode_str_len);
+        inode_str[inode_str_len] = '\0';
+        *inode_p = strtol(inode_str, &serr, 0);
+        if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX) {
+            *inode_p = -1;
+        }
+    }
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static void extract_type_2_socket_inode(const char lname[], long *inode_p)
+{
+
+    /* If lname is of the form "[0000]:12345", extract the "12345"
+       as *inode_p.  Otherwise, return -1 as *inode_p.
+     */
+
+    if (strlen(lname) < PRG_SOCKET_PFX2l+1) {
+        *inode_p = -1;
+    } else if (memcmp(lname, PRG_SOCKET_PFX2, PRG_SOCKET_PFX2l)) {
+        *inode_p = -1;
+    } else {
+        char *serr = NULL;
+
+        *inode_p = strtol(lname + PRG_SOCKET_PFX2l, &serr, 0);
+        if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX) {
+            *inode_p = -1;
+        }
+    }
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static int prg_cache_load(prg_hash *hash)
+{
+    char line[LINE_MAX];
+    int procfdlen, lnamelen;
+    char lname[30];
+    long inode;
+    const char *cs = NULL;
+    DIR *dirproc = NULL, *dirfd = NULL;
+    struct dirent *direproc = NULL, *direfd = NULL;
+
+    /* reset the hash table */
+    memset(hash, 0, sizeof(prg_hash));
+
+    dirproc = opendir(PATH_PROC);
+    if (NULL == dirproc) {
+        return 0;
+    }
+
+    for (;;) {
+        int pid = 0;
+
+        errno = 0;
+        direproc = readdir(dirproc);
+        if (NULL == direproc) {
+            break;
+        }
+
+#ifdef DIRENT_HAVE_D_TYPE_WORKS
+        if (direproc->d_type != DT_DIR) {
+            continue;
+        }
+#endif
+        for (cs = direproc->d_name; *cs; cs++) {
+            if (!isdigit(*cs)) {
+                break;
+            }
+        }
+        if (*cs) {
+            continue;
+        }
+
+        procfdlen = snprintf(line, sizeof(line),
+                             PATH_PROC_X_FD, direproc->d_name);
+        if ((procfdlen <= 0) || (procfdlen >= sizeof(line) - 5)) {
+            continue;
+        }
+        errno = 0;
+        dirfd = opendir(line);
+        if (NULL == dirfd) {
+            continue;
+        }
+        line[procfdlen] = '/';
+        for (;;) {
+            errno = 0;
+            direfd = readdir(dirfd);
+            if (NULL == direfd) {
+                break;
+            }
+
+#ifdef DIRENT_HAVE_D_TYPE_WORKS
+            if (direfd->d_type != DT_LNK) {
+                continue;
+            }
+#endif
+            if (procfdlen + 1 + strlen(direfd->d_name) + 1 > sizeof(line)) {
+                continue;
+            }
+            memcpy(line + procfdlen - PATH_FD_SUFFl, PATH_FD_SUFF "/",
+                   PATH_FD_SUFFl + 1);
+            strcpy(line + procfdlen + 1, direfd->d_name);
+            lnamelen = readlink(line, lname, sizeof(lname)-1);
+            lname[lnamelen] = '\0';  /*make it a null-terminated string*/
+
+            extract_type_1_socket_inode(lname, &inode);
+
+            if (inode < 0) {
+                extract_type_2_socket_inode(lname, &inode);
+            }
+
+            if (inode < 0) {
+                continue;
+            }
+
+            pid = strtoul(direproc->d_name, NULL, 10);
+            prg_cache_add(hash, inode, pid);
+        }
+        closedir(dirfd);
+        dirfd = NULL;
+    }
+    if (dirproc) {
+        closedir(dirproc);
+    }
+    if (dirfd) {
+        closedir(dirfd);
+    }
+
+    return 1;
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static GuestActiveConnection *udp_do_one(prg_hash *hash, const char *line)
+{
+    GuestActiveConnection *conn = NULL;
+    char local_addr[64], rem_addr[64];
+    char more[512];
+    int num, local_port, rem_port, d, state, timer_run, uid, timeout;
+    struct sockaddr_in localaddr, remaddr;
+    unsigned long rxq, txq, time_len, retr, inode;
+
+    more[0] = '\0';
+    num = sscanf(line,
+            "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X"
+            " %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
+            &d, local_addr, &local_port,
+            rem_addr, &rem_port, &state,
+            &txq, &rxq, &timer_run, &time_len,
+            &retr, &uid, &timeout, &inode, more);
+
+    if (strlen(local_addr) > 8) {
+        /* ipv6 support is missing */
+    } else {
+        sscanf(local_addr, "%X",
+                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
+        sscanf(rem_addr, "%X",
+                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
+        ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
+        ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
+    }
+
+    retr = 0L;
+
+    if (num < 10) {
+        return NULL;
+    }
+
+    conn = g_malloc0(sizeof(GuestActiveConnection));
+
+    if (AF_INET == localaddr.sin_family) {
+        conn->source_addr = g_strdup(inet_ntoa(localaddr.sin_addr));
+        conn->dest_addr = g_strdup(inet_ntoa(remaddr.sin_addr));
+    }
+
+    conn->source_port = local_port;
+    conn->dest_port = rem_port;
+    conn->owner_process_id = prg_cache_get(hash, inode);
+    conn->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+    conn->protocol = GUEST_IP_PROTOCOL_UDP;
+
+    switch (state) {
+    case TCP_CLOSE:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_CLOSED;
+        break;
+    case TCP_ESTABLISHED:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_ESTABLISHED;
+        break;
+    default:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_LISTEN;
+        break;
+    }
+
+    return conn;
+}
+
+/* this function is taken out of netstat (found in net-tools) and modified */
+static GuestActiveConnection *tcp_do_one(prg_hash *hash, const char *line)
+{
+    unsigned long rxq, txq, time_len, retr, inode;
+    int num, local_port, rem_port, d, state, uid, timer_run, timeout;
+    char rem_addr[128], local_addr[128], more[512];
+    struct sockaddr_in localaddr, remaddr;
+    GuestActiveConnection *conn = NULL;
+
+    num = sscanf(line,
+            "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X"
+            " %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
+            &d, local_addr, &local_port, rem_addr, &rem_port, &state,
+            &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout,
+            &inode, more);
+
+    if (strlen(local_addr) > 8) {
+        /* ipv6 support is missing */
+    } else {
+        sscanf(local_addr, "%X",
+                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
+        sscanf(rem_addr, "%X",
+                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
+        ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
+        ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
+    }
+
+    if (num < 11) {
+        return NULL;
+    }
+
+    if (state == TCP_LISTEN) {
+        time_len = 0;
+        retr = 0L;
+        rxq = 0L;
+        txq = 0L;
+    }
+
+    conn = g_malloc0(sizeof(GuestActiveConnection));
+
+    if (AF_INET == localaddr.sin_family) {
+        conn->source_addr = g_strdup(inet_ntoa(localaddr.sin_addr));
+        conn->dest_addr = g_strdup(inet_ntoa(remaddr.sin_addr));
+    }
+
+    conn->source_port = local_port;
+    conn->dest_port = rem_port;
+    conn->owner_process_id = prg_cache_get(hash, inode);
+    conn->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+    conn->protocol = GUEST_IP_PROTOCOL_TCP;
+
+    switch (state) {
+    case TCP_CLOSE:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_CLOSED;
+        break;
+    case TCP_LISTEN:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_LISTEN;
+        break;
+    case TCP_SYN_SENT:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_SYN_SENT;
+        break;
+    case TCP_SYN_RECV:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_SYN_RCVD;
+        break;
+    case TCP_ESTABLISHED:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_ESTABLISHED;
+        break;
+    case TCP_FIN_WAIT1:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_FIN_WAIT1;
+        break;
+    case TCP_FIN_WAIT2:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_FIN_WAIT2;
+        break;
+    case TCP_CLOSE_WAIT:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_CLOSE_WAIT;
+        break;
+    case TCP_CLOSING:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_CLOSING;
+        break;
+    case TCP_LAST_ACK:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_LAST_ACK;
+        break;
+    case TCP_TIME_WAIT:
+        conn->state = GUEST_TCP_PROTOCOL_STATE_TIME_WAIT;
+        break;
+    }
+
+    return conn;
+}
+
+GuestActiveConnectionList *qmp_guest_get_active_connections(Error **errp)
+{
+    GuestActiveConnectionList *conn_list_head = NULL;
+    GuestActiveConnectionList *conn_list_last = NULL;
+    prg_hash hash;
+    FILE *udp_info = NULL;
+    FILE *tcp_info = fopen("/proc/net/tcp", "r");
+    int i = 0;
+
+    if (NULL == tcp_info) {
+        error_setg(errp, "Error opening '/proc/net/tcp' (error %d)", errno);
+        return NULL;
+    }
+
+    prg_cache_load(&hash);
+
+    for (i = 0; !feof(tcp_info); ++i) {
+        char tcp_info_line[1024];
+        GuestActiveConnectionList *conn_item = NULL;
+        GuestActiveConnection *conn = NULL;
+
+        if (NULL == fgets(tcp_info_line, 1024, tcp_info)) {
+            continue;
+        }
+
+        if (i == 0) {
+            continue;
+        }
+
+        conn = tcp_do_one(&hash, tcp_info_line);
+        if (NULL == conn) {
+            continue;
+        }
+
+        /* add connection to the end of list */
+        conn_item = g_malloc0(sizeof(GuestActiveConnectionList));
+        if (NULL == conn_list_head) {
+            conn_list_head = conn_item;
+        }
+        if (NULL != conn_list_last) {
+            conn_list_last->next = conn_item;
+        }
+        conn_list_last = conn_item;
+        conn_item->value = conn;
+    }
+
+    fclose(tcp_info);
+
+    udp_info = fopen("/proc/net/udp", "r");
+    if (NULL == udp_info) {
+        error_setg(errp, "Error opening '/proc/net/udp' (error %d)", errno);
+        return NULL;
+    }
+
+    for (i = 0; !feof(udp_info); ++i) {
+        char udp_info_line[1024];
+        GuestActiveConnectionList *conn_item = NULL;
+        GuestActiveConnection *conn = NULL;
+
+        if (NULL == fgets(udp_info_line, 1024, udp_info)) {
+            continue;
+        }
+
+        if (i == 0) {
+            continue;
+        }
+
+        conn = udp_do_one(&hash, udp_info_line);
+        if (NULL == conn) {
+            continue;
+        }
+
+        /* add connection to the end of list */
+        conn_item = g_malloc0(sizeof(GuestActiveConnectionList));
+        if (NULL == conn_list_head) {
+            conn_list_head = conn_item;
+        }
+        if (NULL != conn_list_last) {
+            conn_list_last->next = conn_item;
+        }
+        conn_list_last = conn_item;
+        conn_item->value = conn;
+    }
+
+    prg_cache_clear(&hash);
+
+    return conn_list_head;
+}
 
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 6987f4e..30dcd50 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -9,6 +9,7 @@
  *
  * Changes (address@hidden):
  * - file attributes, removal, hashes
+ * - added process and connection enumeration support
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
@@ -22,6 +23,7 @@
 #include "qga/guest-agent-core.h"
 #include "qga/vss-win32.h"
 #include "qga-qmp-commands.h"
+#include "qga/win32-definitions.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/queue.h"
 
@@ -29,6 +31,10 @@
 #define SHTDN_REASON_FLAG_PLANNED 0x80000000
 #endif
 
+#ifndef MAX_PATH
+#define MAX_PATH            (256)
+#endif
+
 /* multiple of 100 nanoseconds elapsed between windows baseline
  *    (1/1/1601) and Unix Epoch (1/1/1970), accounting for leap years */
 #define W32_FT_OFFSET (10000000ULL * 60 * 60 * 24 * \
@@ -37,6 +43,38 @@
 
 #define INVALID_SET_FILE_POINTER ((DWORD)-1)
 
+DWORD (__stdcall * GetExtendedTcpTable)(void *pTcpTable,
+                                        DWORD * pdwSize,
+                                        BOOL bOrder,
+                                        ULONG ulAf,
+                                        TCP_TABLE_CLASS TableClass,
+                                        ULONG Reserved) = NULL;
+
+DWORD (__stdcall * GetExtendedUdpTable)(void *pUdpTable,
+                                        DWORD * pdwSize,
+                                        BOOL bOrder,
+                                        ULONG ulAf,
+                                        UDP_TABLE_CLASS TableClass,
+                                        ULONG Reserved) = NULL;
+
+NTSTATUS (__stdcall * RtlUnicodeStringToAnsiString)(
+                           ANSI_STRING *DestinationString,
+                           UNICODE_STRING *SourceString,
+                           BOOL AllocateDestinationString) = NULL;
+
+NTSTATUS (__stdcall * NtQueryInformationProcess)(
+                           HANDLE ProcessHandle,
+                           PROCESSINFOCLASS ProcessInformationClass,
+                           void *ProcessInformation,
+                           uint32_t ProcessInformationLength,
+                           uint32_t *ReturnLength) = NULL;
+
+NTSTATUS (__stdcall * NtQuerySystemInformation)(
+                           SYSTEM_INFORMATION_CLASS SystemInformationClass,
+                           void *SystemInformation,
+                           uint32_t SystemInformationLength,
+                           uint32_t *ReturnLength) = NULL;
+
 typedef struct GuestFileHandle {
     int64_t id;
     HANDLE fh;
@@ -386,17 +424,59 @@ static void guest_file_init(void)
 }
 
 int ga_win_commands_init(void)
-{
+ {
+    HMODULE ntdll_module = GetModuleHandle("ntdll.dll");
+    HMODULE iphlpapi_module = LoadLibrary("iphlpapi.dll");
     WSADATA wsa_data = {0};
 
+    if ((NULL == ntdll_module) ||
+        (NULL == iphlpapi_module)) {
+        goto error;
+    }
+
     if (WSAStartup(MAKEWORD(2, 2), &wsa_data)) {
         g_critical("failed to initialize WSA engine");
         goto error;
     }
 
+    NtQuerySystemInformation =
+                          (void *)GetProcAddress(ntdll_module,
+                                                 "NtQuerySystemInformation");
+    if (NULL == NtQuerySystemInformation) {
+        goto error;
+    }
+
+    RtlUnicodeStringToAnsiString =
+                       (void *)GetProcAddress(ntdll_module,
+                                              "RtlUnicodeStringToAnsiString");
+    if (NULL == RtlUnicodeStringToAnsiString) {
+        goto error;
+    }
+
+    NtQueryInformationProcess =
+                         (void *)GetProcAddress(ntdll_module,
+                                                "NtQueryInformationProcess");
+    if (NULL == NtQueryInformationProcess) {
+        goto error;
+    }
+
+    GetExtendedTcpTable = (void *)GetProcAddress(iphlpapi_module,
+                                                 "GetExtendedTcpTable");
+    if (NULL == GetExtendedTcpTable) {
+        goto error;
+    }
+
+    GetExtendedUdpTable = (void *)GetProcAddress(iphlpapi_module,
+                                                 "GetExtendedUdpTable");
+    if (NULL == GetExtendedUdpTable) {
+        goto error;
+    }
+
     return 1;
 
-error:
+ error:
+    (void)FreeLibrary(iphlpapi_module);
+
     return 0;
 }
 
@@ -902,4 +982,324 @@ uint32_t qmp_guest_uptime(Error **errp)
     return uptime_milli / 1000;
 }
 
+GuestProcessInfoList *qmp_guest_get_process_list(Error **errp)
+{
+    uint32_t bytes_needed = sizeof(SYSTEM_PROCESS_INFORMATION) * 20;
+    SYSTEM_PROCESS_INFORMATION *process_list = NULL;
+    SYSTEM_PROCESS_INFORMATION *process_list_iter = NULL;
+    GuestProcessInfoList *process_list_head = NULL;
+    GuestProcessInfoList *process_list_last = NULL;
+    DWORD current_process_id = GetCurrentProcessId();
+    NTSTATUS status = STATUS_SUCCESS;
+
+    /* find the minimal buffer for the process list */
+    for (;;) {
+        process_list = g_malloc0(bytes_needed);
+        if (NULL == process_list) {
+            error_setg(errp, "No memory for process list (%d bytes)",
+                       bytes_needed);
+            return NULL;
+        }
+
+        /* query the process list (if enough bytes are given) */
+        status = NtQuerySystemInformation(SystemProcessInformation,
+                                          process_list,
+                                          bytes_needed,
+                                          &bytes_needed);
+        if (STATUS_SUCCESS != status) {
+            (void)g_free(process_list);
+
+            if (STATUS_INFO_LENGTH_MISMATCH == status) {
+                bytes_needed <<= 1;
+                continue;
+            }
+
+            error_setg(errp, "Failed quering process list (status %08X)",
+                       (int)status);
+            return NULL;
+        }
+
+        break;
+    }
+
+    /* iterate the process list and build the JSON reply */
+    for (process_list_iter = process_list;;) {
+        GuestProcessInfoList *list_item =
+                                      g_malloc0(sizeof(GuestProcessInfoList));
+        ANSI_STRING process_name;
+        HANDLE process_handle = NULL;
+        UNICODE_STRING *process_image_path = NULL;
+        PROCESS_BASIC_INFORMATION process_basic_info = {0};
+
+        if (NULL == process_list_head) {
+            process_list_head = list_item;
+        }
+        if (NULL != process_list_last) {
+            process_list_last->next = list_item;
+        }
+        process_list_last = list_item;
+
+        list_item->next = NULL;
+        list_item->value = g_malloc0(sizeof(GuestProcessInfo));
+        list_item->value->process_id = (int)process_list_iter->UniqueProcessId;
+        list_item->value->session_id = (int)process_list_iter->SessionId;
+
+        if (0 == list_item->value->process_id) {
+            list_item->value->process_name = g_strdup("System Idle Process");
+            process_list_iter = (void *)((uint32_t)process_list_iter +
+                                         process_list_iter->NextEntryOffset);
+            continue;
+        } else if (4 == list_item->value->process_id) {
+            list_item->value->process_name = g_strdup("System");
+            process_list_iter = (void *)((uint32_t)process_list_iter +
+                                         process_list_iter->NextEntryOffset);
+            continue;
+        }
+
+        process_name.MaximumLength =
+                                   process_list_iter->ImageName.MaximumLength;
+        process_name.Length = 0;
+        process_name.Buffer = g_malloc0(process_name.MaximumLength);
+
+        /* convert the image name to ansi string */
+        (void)RtlUnicodeStringToAnsiString(&process_name,
+                                           &process_list_iter->ImageName,
+                                           FALSE);
+        list_item->value->process_name = process_name.Buffer;
+
+        if (!process_list_iter->NextEntryOffset) {
+            break;
+        }
+
+        if (current_process_id != list_item->value->process_id) {
+            process_handle = OpenProcess(PROCESS_QUERY_INFORMATION,
+                                         FALSE,
+                                         list_item->value->process_id);
+        } else {
+            char curr_image_path[MAX_PATH];
+
+            process_handle = GetCurrentProcess();
+
+            if (GetModuleFileName(NULL,
+                                  curr_image_path,
+                                  MAX_PATH)) {
+                list_item->value->image_path = g_strdup(&curr_image_path[0]);
+            }
+        }
+
+        if (NULL != process_handle) {
+            /* get process parent ID */
+            status = NtQueryInformationProcess(
+                                           process_handle,
+                                           ProcessBasicInformation,
+                                           &process_basic_info,
+                                           sizeof(PROCESS_BASIC_INFORMATION),
+                                           NULL);
+            if (STATUS_SUCCESS == status)  {
+                list_item->value->parent_id =
+                         (int)process_basic_info.InheritedFromUniqueProcessId;
+            }
+
+            /* get process image path */
+            if (NULL == list_item->value->image_path) {
+                process_image_path = g_malloc0(sizeof(UNICODE_STRING) +
+                                               MAX_PATH * sizeof(wchar_t));
+
+                status = NtQueryInformationProcess(process_handle,
+                                                   ProcessImageFileName,
+                                                   process_image_path,
+                                                   sizeof(UNICODE_STRING) +
+                                                   MAX_PATH * sizeof(wchar_t),
+                                                   NULL);
+                if (STATUS_SUCCESS == status) {
+                    process_name.MaximumLength =
+                                            process_image_path->MaximumLength;
+                    process_name.Length = 0;
+                    process_name.Buffer =
+                                        g_malloc0(process_name.MaximumLength);
+
+                    /* convert the image name to ANSI string */
+                    (void)RtlUnicodeStringToAnsiString(&process_name,
+                                                       process_image_path,
+                                                       FALSE);
+                    list_item->value->image_path = process_name.Buffer;
+                }
+
+                (void)g_free(process_image_path);
+            }
+
+            (void)CloseHandle(process_handle);
+        }
+
+        process_list_iter = (void *)((uint32_t)process_list_iter +
+                                     process_list_iter->NextEntryOffset);
+    }
+
+    (void)g_free(process_list);
+
+    return process_list_head;
+}
+
+GuestActiveConnectionList *qmp_guest_get_active_connections(Error **errp)
+{
+    MIB_UDPTABLE_OWNER_MODULE *udp_table = NULL;
+    MIB_TCPTABLE_OWNER_MODULE *tcp_table = NULL;
+    DWORD bytes_needed = sizeof(MIB_UDPTABLE_OWNER_MODULE) * 30;
+    GuestActiveConnectionList *connections = NULL;
+    int entry_index = 0;
+    DWORD ret;
+
+    /* get the UDP table */
+    for (;;) {
+        udp_table = g_malloc0(bytes_needed);
+        if (NULL == udp_table) {
+            error_setg(errp, "Failed allocating active UDP connections table");
+            return NULL;
+        }
+
+        ret = GetExtendedUdpTable(udp_table,
+                                  &bytes_needed,
+                                  TRUE,
+                                  AF_INET,
+                                  UDP_TABLE_OWNER_MODULE,
+                                  0);
+        if (NO_ERROR != ret) {
+            (void)g_free(tcp_table);
+            udp_table = NULL;
+
+            if (ERROR_INSUFFICIENT_BUFFER == ret) {
+                bytes_needed <<= 1;
+                continue;
+            }
+        }
+
+        break;
+    }
+
+    /* add the UDP connections to the list backward */
+    for (entry_index = udp_table->dwNumEntries - 1;
+         entry_index >= 0;
+         --entry_index) {
+        MIB_UDPROW_OWNER_MODULE *udp_row = &udp_table->table[entry_index];
+
+        /* allocate new active connection item */
+        GuestActiveConnectionList *new_item =
+                                 g_malloc0(sizeof(GuestActiveConnectionList));
+        new_item->value = g_malloc0(sizeof(GuestActiveConnection));
+
+        /* push the connection to the head of the list */
+        new_item->next = connections;
+        connections = new_item;
+
+        new_item->value->source_addr =
+                g_strdup(inet_ntoa(*(struct in_addr *)&udp_row->dwLocalAddr));
+        new_item->value->source_port = htons(udp_row->dwLocalPort);
+        new_item->value->owner_process_id = udp_row->dwOwningPid;
+        new_item->value->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+        new_item->value->protocol = GUEST_IP_PROTOCOL_UDP;
+        new_item->value->start_time = udp_row->liCreateTimestamp.QuadPart;
+    }
+
+    (void)g_free(udp_table);
+    udp_table = NULL;
+
+    bytes_needed = sizeof(MIB_TCPROW_OWNER_PID) * 30;
+
+    /* get the TCP table */
+    for (;;) {
+        tcp_table = g_malloc0(bytes_needed);
+        if (NULL == tcp_table) {
+            error_setg(errp, "Failed allocating active connections table");
+            return NULL;
+        }
+
+        ret = GetExtendedTcpTable(tcp_table,
+                                  &bytes_needed,
+                                  TRUE,
+                                  AF_INET,
+                                  TCP_TABLE_OWNER_MODULE_ALL,
+                                  0);
+        if (NO_ERROR != ret) {
+            (void)g_free(tcp_table);
+            tcp_table = NULL;
+
+            if (ERROR_INSUFFICIENT_BUFFER == ret) {
+                bytes_needed <<= 1;
+                continue;
+            }
+        }
+
+        break;
+    }
+
+    /* add the TCP connections to the list backward */
+    for (entry_index = tcp_table->dwNumEntries - 1;
+         entry_index >= 0;
+         --entry_index) {
+        MIB_TCPROW_OWNER_MODULE *tcp_row = &tcp_table->table[entry_index];
+
+        /* allocate new active connection item */
+        GuestActiveConnectionList *new_item =
+                                  g_malloc0(sizeof(GuestActiveConnectionList));
+        new_item->value = g_malloc0(sizeof(GuestActiveConnection));
+
+        /* push the connection to the head of the list */
+        new_item->next = connections;
+        connections = new_item;
+
+        new_item->value->source_addr =
+                g_strdup(inet_ntoa(*(struct in_addr *)&tcp_row->dwLocalAddr));
+        new_item->value->source_port = htons(tcp_row->dwLocalPort);
+        new_item->value->dest_addr =
+                g_strdup(inet_ntoa(*(struct in_addr *)&tcp_row->dwRemoteAddr));
+        new_item->value->dest_port = htons(tcp_row->dwRemotePort);
+        new_item->value->owner_process_id = tcp_row->dwOwningPid;
+        new_item->value->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+        new_item->value->protocol = GUEST_IP_PROTOCOL_TCP;
+        new_item->value->start_time = tcp_row->liCreateTimestamp.QuadPart;
+
+        switch (tcp_row->dwState) {
+        case MIB_TCP_STATE_CLOSED:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_CLOSED;
+            break;
+        case MIB_TCP_STATE_LISTEN:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_LISTEN;
+            break;
+        case MIB_TCP_STATE_SYN_SENT:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_SYN_SENT;
+            break;
+        case MIB_TCP_STATE_SYN_RCVD:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_SYN_RCVD;
+            break;
+        case MIB_TCP_STATE_ESTAB:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_ESTABLISHED;
+            break;
+        case MIB_TCP_STATE_FIN_WAIT1:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_FIN_WAIT1;
+            break;
+        case MIB_TCP_STATE_FIN_WAIT2:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_FIN_WAIT2;
+            break;
+        case MIB_TCP_STATE_CLOSE_WAIT:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_CLOSE_WAIT;
+            break;
+        case MIB_TCP_STATE_CLOSING:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_CLOSING;
+            break;
+        case MIB_TCP_STATE_LAST_ACK:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_LAST_ACK;
+            break;
+        case MIB_TCP_STATE_TIME_WAIT:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_TIME_WAIT;
+            break;
+        case MIB_TCP_STATE_DELETE_TCB:
+            new_item->value->state = GUEST_TCP_PROTOCOL_STATE_DELETE_TCB;
+            break;
+        }
+    }
+
+    (void)g_free(tcp_table);
+
+    return connections;
+}
 
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 61f8a5a..9df985d 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -971,3 +971,102 @@
 { 'command': 'guest-uptime',
   'returns': 'uint32' }
 
+##
+# @GuestProcessInfo
+#
+# @process-id: the process unique id
+# @parent-id: the process parent unique id
+# @process-name: the name of the process
+# @image-path: full path of the process image
+# @session-id: the session id of the process
+#
+# Since: 2.4
+##
+{ 'type': 'GuestProcessInfo',
+  'data': {'process-id': 'int', 'parent-id': 'int', 'process-name': 'str',
+              'image-path': 'str', 'session-id': 'int'}}
+
+##
+# @guest-get-process-list:
+#
+# Get the list of active processes on the guest operating system
+#
+# Returns: array of active processes
+#
+# Since 2.4
+##
+{ 'command': 'guest-get-process-list',
+  'returns': ['GuestProcessInfo'] }
+
+##
+# @GuestIpProtocol:
+#
+# An enumeration of supported IP protocols
+#
+# @tcp: TCP
+#
+# @udp: UDP
+#
+# Since: 2.4
+##
+{ 'enum': 'GuestIpProtocol',
+  'data': [ 'tcp', 'udp' ] }
+
+##
+# @GuestTcpProtocolState:
+#
+# An enumeration of TCP connection state
+#
+# @closed: CLOSED
+# @listen: LISTEN
+# @syn-sent: SYN_SENT
+# @syn-rcvd: SYN_RCVD
+# @established: ESTABLISHED
+# @fin-wait1: FIN_WAIT1
+# @fin-wait2: FIN_WAIT2
+# @close-wait: CLOSE_WAIT
+# @closing: CLOSING
+# @last-ack: LAST_ACK
+# @time-wait: TIME_WAIT
+# @delete-tcb: DELETE_TCB
+#
+# Since: 2.4
+##
+{ 'enum': 'GuestTcpProtocolState',
+  'data': [ 'closed', 'listen', 'syn-sent', 'syn-rcvd', 'established',
+              'fin-wait1', 'fin-wait2', 'close-wait', 'closing',
+              'last-ack', 'time-wait', 'delete-tcb' ] }
+
+##
+# @GuestActiveConnection
+#
+# @if-family: ipv4 / ipv6
+# @protocol: TCP / UDP
+# @source-addr: the source IP address of the connection
+# @source-port: the source port of the connection
+# @dest-addr: the destination IP address of the connection
+# @dest-port: the destination port of the connection
+# @owner-process_id: the process unique id for the connection owner
+# @state: connection protocol state
+# @start-time: time where bind() was called for the connection
+#
+# Since: 2.4
+##
+{ 'type': 'GuestActiveConnection',
+  'data': {    'source-addr': 'str', 'source-port': 'int', 'dest-addr': 'str',
+              'dest-port': 'int', 'owner-process-id': 'int', 'state': 
'GuestTcpProtocolState',
+              'if-family': 'GuestIpAddressType', 'protocol': 'GuestIpProtocol',
+              'start-time': 'uint64'}}
+
+##
+# @guest-get-active-connections:
+#
+# Get the list of active connections on the guest operating system
+#
+# Returns: array of active connections
+#
+# Since 2.4
+##
+{ 'command': 'guest-get-active-connections',
+  'returns': ['GuestActiveConnection'] }
+
diff --git a/qga/win32-definitions.h b/qga/win32-definitions.h
new file mode 100644
index 0000000..c4f0a2b
--- /dev/null
+++ b/qga/win32-definitions.h
@@ -0,0 +1,110 @@
+
+#ifndef WIN32_DEFINITIONS_H_
+#define WIN32_DEFINITIONS_H_    1
+
+#include "win32-iptypes.h"
+
+#define STATUS_INFO_LENGTH_MISMATCH        (0xC0000004)
+
+typedef
+enum _PROCESSINFOCLASS {
+    ProcessBasicInformation = 0x0000,
+    ProcessDebugPort = 0x0007,
+    ProcessWow64Information = 0x001a,
+    ProcessImageFileName = 0x001b,
+    ProcessBreakOnTermination = 0x001d,
+} PROCESSINFOCLASS;
+
+typedef struct {
+    ULONG          AllocationSize;
+    ULONG          ActualSize;
+    ULONG          Flags;
+    ULONG          Unknown1;
+    UNICODE_STRING Unknown2;
+    HANDLE         InputHandle;
+    HANDLE         OutputHandle;
+    HANDLE         ErrorHandle;
+    UNICODE_STRING CurrentDirectory;
+    HANDLE         CurrentDirectoryHandle;
+    UNICODE_STRING SearchPaths;
+    UNICODE_STRING ApplicationName;
+    UNICODE_STRING CommandLine;
+    PVOID          EnvironmentBlock;
+    ULONG          Unknown[9];
+    UNICODE_STRING Unknown3;
+    UNICODE_STRING Unknown4;
+    UNICODE_STRING Unknown5;
+    UNICODE_STRING Unknown6;
+} PROCESS_PARAMETERS, *PPROCESS_PARAMETERS;
+
+typedef struct {
+    ULONG               AllocationSize;
+    ULONG               Unknown1;
+    HINSTANCE           ProcessHinstance;
+    PVOID               ListDlls;
+    PPROCESS_PARAMETERS ProcessParameters;
+    ULONG               Unknown2;
+    HANDLE              Heap;
+} PEB, *PPEB;
+
+typedef struct {
+    DWORD ExitStatus;
+    PPEB  PebBaseAddress;
+    DWORD AffinityMask;
+    DWORD BasePriority;
+    ULONG UniqueProcessId;
+    ULONG InheritedFromUniqueProcessId;
+}   PROCESS_BASIC_INFORMATION;
+
+typedef
+enum _SYSTEM_INFORMATION_CLASS {
+    SystemBasicInformation = 0x0000,
+    SystemProcessorInformation = 0x0001,
+    SystemPerformanceInformation = 0x0002,
+    SystemTimeOfDayInformation = 0x0003,
+    SystemPathInformation = 0x0004,
+    SystemProcessInformation = 0x0005,
+    SystemDeviceInformation = 0x0007,
+    SystemModuleInformation = 0x000B,
+} SYSTEM_INFORMATION_CLASS;
+
+typedef
+struct _SYSTEM_PROCESS_INFORMATION /* Size=184 */ {
+    ULONG NextEntryOffset; /* Size=4 Offset=0 */
+    ULONG NumberOfThreads; /* Size=4 Offset=4 */
+    LARGE_INTEGER WorkingSetPrivateSize; /* Size=8 Offset=8 */
+    ULONG HardFaultCount; /* Size=4 Offset=16 */
+    ULONG NumberOfThreadsHighWatermark; /* Size=4 Offset=20 */
+    ULONGLONG CycleTime; /* Size=8 Offset=24 */
+    LARGE_INTEGER CreateTime; /* Size=8 Offset=32 */
+    LARGE_INTEGER UserTime; /* Size=8 Offset=40 */
+    LARGE_INTEGER KernelTime; /* Size=8 Offset=48 */
+    UNICODE_STRING ImageName; /* Size=8 Offset=56 */
+    LONG BasePriority; /* Size=4 Offset=64 */
+    PVOID UniqueProcessId; /* Size=4 Offset=68 */
+    PVOID InheritedFromUniqueProcessId; /* Size=4 Offset=72 */
+    ULONG HandleCount; /* Size=4 Offset=76 */
+    ULONG SessionId; /* Size=4 Offset=80 */
+    ULONG UniqueProcessKey; /* Size=4 Offset=84 */
+    ULONG PeakVirtualSize; /* Size=4 Offset=88 */
+    ULONG VirtualSize; /* Size=4 Offset=92 */
+    ULONG PageFaultCount; /* Size=4 Offset=96 */
+    ULONG PeakWorkingSetSize; /* Size=4 Offset=100 */
+    ULONG WorkingSetSize; /* Size=4 Offset=104 */
+    ULONG QuotaPeakPagedPoolUsage; /* Size=4 Offset=108 */
+    ULONG QuotaPagedPoolUsage; /* Size=4 Offset=112 */
+    ULONG QuotaPeakNonPagedPoolUsage; /* Size=4 Offset=116 */
+    ULONG QuotaNonPagedPoolUsage; /* Size=4 Offset=120 */
+    ULONG PagefileUsage; /* Size=4 Offset=124 */
+    ULONG PeakPagefileUsage; /* Size=4 Offset=128 */
+    ULONG PrivatePageCount; /* Size=4 Offset=132 */
+    LARGE_INTEGER ReadOperationCount; /* Size=8 Offset=136 */
+    LARGE_INTEGER WriteOperationCount; /* Size=8 Offset=144 */
+    LARGE_INTEGER OtherOperationCount; /* Size=8 Offset=152 */
+    LARGE_INTEGER ReadTransferCount; /* Size=8 Offset=160 */
+    LARGE_INTEGER WriteTransferCount; /* Size=8 Offset=168 */
+    LARGE_INTEGER OtherTransferCount; /* Size=8 Offset=176 */
+} SYSTEM_PROCESS_INFORMATION;
+
+#endif /* WIN32_DEFINITIONS_H_ */
+
diff --git a/qga/win32-iptypes.h b/qga/win32-iptypes.h
new file mode 100644
index 0000000..ec55300
--- /dev/null
+++ b/qga/win32-iptypes.h
@@ -0,0 +1,412 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+    iptypes.h
+
+--*/
+
+#ifndef IP_TYPES_INCLUDED
+#define IP_TYPES_INCLUDED
+
+#include <time.h>
+
+#define INET_ADDRSTRLEN         (16)
+#define INET6_ADDRSTRLEN        (48)
+
+/* Definitions and structures used by getnetworkparams and
+ getadaptersinfo apis */
+#define MAX_ADAPTER_DESCRIPTION_LENGTH  128
+#define MAX_ADAPTER_NAME_LENGTH         256
+#define MAX_ADAPTER_ADDRESS_LENGTH      8
+#define DEFAULT_MINIMUM_ENTITIES        32
+#define MAX_HOSTNAME_LEN                128
+#define MAX_DOMAIN_NAME_LEN             128
+#define MAX_SCOPE_ID_LEN                256
+
+/*
+ types
+*/
+
+/* Node Type */
+
+#define BROADCAST_NODETYPE              1
+#define PEER_TO_PEER_NODETYPE           2
+#define MIXED_NODETYPE                  4
+#define HYBRID_NODETYPE                 8
+
+/*
+IP_ADDRESS_STRING - store an IP address as a dotted decimal string
+*/
+
+typedef struct {
+    char String[4 * 4];
+} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
+
+/*
+IP_ADDR_STRING - store an IP address with its corresponding subnet mask,
+both as dotted decimal strings
+*/
+
+typedef struct _IP_ADDR_STRING {
+    struct _IP_ADDR_STRING *Next;
+    IP_ADDRESS_STRING IpAddress;
+    IP_MASK_STRING IpMask;
+    DWORD Context;
+} IP_ADDR_STRING, *PIP_ADDR_STRING;
+
+/*
+ADAPTER_INFO - per-adapter information. All IP addresses are stored as
+strings
+*/
+
+typedef struct _IP_ADAPTER_INFO {
+    struct _IP_ADAPTER_INFO *Next;
+    DWORD ComboIndex;
+    char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
+    char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
+    UINT AddressLength;
+    BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
+    DWORD Index;
+    UINT Type;
+    UINT DhcpEnabled;
+    PIP_ADDR_STRING CurrentIpAddress;
+    IP_ADDR_STRING IpAddressList;
+    IP_ADDR_STRING GatewayList;
+    IP_ADDR_STRING DhcpServer;
+    BOOL HaveWins;
+    IP_ADDR_STRING PrimaryWinsServer;
+    IP_ADDR_STRING SecondaryWinsServer;
+    time_t LeaseObtained;
+    time_t LeaseExpires;
+} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
+
+/*
+The following types require Winsock2.
+*/
+
+typedef enum {
+    IpPrefixOriginOther = 0,
+    IpPrefixOriginManual,
+    IpPrefixOriginWellKnown,
+    IpPrefixOriginDhcp,
+    IpPrefixOriginRouterAdvertisement,
+} IP_PREFIX_ORIGIN;
+
+typedef enum {
+    IpSuffixOriginOther = 0,
+    IpSuffixOriginManual,
+    IpSuffixOriginWellKnown,
+    IpSuffixOriginDhcp,
+    IpSuffixOriginLinkLayerAddress,
+    IpSuffixOriginRandom,
+} IP_SUFFIX_ORIGIN;
+
+typedef enum {
+    IpDadStateInvalid    = 0,
+    IpDadStateTentative,
+    IpDadStateDuplicate,
+    IpDadStateDeprecated,
+    IpDadStatePreferred,
+} IP_DAD_STATE;
+
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_UNICAST_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+
+    IP_PREFIX_ORIGIN PrefixOrigin;
+    IP_SUFFIX_ORIGIN SuffixOrigin;
+    IP_DAD_STATE DadState;
+
+    ULONG ValidLifetime;
+    ULONG PreferredLifetime;
+    ULONG LeaseLifetime;
+} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;
+
+typedef struct _IP_ADAPTER_ANYCAST_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_ANYCAST_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+} IP_ADAPTER_ANYCAST_ADDRESS, *PIP_ADAPTER_ANYCAST_ADDRESS;
+
+typedef struct _IP_ADAPTER_MULTICAST_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_MULTICAST_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+} IP_ADAPTER_MULTICAST_ADDRESS, *PIP_ADAPTER_MULTICAST_ADDRESS;
+
+/*
+Per-address Flags
+*/
+#define IP_ADAPTER_ADDRESS_DNS_ELIGIBLE 0x01
+#define IP_ADAPTER_ADDRESS_TRANSIENT    0x02
+
+typedef struct _IP_ADAPTER_DNS_SERVER_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Reserved;
+        };
+    };
+    struct _IP_ADAPTER_DNS_SERVER_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+} IP_ADAPTER_DNS_SERVER_ADDRESS, *PIP_ADAPTER_DNS_SERVER_ADDRESS;
+
+typedef struct _IP_ADAPTER_PREFIX {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_PREFIX *Next;
+    SOCKET_ADDRESS Address;
+    ULONG PrefixLength;
+} IP_ADAPTER_PREFIX, *PIP_ADAPTER_PREFIX;
+
+/*
+Per-adapter Flags
+*/
+#define IP_ADAPTER_DDNS_ENABLED               0x01
+#define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX    0x02
+#define IP_ADAPTER_DHCP_ENABLED               0x04
+#define IP_ADAPTER_RECEIVE_ONLY               0x08
+#define IP_ADAPTER_NO_MULTICAST               0x10
+#define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20
+
+/*
+OperStatus values from RFC 2863
+*/
+typedef enum {
+    IfOperStatusUp = 1,
+    IfOperStatusDown,
+    IfOperStatusTesting,
+    IfOperStatusUnknown,
+    IfOperStatusDormant,
+    IfOperStatusNotPresent,
+    IfOperStatusLowerLayerDown
+} IF_OPER_STATUS;
+
+/*
+Scope levels from RFC 2373 used with ZoneIndices array.
+*/
+typedef enum {
+    ScopeLevelInterface    = 1,
+    ScopeLevelLink         = 2,
+    ScopeLevelSubnet       = 3,
+    ScopeLevelAdmin        = 4,
+    ScopeLevelSite         = 5,
+    ScopeLevelOrganization = 8,
+    ScopeLevelGlobal       = 14
+} SCOPE_LEVEL;
+
+typedef struct _IP_ADAPTER_ADDRESSES {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD IfIndex;
+        };
+    };
+    struct _IP_ADAPTER_ADDRESSES *Next;
+    PCHAR AdapterName;
+    PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
+    PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
+    PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
+    PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
+    PWCHAR DnsSuffix;
+    PWCHAR Description;
+    PWCHAR FriendlyName;
+    BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
+    DWORD PhysicalAddressLength;
+    DWORD Flags;
+    DWORD Mtu;
+    DWORD IfType;
+    IF_OPER_STATUS OperStatus;
+    DWORD Ipv6IfIndex;
+    DWORD ZoneIndices[16];
+    PIP_ADAPTER_PREFIX FirstPrefix;
+} IP_ADAPTER_ADDRESSES, *PIP_ADAPTER_ADDRESSES;
+
+/*
+Flags used as argument to GetAdaptersAddresses().
+"SKIP" flags are added when the default is to include the information.
+"INCLUDE" flags are added when the default is to skip the information.
+*/
+#define GAA_FLAG_SKIP_UNICAST       0x0001
+#define GAA_FLAG_SKIP_ANYCAST       0x0002
+#define GAA_FLAG_SKIP_MULTICAST     0x0004
+#define GAA_FLAG_SKIP_DNS_SERVER    0x0008
+#define GAA_FLAG_INCLUDE_PREFIX     0x0010
+#define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
+
+/*
+IP_PER_ADAPTER_INFO - per-adapter IP information such as DNS server list.
+*/
+
+typedef struct _IP_PER_ADAPTER_INFO {
+    UINT AutoconfigEnabled;
+    UINT AutoconfigActive;
+    PIP_ADDR_STRING CurrentDnsServer;
+    IP_ADDR_STRING DnsServerList;
+} IP_PER_ADAPTER_INFO, *PIP_PER_ADAPTER_INFO;
+
+/*
+FIXED_INFO - the set of IP-related information which does not depend on DHCP
+*/
+
+typedef struct {
+    char HostName[MAX_HOSTNAME_LEN + 4] ;
+    char DomainName[MAX_DOMAIN_NAME_LEN + 4];
+    PIP_ADDR_STRING CurrentDnsServer;
+    IP_ADDR_STRING DnsServerList;
+    UINT NodeType;
+    char ScopeId[MAX_SCOPE_ID_LEN + 4];
+    UINT EnableRouting;
+    UINT EnableProxy;
+    UINT EnableDns;
+} FIXED_INFO, *PFIXED_INFO;
+
+typedef struct ip_interface_name_info {
+    ULONG           Index;      /* Interface Index */
+    ULONG           MediaType;  /* Interface Types - see ipifcons.h */
+    UCHAR           ConnectionType;
+    UCHAR           AccessType;
+    GUID            DeviceGuid; /* Device GUID is the guid of the device */
+                                /* that IP exposes */
+    GUID            InterfaceGuid; /* Interface GUID, if not GUID_NULL is the
+                                GUID for the interface mapped to the device  */
+} IP_INTERFACE_NAME_INFO, *PIP_INTERFACE_NAME_INFO;
+
+typedef enum  {
+  TCP_TABLE_BASIC_LISTENER,
+  TCP_TABLE_BASIC_CONNECTIONS,
+  TCP_TABLE_BASIC_ALL,
+  TCP_TABLE_OWNER_PID_LISTENER,
+  TCP_TABLE_OWNER_PID_CONNECTIONS,
+  TCP_TABLE_OWNER_PID_ALL,
+  TCP_TABLE_OWNER_MODULE_LISTENER,
+  TCP_TABLE_OWNER_MODULE_CONNECTIONS,
+  TCP_TABLE_OWNER_MODULE_ALL
+} TCP_TABLE_CLASS, *PTCP_TABLE_CLASS;
+
+typedef enum  {
+  UDP_TABLE_BASIC,
+  UDP_TABLE_OWNER_PID,
+  UDP_TABLE_OWNER_MODULE
+} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS;
+
+#define TCPIP_OWNING_MODULE_SIZE     (16)
+#define ANY_SIZE                    (1)
+
+typedef enum {
+  MIB_TCP_STATE_UNKNOWN = 0,
+  MIB_TCP_STATE_CLOSED = 1,
+  MIB_TCP_STATE_LISTEN = 2,
+  MIB_TCP_STATE_SYN_SENT = 3,
+  MIB_TCP_STATE_SYN_RCVD = 4,
+  MIB_TCP_STATE_ESTAB = 5,
+  MIB_TCP_STATE_FIN_WAIT1 = 6,
+  MIB_TCP_STATE_FIN_WAIT2 = 7,
+  MIB_TCP_STATE_CLOSE_WAIT = 8,
+  MIB_TCP_STATE_CLOSING = 9,
+  MIB_TCP_STATE_LAST_ACK = 10,
+  MIB_TCP_STATE_TIME_WAIT = 11,
+  MIB_TCP_STATE_DELETE_TCB = 12
+} MIB_TCP_STATE;
+
+typedef struct _MIB_UDPROW {
+  DWORD dwLocalAddr;
+  DWORD dwLocalPort;
+} MIB_UDPROW, *PMIB_UDPROW;
+
+typedef struct _MIB_UDPTABLE {
+  DWORD      dwNumEntries;
+  MIB_UDPROW table[ANY_SIZE];
+} MIB_UDPTABLE, *PMIB_UDPTABLE;
+
+typedef struct _MIB_UDPROW_OWNER_PID {
+  DWORD dwLocalAddr;
+  DWORD dwLocalPort;
+  DWORD dwOwningPid;
+} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID;
+
+typedef struct _MIB_UDPTABLE_OWNER_PID {
+  DWORD                dwNumEntries;
+  MIB_UDPROW_OWNER_PID table[ANY_SIZE];
+} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;
+
+typedef struct _MIB_UDPROW_OWNER_MODULE {
+  DWORD         dwLocalAddr;
+  DWORD         dwLocalPort;
+  DWORD         dwOwningPid;
+  LARGE_INTEGER liCreateTimestamp;
+  union {
+    struct {
+      int SpecificPortBind:1;
+    };
+    int    dwFlags;
+  };
+  ULONGLONG     OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
+} MIB_UDPROW_OWNER_MODULE, *PMIB_UDPROW_OWNER_MODULE;
+
+typedef struct _MIB_UDPTABLE_OWNER_MODULE {
+  DWORD                   dwNumEntries;
+  MIB_UDPROW_OWNER_MODULE table[ANY_SIZE];
+} MIB_UDPTABLE_OWNER_MODULE, *PMIB_UDPTABLE_OWNER_MODULE;
+
+typedef struct _MIB_TCPROW_OWNER_MODULE {
+  DWORD         dwState;
+  DWORD         dwLocalAddr;
+  DWORD         dwLocalPort;
+  DWORD         dwRemoteAddr;
+  DWORD         dwRemotePort;
+  DWORD         dwOwningPid;
+  LARGE_INTEGER liCreateTimestamp;
+  ULONGLONG     OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
+} MIB_TCPROW_OWNER_MODULE, *PMIB_TCPROW_OWNER_MODULE;
+
+typedef struct {
+  DWORD                   dwNumEntries;
+  MIB_TCPROW_OWNER_MODULE table[ANY_SIZE];
+} MIB_TCPTABLE_OWNER_MODULE, *PMIB_TCPTABLE_OWNER_MODULE;
+
+typedef struct _MIB_TCPROW_OWNER_PID {
+  DWORD dwState;
+  DWORD dwLocalAddr;
+  DWORD dwLocalPort;
+  DWORD dwRemoteAddr;
+  DWORD dwRemotePort;
+  DWORD dwOwningPid;
+} MIB_TCPROW_OWNER_PID, *PMIB_TCPROW_OWNER_PID;
+
+typedef struct {
+  DWORD                dwNumEntries;
+  MIB_TCPROW_OWNER_PID table[ANY_SIZE];
+} MIB_TCPTABLE_OWNER_PID, *PMIB_TCPTABLE_OWNER_PID;
+
+#endif /* IP_TYPES_INCLUDED */
+
-- 
2.3.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]