ipfwacc.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:12k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /****************************************************************************
  2.  * Module for ucd-snmpd reading IP Firewall accounting rules.               *
  3.  * It reads "/proc/net/ip_acct". If the file has a wrong format it silently *
  4.  * returns erroneous data but doesn't do anything harmfull. Based (on the   *
  5.  * output of) mib2c, wombat.c, proc.c and the Linux kernel.                 *
  6.  * Author: Cristian.Estan@net.utcluj.ro                                     *
  7.  ***************************************************************************/
  8. #include <net-snmp/net-snmp-config.h>
  9. #if TIME_WITH_SYS_TIME
  10. # include <sys/time.h>
  11. # include <time.h>
  12. #else
  13. # if HAVE_SYS_TIME_H
  14. #  include <sys/time.h>
  15. # else
  16. #  include <time.h>
  17. # endif
  18. #endif
  19. #include <net-snmp/net-snmp-includes.h>
  20. #include <net-snmp/agent/net-snmp-agent-includes.h>
  21. #include "util_funcs.h"
  22. #include "ipfwacc.h"
  23. /*
  24.  * According to the 2.0.33 Linux kernel, assuming we use ipv4 any line from
  25.  * * "/proc/net/ip_acct should fit into
  26.  * * 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
  27.  * * characters+ newline.
  28.  */
  29. #define IPFWRULELEN 200
  30. #define IP_FW_F_ALL     0x0000  /* This is a universal packet firewall */
  31. #define IP_FW_F_TCP     0x0001  /* This is a TCP packet firewall      */
  32. #define IP_FW_F_UDP     0x0002  /* This is a UDP packet firewall      */
  33. #define IP_FW_F_ICMP    0x0003  /* This is a ICMP packet firewall     */
  34. #define IP_FW_F_KIND    0x0003  /* Mask to isolate firewall kind      */
  35. #define IP_FW_F_SRNG    0x0008  /* The first two src ports are a min  *
  36.                                  * and max range (stored in host byte *
  37.                                  * order).                            */
  38. #define IP_FW_F_DRNG    0x0010  /* The first two dst ports are a min  *
  39.                                  * and max range (stored in host byte *
  40.                                  * order).                            *
  41.                                  * (ports[0] <= port <= ports[1])     */
  42. #define IP_FW_F_BIDIR   0x0040  /* For bidirectional firewalls        */
  43. #define IP_FW_F_ACCTIN  0x1000  /* Account incoming packets only.     */
  44. #define IP_FW_F_ACCTOUT 0x2000  /* Account outgoing packets only.     */
  45. static unsigned char rule[IPFWRULELEN]; /*Buffer for reading a line from
  46.                                          * /proc/net/ip_acct. Care has been taken
  47.                                          * not to read beyond the end of this 
  48.                                          * buffer, even if rules are in an 
  49.                                          * unexpected format
  50.                                          */
  51. /*
  52.  * This function reads the rule with the given number into the buffer. It
  53.  * * returns the number of rule read or 0 if the number is invalid or other
  54.  * * problems occur. If the argument is 0 it returns the number of accounting
  55.  * * rules. No caching of rules is done.
  56.  */
  57. static int
  58. readrule(unsigned int number)
  59. {
  60.     int             i;
  61.     FILE           *f = fopen("/proc/net/ip_acct", "rt");
  62.     if (!f)
  63.         return 0;
  64.     /*
  65.      * get rid of "IP accounting rules" line
  66.      */
  67.     if (!fgets(rule, sizeof(rule), f)) {
  68.         fclose(f);
  69.         return 0;
  70.     }
  71.     for (i = 1; i != number; i++)
  72.         if (!fgets(rule, sizeof(rule), f)) {
  73.             fclose(f);
  74.             return (number ? 0 : (i - 1));
  75.         }
  76.     if (!fgets(rule, sizeof(rule), f)) {
  77.         fclose(f);
  78.         return 0;
  79.     }
  80.     fclose(f);
  81.     return i;
  82. }
  83. static unsigned long ret_val;   /* Used by var_ipfwacc to return ulongs */
  84. /*
  85.  * This function converts the hexadecimal representation of an IP address from
  86.  * * the rule buffer to an unsigned long. The result is stored in the ret_val
  87.  * * variable. The parameter indicates the position where the address starts. It
  88.  * * only works with uppercase letters and assumes input is correct. Had to use
  89.  * * this because stol returns a signed long. 
  90.  */
  91. static inline void
  92. atoip(int pos)
  93. {
  94.     int             i;
  95.     ret_val = 0;
  96.     for (i = 0; i < 32; i += 8) {
  97.         unsigned long   value = (((rule[pos]) >= '0' && rule[pos] <= '9') ?
  98.                                  rule[pos] - '0' : rule[pos] - 'A' + 10);
  99.         pos++;
  100.         value = (value << 4) + (((rule[pos]) >= '0' && rule[pos] <= '9') ?
  101.                                 rule[pos] - '0' : rule[pos] - 'A' + 10);
  102.         pos++;
  103.         ret_val |= (value << i);
  104.     }
  105. }
  106. /*
  107.  * This function parses the flags field from the line in the buffer 
  108.  */
  109. static unsigned long int
  110. getflags(void)
  111. {
  112.     unsigned long int flags;
  113.     int             i = 37;     /* position in the rule */
  114.     /*
  115.      * skipping via name 
  116.      */
  117.     while (rule[i] != ' ' && i < IPFWRULELEN - 12)
  118.         i++;
  119.     /*
  120.      * skipping via address 
  121.      */
  122.     i += 10;
  123.     for (flags = 0; rule[i] != ' ' && i < IPFWRULELEN - 1; i++) {
  124.         int             value = (((rule[i]) >= '0' && rule[i] <= '9') ?
  125.                                  rule[i] - '0' : rule[i] - 'A' + 10);
  126.         flags = (flags << 4) + value;
  127.     }
  128.     return flags;
  129. }
  130. /*
  131.  * This function reads into ret_val a field from the rule buffer. The field
  132.  * * is a base 10 long integer and the parameter skip tells us how many fields
  133.  * * to skip after the "via addrress" field (including the flag field)
  134.  */
  135. static void
  136. getnumeric(int skip)
  137. {
  138.     int             i = 37;     /* position in the rule */
  139.     /*
  140.      * skipping via name 
  141.      */
  142.     while (rule[i] != ' ' && i < IPFWRULELEN - 12)
  143.         i++;
  144.     /*
  145.      * skipping via address 
  146.      */
  147.     i += 10;
  148.     while (skip > 0) {
  149.         skip--;
  150.         /*
  151.          * skipping field, than subsequent spaces 
  152.          */
  153.         while (rule[i] != ' ' && i < IPFWRULELEN - 2)
  154.             i++;
  155.         while (rule[i] == ' ' && i < IPFWRULELEN - 1)
  156.             i++;
  157.     }
  158.     for (ret_val = 0; rule[i] != ' ' && i < IPFWRULELEN - 1; i++)
  159.         ret_val = ret_val * 10 + rule[i] - '0';
  160. }
  161. /*
  162.  * this variable defines function callbacks and type return information 
  163.  * for the ipfwaccounting mib 
  164.  */
  165. struct variable2 ipfwacc_variables[] = {
  166.     {IPFWACCINDEX, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCINDEX}},
  167.     {IPFWACCSRCADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
  168.      {IPFWACCSRCADDR}},
  169.     {IPFWACCSRCNM, ASN_IPADDRESS, RONLY, var_ipfwacc, 1, {IPFWACCSRCNM}},
  170.     {IPFWACCDSTADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
  171.      {IPFWACCDSTADDR}},
  172.     {IPFWACCDSTNM, ASN_IPADDRESS, RONLY, var_ipfwacc, 1, {IPFWACCDSTNM}},
  173.     {IPFWACCVIANAME, ASN_OCTET_STR, RONLY, var_ipfwacc, 1,
  174.      {IPFWACCVIANAME}},
  175.     {IPFWACCVIAADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
  176.      {IPFWACCVIAADDR}},
  177.     {IPFWACCPROTO, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPROTO}},
  178.     {IPFWACCBIDIR, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCBIDIR}},
  179.     {IPFWACCDIR, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCDIR}},
  180.     {IPFWACCBYTES, ASN_COUNTER, RONLY, var_ipfwacc, 1, {IPFWACCBYTES}},
  181.     {IPFWACCPACKETS, ASN_COUNTER, RONLY, var_ipfwacc, 1, {IPFWACCPACKETS}},
  182.     {IPFWACCNSRCPRTS, ASN_INTEGER, RONLY, var_ipfwacc, 1,
  183.      {IPFWACCNSRCPRTS}},
  184.     {IPFWACCNDSTPRTS, ASN_INTEGER, RONLY, var_ipfwacc, 1,
  185.      {IPFWACCNDSTPRTS}},
  186.     {IPFWACCSRCISRNG, ASN_INTEGER, RONLY, var_ipfwacc, 1,
  187.      {IPFWACCSRCISRNG}},
  188.     {IPFWACCDSTISRNG, ASN_INTEGER, RONLY, var_ipfwacc, 1,
  189.      {IPFWACCDSTISRNG}},
  190.     {IPFWACCPORT1, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT1}},
  191.     {IPFWACCPORT2, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT2}},
  192.     {IPFWACCPORT3, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT3}},
  193.     {IPFWACCPORT4, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT4}},
  194.     {IPFWACCPORT5, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT5}},
  195.     {IPFWACCPORT6, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT6}},
  196.     {IPFWACCPORT7, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT7}},
  197.     {IPFWACCPORT8, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT8}},
  198.     {IPFWACCPORT9, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT9}},
  199.     {IPFWACCPORT10, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT10}}
  200. };
  201. oid             ipfwacc_variables_oid[] =
  202.     { 1, 3, 6, 1, 4, 1, 2021, 13, 1, 1, 1 };
  203. void
  204. init_ipfwacc(void)
  205. {
  206.     REGISTER_MIB("misc/ipfwacc", ipfwacc_variables, variable2,
  207.                  ipfwacc_variables_oid);
  208. }
  209. u_char         *
  210. var_ipfwacc(struct variable *vp,
  211.             oid * name,
  212.             size_t * length,
  213.             int exact, size_t * var_len, WriteMethod ** write_method)
  214. {
  215.     *write_method = 0;          /* assume it isnt writable for the time being */
  216.     *var_len = sizeof(ret_val); /* assume an integer and change later if not */
  217.     if (header_simple_table
  218.         (vp, name, length, exact, var_len, write_method, readrule(0)))
  219.         return (NULL);
  220.     if (readrule(name[*length - 1])) {
  221.         /*
  222.          * this is where we do the value assignments for the mib results. 
  223.          */
  224.         switch (vp->magic) {
  225.         case IPFWACCINDEX:
  226.             ret_val = name[*length - 1];
  227.             return ((u_char *) (&ret_val));
  228.         case IPFWACCSRCADDR:
  229.             atoip(0);
  230.             return ((u_char *) (&ret_val));
  231.         case IPFWACCSRCNM:
  232.             atoip(9);
  233.             return ((u_char *) (&ret_val));
  234.         case IPFWACCDSTADDR:
  235.             atoip(19);
  236.             return ((u_char *) (&ret_val));
  237.         case IPFWACCDSTNM:
  238.             atoip(28);
  239.             return ((u_char *) (&ret_val));
  240.         case IPFWACCVIANAME:
  241.             {
  242.                 int             i = 37; /* position in the rule */
  243.                 while (rule[i] != ' ' && i < IPFWRULELEN - 1)
  244.                     i++;
  245.                 rule[i] = 0;
  246.                 return (rule + 37);
  247.             }
  248.         case IPFWACCVIAADDR:
  249.             {
  250.                 int             i = 37; /* position in the rule */
  251.                 while (rule[i] != ' ' && i < IPFWRULELEN - 9)
  252.                     i++;
  253.                 atoip(i + 1);
  254.                 return ((u_char *) (&ret_val));
  255.             }
  256.         case IPFWACCPROTO:
  257.             switch (getflags() & IP_FW_F_KIND) {
  258.             case IP_FW_F_ALL:
  259.                 ret_val = 2;
  260.                 return ((u_char *) (&ret_val));
  261.             case IP_FW_F_TCP:
  262.                 ret_val = 3;
  263.                 return ((u_char *) (&ret_val));
  264.             case IP_FW_F_UDP:
  265.                 ret_val = 4;
  266.                 return ((u_char *) (&ret_val));
  267.             case IP_FW_F_ICMP:
  268.                 ret_val = 5;
  269.                 return ((u_char *) (&ret_val));
  270.             default:
  271.                 ret_val = 1;
  272.                 return ((u_char *) (&ret_val));
  273.             }
  274.         case IPFWACCBIDIR:
  275.             ret_val = ((getflags() & IP_FW_F_BIDIR) ? 2 : 1);
  276.             return ((u_char *) (&ret_val));
  277.         case IPFWACCDIR:
  278.             ret_val = (getflags() & (IP_FW_F_ACCTIN | IP_FW_F_ACCTOUT));
  279.             if (ret_val == IP_FW_F_ACCTIN)
  280.                 ret_val = 2;
  281.             else if (ret_val == IP_FW_F_ACCTOUT)
  282.                 ret_val = 3;
  283.             else
  284.                 ret_val = 1;
  285.             return ((u_char *) (&ret_val));
  286.         case IPFWACCBYTES:
  287.             getnumeric(4);
  288.             return ((u_char *) (&ret_val));
  289.         case IPFWACCPACKETS:
  290.             getnumeric(3);
  291.             return ((u_char *) (&ret_val));
  292.         case IPFWACCNSRCPRTS:
  293.             getnumeric(1);
  294.             return ((u_char *) (&ret_val));
  295.         case IPFWACCNDSTPRTS:
  296.             getnumeric(2);
  297.             return ((u_char *) (&ret_val));
  298.         case IPFWACCSRCISRNG:
  299.             ret_val = ((getflags() & IP_FW_F_SRNG) ? 1 : 2);
  300.             return ((u_char *) (&ret_val));
  301.         case IPFWACCDSTISRNG:
  302.             ret_val = ((getflags() & IP_FW_F_DRNG) ? 1 : 2);
  303.             return ((u_char *) (&ret_val));
  304.         case IPFWACCPORT1:
  305.         case IPFWACCPORT2:
  306.         case IPFWACCPORT3:
  307.         case IPFWACCPORT4:
  308.         case IPFWACCPORT5:
  309.         case IPFWACCPORT6:
  310.         case IPFWACCPORT7:
  311.         case IPFWACCPORT8:
  312.         case IPFWACCPORT9:
  313.         case IPFWACCPORT10:
  314.             getnumeric(5 + (vp->magic) - IPFWACCPORT1);
  315.             return ((u_char *) (&ret_val));
  316.         }
  317.     }
  318.     return NULL;
  319. }