Author: mladen.turk(a)jboss.com
Date: 2007-09-09 05:20:58 -0400 (Sun, 09 Sep 2007)
New Revision: 993
Modified:
trunk/sight/native/include/sight_local.h
trunk/sight/native/os/linux/tcpstat.c
trunk/sight/native/share/jnu.c
Log:
Implement TCP lister
Modified: trunk/sight/native/include/sight_local.h
===================================================================
--- trunk/sight/native/include/sight_local.h 2007-09-08 16:45:38 UTC (rev 992)
+++ trunk/sight/native/include/sight_local.h 2007-09-09 09:20:58 UTC (rev 993)
@@ -426,8 +426,7 @@
const char *sight_inet_ntop4(const unsigned char *, char *, size_t);
const char *sight_inet_ntop6(const unsigned char *, char *, size_t);
-const unsigned char *sight_hex2bin(const unsigned char *, unsigned char *,
- size_t);
+int sight_hex2bin(const char *, unsigned char *, size_t);
jobject sight_new_netaddr_class(SIGHT_STDARGS);
jobjectArray sight_new_netaddr_array(SIGHT_STDARGS, jsize);
Modified: trunk/sight/native/os/linux/tcpstat.c
===================================================================
--- trunk/sight/native/os/linux/tcpstat.c 2007-09-08 16:45:38 UTC (rev 992)
+++ trunk/sight/native/os/linux/tcpstat.c 2007-09-09 09:20:58 UTC (rev 993)
@@ -153,8 +153,43 @@
sight_unload_class(_E, &_clazzn);
}
+#define PROC_NET_FS "/proc/net/"
static const char *eiftype = "Unsupported NetworkAddressFamily type";
+/* These enums are used by IPX too. :-( */
+typedef 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 */
+} sight_tcp_state_e;
+
+static int tcp2sstate[] = {
+ 0,
+ SIGHT_TCP_ESTABLISHED,
+ SIGHT_TCP_SYN_SENT,
+ SIGHT_TCP_SYN_RCVD,
+ SIGHT_TCP_FIN_WAIT1,
+ SIGHT_TCP_FIN_WAIT2,
+ SIGHT_TCP_TIME_WAIT,
+ SIGHT_TCP_CLOSED,
+ SIGHT_TCP_CLOSE_WAIT,
+ SIGHT_TCP_LAST_ACK,
+ SIGHT_TCP_LISTENING,
+ SIGHT_TCP_CLOSING,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
/* Initialize volume enumeration */
SIGHT_EXPORT_DECLARE(void, TcpStatistics, info0)(SIGHT_STDARGS,
jobject thiz,
@@ -162,21 +197,51 @@
jlong pool)
{
apr_status_t rc = APR_ENOTIMPL;
- sight_arr_t *tgrp;
+ sight_arr_t *tnet;
int i;
- int RtoAlgorithm, RtoMin, RtoMax, MaxConn, ActiveOpens, PassiveOpens, AttemptFails,
EstabResets, CurrEstab, InSegs, OutSegs, RetransSegs, InErrs, OutRsts;
+ int RtoAlgorithm, RtoMin, RtoMax, MaxConn, ActiveOpens, PassiveOpens;
+ int AttemptFails, EstabResets, CurrEstab, InSegs, OutSegs, RetransSegs;
+ int InErrs, OutRsts;
+ int NumCons = 0;
UNREFERENCED_O;
+ if (iftype == 1) {
+ if (!(tnet = sight_arr_rload(PROC_NET_FS "sockstat"))) {
+ throwAprException(_E, apr_get_os_error());
+ }
+ for (i = 0; i < tnet->siz; i++) {
+ if (memcmp(tnet->arr.ca[i], "TCP: inuse ", 11) == 0) {
+ NumCons = atoi(tnet->arr.ca[i] + 11);
+ break;
+ }
+ }
+ }
+ else if (iftype == 2) {
+ if (!(tnet = sight_arr_rload(PROC_NET_FS "sockstat6"))) {
+ throwAprException(_E, apr_get_os_error());
+ }
+ for (i = 0; i < tnet->siz; i++) {
+ if (memcmp(tnet->arr.ca[i], "TCP6: inuse ", 12) == 0) {
+ NumCons = atoi(tnet->arr.ca[i] + 12);
+ break;
+ }
+ }
+ }
+ else {
+ throwOSException(_E, eiftype);
+ return;
+ }
+ sight_arr_free(tnet);
- if (!(tgrp = sight_arr_rload("/proc/net/snmp"))) {
+ if (!(tnet = sight_arr_rload(PROC_NET_FS "snmp"))) {
throwAprException(_E, apr_get_os_error());
}
/* Get the information corresponding to the second entry Tcp: */
- for (i = 0; i < tgrp->siz; i++) {
- if (memcmp(tgrp->arr.ca[i], "Tcp:", 4) == 0) {
- if (memcmp(tgrp->arr.ca[i], "Tcp: RtoAlgorithm", 17) != 0) {
- sscanf(tgrp->arr.ca[i], "Tcp: %d %d %d %d %d %d %d %d %d %d %d %d
%d %d",
+ for (i = 0; i < tnet->siz; i++) {
+ if (memcmp(tnet->arr.ca[i], "Tcp:", 4) == 0) {
+ if (memcmp(tnet->arr.ca[i], "Tcp: RtoAlgorithm", 17) != 0) {
+ sscanf(tnet->arr.ca[i], "Tcp: %d %d %d %d %d %d %d %d %d %d %d %d
%d %d",
&RtoAlgorithm, &RtoMin, &RtoMax, &MaxConn,
&ActiveOpens,
&PassiveOpens, &AttemptFails, &EstabResets,
&CurrEstab,
&InSegs, &OutSegs, &RetransSegs, &InErrs,
&OutRsts);
@@ -184,7 +249,7 @@
}
}
}
- sight_arr_free(tgrp);
+ sight_arr_free(tnet);
/* Fill the info (RtoAlgorithm not used) */
SET_IFIELD_I(0000, thiz, RtoMin);
@@ -200,14 +265,51 @@
SET_IFIELD_I(0010, thiz, RetransSegs);
SET_IFIELD_I(0011, thiz, InErrs);
SET_IFIELD_I(0012, thiz, OutRsts);
- /* XXX: SET_IFIELD_I(0013, thiz, s.dwNumConns); */
+ SET_IFIELD_I(0013, thiz, NumCons);
}
+typedef struct tcpconn_enum_t {
+ int type;
+ int idx;
+ sight_arr_t *tnet;
+} tcpconn_enum_t;
+
+
/* Initialize TCP conn enumeration */
SIGHT_EXPORT_DECLARE(jlong, TcpStatistics, enum0)(SIGHT_STDARGS,
jint iftype,
jlong pool)
{
+ tcpconn_enum_t *e;
+
+ UNREFERENCED_O;
+ if (iftype < 1 || iftype > 2) {
+ throwOSException(_E, eiftype);
+ return 0;
+ }
+ if (!(e = (tcpconn_enum_t *)calloc(1, sizeof(tcpconn_enum_t)))) {
+ throwAprMemoryException(_E, THROW_FMARK,
+ apr_get_os_error());
+ return 0;
+ }
+ e->type = iftype;
+ if (iftype == 1) {
+ if (!(e->tnet = sight_arr_rload(PROC_NET_FS "tcp"))) {
+ throwAprException(_E, apr_get_os_error());
+ goto cleanup;
+ }
+ }
+ else {
+ if (!(e->tnet = sight_arr_rload(PROC_NET_FS "tcp6"))) {
+ throwAprException(_E, apr_get_os_error());
+ goto cleanup;
+ }
+ }
+
+ return P2J(e);
+cleanup:
+ sight_arr_free(e->tnet);
+ free(e);
return 0;
}
@@ -215,7 +317,15 @@
SIGHT_EXPORT_DECLARE(jint, TcpStatistics, enum1)(SIGHT_STDARGS,
jlong handle)
{
- return 0;
+ tcpconn_enum_t *e = J2P(handle, tcpconn_enum_t *);
+
+ UNREFERENCED_STDARGS;
+ if (e && e->tnet) {
+ e->idx = 1;
+ return e->tnet->siz - 1; /* Skip description field */
+ }
+ else
+ return 0;
}
SIGHT_EXPORT_DECLARE(void, TcpStatistics, enum2)(SIGHT_STDARGS,
@@ -223,12 +333,103 @@
jint index,
jlong handle)
{
+ jint pid = -1;
+ jint state = 0;
+ jint lp = 0, rp = 0;
+ jobject la, ra;
+ char las[128] = "";
+ char ras[128] = "";
+ char ssi[32] = "";
+ struct in_addr ial, iar;
+ jlong cts = 0;
+ unsigned long rxq, txq, timelen, retr, inode;
+ int num, d, uid, timer_run, timeout;
+ char more[512];
+
+ tcpconn_enum_t *e = J2P(handle, tcpconn_enum_t *);
+
+ if (!e || !e->tnet)
+ return;
+ if (e->idx > e->tnet->siz) {
+ /* TODO: Throw overflow */
+ return;
+ }
+ num = sscanf(e->tnet->arr.ca[e->idx],
+ "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld
%512s",
+ &d, las, &lp, ras, &rp, &state,
+ &txq, &rxq, &timer_run, &timelen, &retr,
+ &uid, &timeout, &inode, more);
+
+ if (e->type == 1) {
+ /* IPV4 entries */
+ int al;
+ struct in_addr in4;
+
+ al = sscanf(las, "%X", &in4.s_addr);
+ if (al == 1)
+ inet_ntop(AF_INET, &in4, las, 64);
+ else
+ las[0] = '\0';
+
+ al = sscanf(ras, "%X", &in4.s_addr);
+ if (al == 1)
+ inet_ntop(AF_INET, &in4, ras, 64);
+ else
+ ras[0] = '\0';
+ }
+ else {
+ /* IPV6 entries */
+ int al;
+ struct in6_addr in6;
+
+ al = sscanf(las, "%08X%08X%08X%08X",
+ &in6.s6_addr32[0], &in6.s6_addr32[1],
+ &in6.s6_addr32[2], &in6.s6_addr32[3]);
+
+ if (al == 4)
+ sight_inet_ntop6(in6.s6_addr, las, 64);
+ else
+ las[0] = '\0';
+ al = sscanf(ras, "%08X%08X%08X%08X",
+ &in6.s6_addr32[0], &in6.s6_addr32[1],
+ &in6.s6_addr32[2], &in6.s6_addr32[3]);
+
+ if (al == 4)
+ sight_inet_ntop6(in6.s6_addr, ras, 64);
+ else
+ ras[0] = '\0';
+ }
+ /* TODO: See what's the actual value of timelen */
+ cts = timelen;
+ sight_tcpconn_set_pid(_E, conn, pid);
+ sight_tcpconn_set_cts(_E, conn, cts);
+ sight_tcpconn_set_state(_E, conn, tcp2sstate[state & 0xFF]);
+
+ la = sight_new_netaddr_class(_E, _O);
+ sight_netaddr_set_addr(_E, la, las);
+ sight_netaddr_set_port(_E, la, lp);
+ sight_tcpconn_set_local(_E, conn, la);
+ (*_E)->DeleteLocalRef(_E, la);
+
+ ra = sight_new_netaddr_class(_E, _O);
+ sight_netaddr_set_addr(_E, ra, ras);
+ sight_netaddr_set_port(_E, ra, rp);
+ sight_tcpconn_set_remote(_E, conn, ra);
+ (*_E)->DeleteLocalRef(_E, ra);
+ /* Increment the index counter */
+ e->idx++;
}
/* Close TCP conn enumeration */
SIGHT_EXPORT_DECLARE(void, TcpStatistics, enum3)(SIGHT_STDARGS,
jlong handle)
{
+ tcpconn_enum_t *e = J2P(handle, tcpconn_enum_t *);
+ UNREFERENCED_STDARGS;
+ if (e) {
+ sight_arr_free(e->tnet);
+ free(e);
+ }
}
Modified: trunk/sight/native/share/jnu.c
===================================================================
--- trunk/sight/native/share/jnu.c 2007-09-08 16:45:38 UTC (rev 992)
+++ trunk/sight/native/share/jnu.c 2007-09-09 09:20:58 UTC (rev 993)
@@ -892,45 +892,42 @@
}
}
-static unsigned char uch4hex(unsigned char i)
+static int uch4hex(int i)
{
if (apr_isdigit(i))
return i - '0';
else if (apr_isupper(i))
- return i - 'A';
+ return i - 'A' + 10;
else
- return i - 'a';
+ return i - 'a' + 10;
}
/*
* Convert hex to array
*/
-const unsigned char *sight_hex2bin(const unsigned char *src, unsigned char *dst,
- size_t size)
+int sight_hex2bin(const char *src, unsigned char *dst,
+ size_t size)
{
- char tmp[64], *tp;
- int i;
- char *next = src;
+ unsigned char tmp[64], *tp;
+ int i, len = 0;
+ const char *next = src;
tp = tmp;
- for (i = 0; i < 62; i++) {
- unsigned char ch;
- if (!*next || !apr_isxdigit(*next))
- break;
- ch = (uch4hex(*next++) << 4);
- if (!*next || !apr_isxdigit(*next))
- break;
- ch |= uch4hex(*next++);
- *tp++ = ch;
+ for (i = 0; i < 62, *next; i++) {
+ int ch = uch4hex(*next++);
+ ch = (ch << 4) | uch4hex(*next++);
+ *tp++ = (unsigned char)ch;
}
- *tp = '\0';
/*
* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size) {
errno = ENOSPC;
- return NULL;
+ return -1;
}
- strcpy(dst, tmp);
- return dst;
+ else
+ len = (int)(tp - tmp);
+ if (len)
+ memcpy(dst, tmp, size);
+ return len;
}