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 ***************************************************************************/
9 #include <net-snmp/net-snmp-config.h>
11 #if TIME_WITH_SYS_TIME
12 # include <sys/time.h>
16 # include <sys/time.h>
22 #include <net-snmp/net-snmp-includes.h>
23 #include <net-snmp/agent/net-snmp-agent-includes.h>
25 #include "util_funcs.h"
29 * According to the 2.0.33 Linux kernel, assuming we use ipv4 any line from
30 * * "/proc/net/ip_acct should fit into
31 * * 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
32 * * characters+ newline.
34 #define IPFWRULELEN 200
36 #define IP_FW_F_ALL 0x0000 /* This is a universal packet firewall */
37 #define IP_FW_F_TCP 0x0001 /* This is a TCP packet firewall */
38 #define IP_FW_F_UDP 0x0002 /* This is a UDP packet firewall */
39 #define IP_FW_F_ICMP 0x0003 /* This is a ICMP packet firewall */
40 #define IP_FW_F_KIND 0x0003 /* Mask to isolate firewall kind */
41 #define IP_FW_F_SRNG 0x0008 /* The first two src ports are a min *
42 * and max range (stored in host byte *
44 #define IP_FW_F_DRNG 0x0010 /* The first two dst ports are a min *
45 * and max range (stored in host byte *
47 * (ports[0] <= port <= ports[1]) */
48 #define IP_FW_F_BIDIR 0x0040 /* For bidirectional firewalls */
49 #define IP_FW_F_ACCTIN 0x1000 /* Account incoming packets only. */
50 #define IP_FW_F_ACCTOUT 0x2000 /* Account outgoing packets only. */
52 static unsigned char rule[IPFWRULELEN]; /*Buffer for reading a line from
53 * /proc/net/ip_acct. Care has been taken
54 * not to read beyond the end of this
55 * buffer, even if rules are in an
60 * This function reads the rule with the given number into the buffer. It
61 * * returns the number of rule read or 0 if the number is invalid or other
62 * * problems occur. If the argument is 0 it returns the number of accounting
63 * * rules. No caching of rules is done.
67 readrule(unsigned int number)
70 FILE *f = fopen("/proc/net/ip_acct", "rt");
75 * get rid of "IP accounting rules" line
77 if (!fgets(rule, sizeof(rule), f)) {
81 for (i = 1; i != number; i++)
82 if (!fgets(rule, sizeof(rule), f)) {
84 return (number ? 0 : (i - 1));
86 if (!fgets(rule, sizeof(rule), f)) {
94 static unsigned long ret_val; /* Used by var_ipfwacc to return ulongs */
97 * This function converts the hexadecimal representation of an IP address from
98 * * the rule buffer to an unsigned long. The result is stored in the ret_val
99 * * variable. The parameter indicates the position where the address starts. It
100 * * only works with uppercase letters and assumes input is correct. Had to use
101 * * this because stol returns a signed long.
110 for (i = 0; i < 32; i += 8) {
111 unsigned long value = (((rule[pos]) >= '0' && rule[pos] <= '9') ?
112 rule[pos] - '0' : rule[pos] - 'A' + 10);
114 value = (value << 4) + (((rule[pos]) >= '0' && rule[pos] <= '9') ?
115 rule[pos] - '0' : rule[pos] - 'A' + 10);
117 ret_val |= (value << i);
122 * This function parses the flags field from the line in the buffer
125 static unsigned long int
128 unsigned long int flags;
129 int i = 37; /* position in the rule */
134 while (rule[i] != ' ' && i < IPFWRULELEN - 12)
137 * skipping via address
140 for (flags = 0; rule[i] != ' ' && i < IPFWRULELEN - 1; i++) {
141 int value = (((rule[i]) >= '0' && rule[i] <= '9') ?
142 rule[i] - '0' : rule[i] - 'A' + 10);
143 flags = (flags << 4) + value;
149 * This function reads into ret_val a field from the rule buffer. The field
150 * * is a base 10 long integer and the parameter skip tells us how many fields
151 * * to skip after the "via addrress" field (including the flag field)
157 int i = 37; /* position in the rule */
162 while (rule[i] != ' ' && i < IPFWRULELEN - 12)
165 * skipping via address
171 * skipping field, than subsequent spaces
173 while (rule[i] != ' ' && i < IPFWRULELEN - 2)
175 while (rule[i] == ' ' && i < IPFWRULELEN - 1)
178 for (ret_val = 0; rule[i] != ' ' && i < IPFWRULELEN - 1; i++)
179 ret_val = ret_val * 10 + rule[i] - '0';
183 * this variable defines function callbacks and type return information
184 * for the ipfwaccounting mib
187 struct variable2 ipfwacc_variables[] = {
188 {IPFWACCINDEX, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCINDEX}},
189 {IPFWACCSRCADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
191 {IPFWACCSRCNM, ASN_IPADDRESS, RONLY, var_ipfwacc, 1, {IPFWACCSRCNM}},
192 {IPFWACCDSTADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
194 {IPFWACCDSTNM, ASN_IPADDRESS, RONLY, var_ipfwacc, 1, {IPFWACCDSTNM}},
195 {IPFWACCVIANAME, ASN_OCTET_STR, RONLY, var_ipfwacc, 1,
197 {IPFWACCVIAADDR, ASN_IPADDRESS, RONLY, var_ipfwacc, 1,
199 {IPFWACCPROTO, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPROTO}},
200 {IPFWACCBIDIR, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCBIDIR}},
201 {IPFWACCDIR, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCDIR}},
202 {IPFWACCBYTES, ASN_COUNTER, RONLY, var_ipfwacc, 1, {IPFWACCBYTES}},
203 {IPFWACCPACKETS, ASN_COUNTER, RONLY, var_ipfwacc, 1, {IPFWACCPACKETS}},
204 {IPFWACCNSRCPRTS, ASN_INTEGER, RONLY, var_ipfwacc, 1,
206 {IPFWACCNDSTPRTS, ASN_INTEGER, RONLY, var_ipfwacc, 1,
208 {IPFWACCSRCISRNG, ASN_INTEGER, RONLY, var_ipfwacc, 1,
210 {IPFWACCDSTISRNG, ASN_INTEGER, RONLY, var_ipfwacc, 1,
212 {IPFWACCPORT1, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT1}},
213 {IPFWACCPORT2, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT2}},
214 {IPFWACCPORT3, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT3}},
215 {IPFWACCPORT4, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT4}},
216 {IPFWACCPORT5, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT5}},
217 {IPFWACCPORT6, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT6}},
218 {IPFWACCPORT7, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT7}},
219 {IPFWACCPORT8, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT8}},
220 {IPFWACCPORT9, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT9}},
221 {IPFWACCPORT10, ASN_INTEGER, RONLY, var_ipfwacc, 1, {IPFWACCPORT10}}
224 oid ipfwacc_variables_oid[] =
225 { 1, 3, 6, 1, 4, 1, 2021, 13, 1, 1, 1 };
230 REGISTER_MIB("misc/ipfwacc", ipfwacc_variables, variable2,
231 ipfwacc_variables_oid);
236 var_ipfwacc(struct variable *vp,
239 int exact, size_t * var_len, WriteMethod ** write_method)
241 *write_method = 0; /* assume it isnt writable for the time being */
242 *var_len = sizeof(ret_val); /* assume an integer and change later if not */
244 if (header_simple_table
245 (vp, name, length, exact, var_len, write_method, readrule(0)))
248 if (readrule(name[*length - 1])) {
250 * this is where we do the value assignments for the mib results.
254 ret_val = name[*length - 1];
255 return ((u_char *) (&ret_val));
258 return ((u_char *) (&ret_val));
261 return ((u_char *) (&ret_val));
264 return ((u_char *) (&ret_val));
267 return ((u_char *) (&ret_val));
270 int i = 37; /* position in the rule */
271 while (rule[i] != ' ' && i < IPFWRULELEN - 1)
278 int i = 37; /* position in the rule */
279 while (rule[i] != ' ' && i < IPFWRULELEN - 9)
282 return ((u_char *) (&ret_val));
285 switch (getflags() & IP_FW_F_KIND) {
288 return ((u_char *) (&ret_val));
291 return ((u_char *) (&ret_val));
294 return ((u_char *) (&ret_val));
297 return ((u_char *) (&ret_val));
300 return ((u_char *) (&ret_val));
303 ret_val = ((getflags() & IP_FW_F_BIDIR) ? 2 : 1);
304 return ((u_char *) (&ret_val));
306 ret_val = (getflags() & (IP_FW_F_ACCTIN | IP_FW_F_ACCTOUT));
307 if (ret_val == IP_FW_F_ACCTIN)
309 else if (ret_val == IP_FW_F_ACCTOUT)
313 return ((u_char *) (&ret_val));
316 return ((u_char *) (&ret_val));
319 return ((u_char *) (&ret_val));
320 case IPFWACCNSRCPRTS:
322 return ((u_char *) (&ret_val));
323 case IPFWACCNDSTPRTS:
325 return ((u_char *) (&ret_val));
326 case IPFWACCSRCISRNG:
327 ret_val = ((getflags() & IP_FW_F_SRNG) ? 1 : 2);
328 return ((u_char *) (&ret_val));
329 case IPFWACCDSTISRNG:
330 ret_val = ((getflags() & IP_FW_F_DRNG) ? 1 : 2);
331 return ((u_char *) (&ret_val));
342 getnumeric(5 + (vp->magic) - IPFWACCPORT1);
343 return ((u_char *) (&ret_val));