/*************************************************************************** * Copyright (C) 04/2007 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include "logging.h" #include "plugins.h" #include "probe.h" #define DS_L3PROTO 1 #define DS_L4PROTO 2 #define DS_TCP 3 struct sammler_plugin plugin; static struct nfct_handle *cth; struct ct_values { int total; int local; int nated; int unreplied; int proto_tcp; int proto_udp; int proto_unknown; int tcp_state[10]; }; static const char *l3proto_ds_def = { "DS:total:GAUGE:15:0:U " "DS:local:GAUGE:15:0:U " "DS:nated:GAUGE:15:0:U " "DS:unreplied:GAUGE:15:0:U " }; static const char *l4proto_ds_def = { "DS:tcp:GAUGE:15:0:U " "DS:udp:GAUGE:15:0:U " "DS:unknown:GAUGE:15:0:U " }; static const char *tcp_ds_def = { "DS:none:GAUGE:15:0:U " "DS:syn_sent:GAUGE:15:0:U " "DS:syn_recv:GAUGE:15:0:U " "DS:established:GAUGE:15:0:U " "DS:fin_wait:GAUGE:15:0:U " "DS:close_wait:GAUGE:15:0:U " "DS:last_ack:GAUGE:15:0:U " "DS:time_wait:GAUGE:15:0:U " "DS:close:GAUGE:15:0:U " "DS:listen:GAUGE:15:0:U " }; static const char * get_ds(int ds_id) { switch (ds_id) { case DS_L3PROTO: return l3proto_ds_def; case DS_L4PROTO: return l4proto_ds_def; case DS_TCP: return tcp_ds_def; default: return NULL; } } static int probe_cb(void *arg, unsigned int flags, int type, void *privdata) { struct nfct_conntrack *ct = (struct nfct_conntrack *)arg; struct ct_values *data = (struct ct_values *)privdata; data->total++; if (ct->status & IPS_NAT_MASK) data->nated++; else data->local++; if (!(ct->status & IPS_SEEN_REPLY)) data->unreplied++; switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) { case IPPROTO_TCP: data->proto_tcp++; data->tcp_state[ct->protoinfo.tcp.state]++; break; case IPPROTO_UDP: data->proto_udp++; break; default: data->proto_unknown++; break; } return 0; } static int probe(void) { struct ct_values data; memset(&data, 0, sizeof(data)); nfct_register_callback(cth, probe_cb, &data); if (nfct_dump_conntrack_table(cth, AF_INET) < 0) { log_print(LOG_WARN, "plugin conntrack: nfct_dump_conntrack_table()"); return -1; } probe_submit(&plugin, "conntrack.rrd", DS_L3PROTO, "%d:%d:%d:%d", data.total, data.local, data.nated, data.unreplied); probe_submit(&plugin, "conntrack-proto.rrd", DS_L4PROTO, "%d:%d:%d", data.proto_tcp, data.proto_udp, data.proto_unknown); probe_submit(&plugin, "conntrack-tcp.rrd", DS_TCP, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", data.tcp_state[0], data.tcp_state[1], data.tcp_state[2], data.tcp_state[3], data.tcp_state[4], data.tcp_state[5], data.tcp_state[6], data.tcp_state[7], data.tcp_state[8], data.tcp_state[9]); return 0; } static int init(void) { cth = nfct_open(CONNTRACK, 0); if (cth == NULL) { log_print(LOG_WARN, "plugin conntrack: nfct_open()"); return -1; } return 0; } static int fini(void) { nfct_close(cth); return 0; } struct sammler_plugin plugin = { .name = "conntrack", .interval = 10, .init = &init, .fini = &fini, .probe = &probe, .get_ds = &get_ds, };