diff options
Diffstat (limited to 'agent/mibgroup/misc/ipfwacc.c')
-rw-r--r-- | agent/mibgroup/misc/ipfwacc.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/agent/mibgroup/misc/ipfwacc.c b/agent/mibgroup/misc/ipfwacc.c new file mode 100644 index 0000000..cca9871 --- /dev/null +++ b/agent/mibgroup/misc/ipfwacc.c @@ -0,0 +1,365 @@ +/**************************************************************************** + * Module for ucd-snmpd reading IP Firewall accounting rules. * + * It reads "/proc/net/ip_acct". If the file has a wrong format it silently * + * returns erroneous data but doesn't do anything harmfull. Based (on the * + * output of) mib2c, wombat.c, proc.c and the Linux kernel. * + * Author: Cristian.Estan@net.utcluj.ro * + ***************************************************************************/ + +#include <net-snmp/net-snmp-config.h> + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "util_funcs/header_simple_table.h" +#include "ipfwacc.h" + +/* + * According to the 2.0.33 Linux kernel, assuming we use ipv4 any line from + * * "/proc/net/ip_acct should fit into + * * 8+1+8+2+8+1+8+1+16+1+8+1+4+1+2+1+2+1+20+20+10*(1+5)+2+2+2+2=182 + * * characters+ newline. + */ +#define IPFWRULELEN 200 + +#define IP_FW_F_ALL 0x0000 /* This is a universal packet firewall */ +#define IP_FW_F_TCP 0x0001 /* This is a TCP packet firewall */ +#define IP_FW_F_UDP 0x0002 /* This is a UDP packet firewall */ +#define IP_FW_F_ICMP 0x0003 /* This is a ICMP packet firewall */ +#define IP_FW_F_KIND 0x0003 /* Mask to isolate firewall kind */ +#define IP_FW_F_SRNG 0x0008 /* The first two src ports are a min * + * and max range (stored in host byte * + * order). */ +#define IP_FW_F_DRNG 0x0010 /* The first two dst ports are a min * + * and max range (stored in host byte * + * order). * + * (ports[0] <= port <= ports[1]) */ +#define IP_FW_F_BIDIR 0x0040 /* For bidirectional firewalls */ +#define IP_FW_F_ACCTIN 0x1000 /* Account incoming packets only. */ +#define IP_FW_F_ACCTOUT 0x2000 /* Account outgoing packets only. */ + +static unsigned char rule[IPFWRULELEN]; /*Buffer for reading a line from + * /proc/net/ip_acct. Care has been taken + * not to read beyond the end of this + * buffer, even if rules are in an + * unexpected format + */ + +/* + * This function reads the rule with the given number into the buffer. It + * * returns the number of rule read or 0 if the number is invalid or other + * * problems occur. If the argument is 0 it returns the number of accounting + * * rules. No caching of rules is done. + */ + +static int +readrule(unsigned int number) +{ + int i; + FILE *f = fopen("/proc/net/ip_acct", "rt"); + + if (!f) + return 0; + /* + * get rid of "IP accounting rules" line + */ + if (!fgets((char *) rule, sizeof(rule), f)) { + fclose(f); + return 0; + } + for (i = 1; i != number; i++) + if (!fgets((char *) rule, sizeof(rule), f)) { + fclose(f); + return (number ? 0 : (i - 1)); + } + if (!fgets((char *) rule, sizeof(rule), f)) { + fclose(f); + return 0; + } + fclose(f); + return i; +} + +static unsigned long ret_val; /* Used by var_ipfwacc to return ulongs */ + +/* + * This function converts the hexadecimal representation of an IP address from + * * the rule buffer to an unsigned long. The result is stored in the ret_val + * * variable. The parameter indicates the position where the address starts. It + * * only works with uppercase letters and assumes input is correct. Had to use + * * this because stol returns a signed long. + */ + +static inline void +atoip(int pos) +{ + int i; + + ret_val = 0; + for (i = 0; i < 32; i += 8) { + unsigned long value = (((rule[pos]) >= '0' && rule[pos] <= '9') ? + rule[pos] - '0' : rule[pos] - 'A' + 10); + pos++; + value = (value << 4) + (((rule[pos]) >= '0' && rule[pos] <= '9') ? + rule[pos] - '0' : rule[pos] - 'A' + 10); + pos++; + ret_val |= (value << i); + } +} + +/* + * This function parses the flags field from the line in the buffer + */ + +static unsigned long int +getflags(void) +{ + unsigned long int flags; + int i = 37; /* position in the rule */ + + /* + * skipping via name + */ + while (rule[i] != ' ' && i < IPFWRULELEN - 12) + i++; + /* + * skipping via address + */ + i += 10; + for (flags = 0; rule[i] != ' ' && i < IPFWRULELEN - 1; i++) { + int value = (((rule[i]) >= '0' && rule[i] <= '9') ? + rule[i] - '0' : rule[i] - 'A' + 10); + flags = (flags << 4) + value; + } + return flags; +} + +/* + * This function reads into ret_val a field from the rule buffer. The field + * * is a base 10 long integer and the parameter skip tells us how many fields + * * to skip after the "via addrress" field (including the flag field) + */ + +static void +getnumeric(int skip) +{ + int i = 37; /* position in the rule */ + + /* + * skipping via name + */ + while (rule[i] != ' ' && i < IPFWRULELEN - 12) + i++; + /* + * skipping via address + */ + i += 10; + while (skip > 0) { + skip--; + /* + * skipping field, than subsequent spaces + */ + while (rule[i] != ' ' && i < IPFWRULELEN - 2) + i++; + while (rule[i] == ' ' && i < IPFWRULELEN - 1) + i++; + } + for (ret_val = 0; rule[i] != ' ' && i < IPFWRULELEN - 1; i++) + ret_val = ret_val * 10 + rule[i] - '0'; +} + +/* + * this variable defines function callbacks and type return information + * for the ipfwaccounting mib + */ + +struct variable2 ipfwacc_variables[] = { + {IPFWACCINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCINDEX}}, + {IPFWACCSRCADDR, ASN_IPADDRESS, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCSRCADDR}}, + {IPFWACCSRCNM, ASN_IPADDRESS, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCSRCNM}}, + {IPFWACCDSTADDR, ASN_IPADDRESS, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCDSTADDR}}, + {IPFWACCDSTNM, ASN_IPADDRESS, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCDSTNM}}, + {IPFWACCVIANAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCVIANAME}}, + {IPFWACCVIAADDR, ASN_IPADDRESS, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCVIAADDR}}, + {IPFWACCPROTO, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPROTO}}, + {IPFWACCBIDIR, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCBIDIR}}, + {IPFWACCDIR, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCDIR}}, + {IPFWACCBYTES, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCBYTES}}, + {IPFWACCPACKETS, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPACKETS}}, + {IPFWACCNSRCPRTS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCNSRCPRTS}}, + {IPFWACCNDSTPRTS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCNDSTPRTS}}, + {IPFWACCSRCISRNG, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCSRCISRNG}}, + {IPFWACCDSTISRNG, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCDSTISRNG}}, + {IPFWACCPORT1, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT1}}, + {IPFWACCPORT2, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT2}}, + {IPFWACCPORT3, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT3}}, + {IPFWACCPORT4, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT4}}, + {IPFWACCPORT5, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT5}}, + {IPFWACCPORT6, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT6}}, + {IPFWACCPORT7, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT7}}, + {IPFWACCPORT8, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT8}}, + {IPFWACCPORT9, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT9}}, + {IPFWACCPORT10, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_ipfwacc, 1, {IPFWACCPORT10}} +}; + +oid ipfwacc_variables_oid[] = + { 1, 3, 6, 1, 4, 1, 2021, 13, 1, 1, 1 }; + +void +init_ipfwacc(void) +{ + REGISTER_MIB("misc/ipfwacc", ipfwacc_variables, variable2, + ipfwacc_variables_oid); +} + + +u_char * +var_ipfwacc(struct variable *vp, + oid * name, + size_t * length, + int exact, size_t * var_len, WriteMethod ** write_method) +{ + *write_method = 0; /* assume it isnt writable for the time being */ + *var_len = sizeof(ret_val); /* assume an integer and change later if not */ + + if (header_simple_table + (vp, name, length, exact, var_len, write_method, readrule(0))) + return (NULL); + + if (readrule(name[*length - 1])) { + /* + * this is where we do the value assignments for the mib results. + */ + switch (vp->magic) { + case IPFWACCINDEX: + ret_val = name[*length - 1]; + return ((u_char *) (&ret_val)); + case IPFWACCSRCADDR: + atoip(0); + return ((u_char *) (&ret_val)); + case IPFWACCSRCNM: + atoip(9); + return ((u_char *) (&ret_val)); + case IPFWACCDSTADDR: + atoip(19); + return ((u_char *) (&ret_val)); + case IPFWACCDSTNM: + atoip(28); + return ((u_char *) (&ret_val)); + case IPFWACCVIANAME: + { + int i = 37; /* position in the rule */ + while (rule[i] != ' ' && i < IPFWRULELEN - 1) + i++; + rule[i] = 0; + return (rule + 37); + } + case IPFWACCVIAADDR: + { + int i = 37; /* position in the rule */ + while (rule[i] != ' ' && i < IPFWRULELEN - 9) + i++; + atoip(i + 1); + return ((u_char *) (&ret_val)); + } + case IPFWACCPROTO: + switch (getflags() & IP_FW_F_KIND) { + case IP_FW_F_ALL: + ret_val = 2; + return ((u_char *) (&ret_val)); + case IP_FW_F_TCP: + ret_val = 3; + return ((u_char *) (&ret_val)); + case IP_FW_F_UDP: + ret_val = 4; + return ((u_char *) (&ret_val)); + case IP_FW_F_ICMP: + ret_val = 5; + return ((u_char *) (&ret_val)); + default: + ret_val = 1; + return ((u_char *) (&ret_val)); + } + case IPFWACCBIDIR: + ret_val = ((getflags() & IP_FW_F_BIDIR) ? 2 : 1); + return ((u_char *) (&ret_val)); + case IPFWACCDIR: + ret_val = (getflags() & (IP_FW_F_ACCTIN | IP_FW_F_ACCTOUT)); + if (ret_val == IP_FW_F_ACCTIN) + ret_val = 2; + else if (ret_val == IP_FW_F_ACCTOUT) + ret_val = 3; + else + ret_val = 1; + return ((u_char *) (&ret_val)); + case IPFWACCBYTES: + getnumeric(4); + return ((u_char *) (&ret_val)); + case IPFWACCPACKETS: + getnumeric(3); + return ((u_char *) (&ret_val)); + case IPFWACCNSRCPRTS: + getnumeric(1); + return ((u_char *) (&ret_val)); + case IPFWACCNDSTPRTS: + getnumeric(2); + return ((u_char *) (&ret_val)); + case IPFWACCSRCISRNG: + ret_val = ((getflags() & IP_FW_F_SRNG) ? 1 : 2); + return ((u_char *) (&ret_val)); + case IPFWACCDSTISRNG: + ret_val = ((getflags() & IP_FW_F_DRNG) ? 1 : 2); + return ((u_char *) (&ret_val)); + case IPFWACCPORT1: + case IPFWACCPORT2: + case IPFWACCPORT3: + case IPFWACCPORT4: + case IPFWACCPORT5: + case IPFWACCPORT6: + case IPFWACCPORT7: + case IPFWACCPORT8: + case IPFWACCPORT9: + case IPFWACCPORT10: + getnumeric(5 + (vp->magic) - IPFWACCPORT1); + return ((u_char *) (&ret_val)); + } + } + return NULL; +} |