Blame agent/mibgroup/misc/ipfwacc.c

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