ipfwacc.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:12k
- /****************************************************************************
- * 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.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(rule, sizeof(rule), f)) {
- fclose(f);
- return 0;
- }
- for (i = 1; i != number; i++)
- if (!fgets(rule, sizeof(rule), f)) {
- fclose(f);
- return (number ? 0 : (i - 1));
- }
- if (!fgets(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, RONLY, var_ipfwacc, 1, {IPFWACCINDEX}},
- {IPFWACCSRCADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
- {IPFWACCSRCADDR}},
- {IPFWACCSRCNM, ASN_IPADDRESS, RONLY, var_ipfwacc, 1, {IPFWACCSRCNM}},
- {IPFWACCDSTADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
- {IPFWACCDSTADDR}},
- {IPFWACCDSTNM, ASN_IPADDRESS, RONLY, var_ipfwacc, 1, {IPFWACCDSTNM}},
- {IPFWACCVIANAME, ASN_OCTET_STR, RONLY, var_ipfwacc, 1,
- {IPFWACCVIANAME}},
- {IPFWACCVIAADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
- {IPFWACCVIAADDR}},
- {IPFWACCPROTO, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPROTO}},
- {IPFWACCBIDIR, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCBIDIR}},
- {IPFWACCDIR, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCDIR}},
- {IPFWACCBYTES, ASN_COUNTER, RONLY, var_ipfwacc, 1, {IPFWACCBYTES}},
- {IPFWACCPACKETS, ASN_COUNTER, RONLY, var_ipfwacc, 1, {IPFWACCPACKETS}},
- {IPFWACCNSRCPRTS, ASN_INTEGER, RONLY, var_ipfwacc, 1,
- {IPFWACCNSRCPRTS}},
- {IPFWACCNDSTPRTS, ASN_INTEGER, RONLY, var_ipfwacc, 1,
- {IPFWACCNDSTPRTS}},
- {IPFWACCSRCISRNG, ASN_INTEGER, RONLY, var_ipfwacc, 1,
- {IPFWACCSRCISRNG}},
- {IPFWACCDSTISRNG, ASN_INTEGER, RONLY, var_ipfwacc, 1,
- {IPFWACCDSTISRNG}},
- {IPFWACCPORT1, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT1}},
- {IPFWACCPORT2, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT2}},
- {IPFWACCPORT3, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT3}},
- {IPFWACCPORT4, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT4}},
- {IPFWACCPORT5, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT5}},
- {IPFWACCPORT6, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT6}},
- {IPFWACCPORT7, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT7}},
- {IPFWACCPORT8, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT8}},
- {IPFWACCPORT9, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT9}},
- {IPFWACCPORT10, ASN_INTEGER, 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;
- }