1658 lines
29 KiB
HTML
1658 lines
29 KiB
HTML
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Functions to query libiptc</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
|
|
"><LINK
|
|
REL="HOME"
|
|
TITLE="Querying libiptc HOWTO"
|
|
HREF="index.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="How to create your program(s)"
|
|
HREF="howtoprg.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Functions to modify firewalling rules and statistics"
|
|
HREF="mfunction.html"></HEAD
|
|
><BODY
|
|
CLASS="SECT1"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Querying libiptc HOWTO</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="howtoprg.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="mfunction.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="QFUNCTION">11. Functions to query libiptc</H1
|
|
><P
|
|
>This section explains which functions allow you to query libiptc. We will use
|
|
the header file of <EM
|
|
>libiptc</EM
|
|
>,
|
|
file <TT
|
|
CLASS="FILENAME"
|
|
>usr/local/include/libiptc/libiptc.h</TT
|
|
>,
|
|
containing prototypes of each function as a reference to develop our explanation. </P
|
|
><P
|
|
>I have also included a brief description (when available) taken from
|
|
<A
|
|
HREF="http://netfilter.samba.org/documentation/HOWTO/"
|
|
TARGET="_top"
|
|
>Linux netfilter Hacking HOWTO</A
|
|
> within each function explanation.</P
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN233">11.1. iptc_init</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_init</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Takes a snapshot of the rules.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>iptc_handle_t iptc_init(const char *tablename)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function must be called as initiator before any other function can be
|
|
called.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>tablename</EM
|
|
> is the name of the table we need to query
|
|
and/or modify; this could be <EM
|
|
>filter</EM
|
|
>,
|
|
<EM
|
|
>mangle</EM
|
|
>, <EM
|
|
>nat</EM
|
|
>, etc.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Pointer to a structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that must
|
|
be used as main parameter for the rest of functions we will call
|
|
from <EM
|
|
>libiptc</EM
|
|
>. <EM
|
|
>iptc_init</EM
|
|
> returns the
|
|
pointer to the structure or NULL if it fails. If this happens you can invoke
|
|
<EM
|
|
>iptc_strerror</EM
|
|
> to get information about the error.
|
|
See below.</P
|
|
><P
|
|
>Have a look at this section of code in file <TT
|
|
CLASS="FILENAME"
|
|
>iptables-save.c</TT
|
|
>
|
|
for how to invoke this function:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> h = iptc_init(tablename);
|
|
if (!h)
|
|
exit_error(OTHER_PROBLEM, "Can't initialize: %s\n",iptc_strerror(errno));</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN260">11.2. iptc_strerror</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_strerror</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Translates error numbers into more human-readable form.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>const char *iptc_strerror(int err)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function returns a more meaningful explanation of a failure code in
|
|
the iptc library. If a function fails, it will always set
|
|
<EM
|
|
>errno</EM
|
|
>. This value can be passed to
|
|
<EM
|
|
>iptc_strerror()</EM
|
|
> to yield an error message.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>err</EM
|
|
> is an integer indicating the error number.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Char pointer containing the error description.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN279">11.3. iptc_first_chain</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_first_chain</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Iterator functions to run through the chains.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>const char *iptc_first_chain(iptc_handle_t *handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function returns the first chain name in the table.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
>Pointer to a structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that was
|
|
obtained by a previous call to <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Char pointer to the name of the chain.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN297">11.4. iptc_next_chain</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_next_chain</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Iterator functions to run through the chains.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>const char *iptc_next_chain(iptc_handle_t *handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function returns the next chain name in the table; NULL means
|
|
no more chains.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
>Pointer to a structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that was
|
|
obtained by a previous call to <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Char pointer to the name of the chain.</P
|
|
><P
|
|
>These two previous functions allow to us to iterate through the chains of the table
|
|
getting the name of each of the chains; <EM
|
|
>iptc_first_chain</EM
|
|
>
|
|
returns the name of the first chain of the table; <EM
|
|
>iptc_next_chain</EM
|
|
>
|
|
returns the name of next chains and NULL when the function reaches the end.</P
|
|
><P
|
|
>We can create <EM
|
|
>Program #1</EM
|
|
> to exercise our understanding of
|
|
these previous four functions:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>/*
|
|
* How to use libiptc- program #1
|
|
* /usr/local/src/p1.c
|
|
*/
|
|
|
|
#include <getopt.h>
|
|
#include <sys/errno.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include <time.h>
|
|
#include "libiptc/libiptc.h"
|
|
#include "iptables.h"
|
|
|
|
int main(void)
|
|
{
|
|
iptc_handle_t h;
|
|
const char *chain = NULL;
|
|
const char *tablename = "filter";
|
|
|
|
program_name = "p1";
|
|
program_version = NETFILTER_VERSION;
|
|
|
|
h = iptc_init(tablename);
|
|
if ( !h ) {
|
|
printf("Error initializing: %s\n", iptc_strerror(errno));
|
|
exit(errno);
|
|
}
|
|
|
|
for (chain = iptc_first_chain(&h); chain; chain = iptc_next_chain(&h)) {
|
|
printf("%s\n", chain);
|
|
}
|
|
|
|
exit(0);
|
|
|
|
} /* main */</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Write this program and save it as <TT
|
|
CLASS="FILENAME"
|
|
>p1.c</TT
|
|
>
|
|
in <TT
|
|
CLASS="FILENAME"
|
|
>/usr/local/src</TT
|
|
>.</P
|
|
><P
|
|
>Now write this <SPAN
|
|
CLASS="QUOTE"
|
|
>"bash"</SPAN
|
|
> script to simplify the compiling process:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>#!/bin/bash
|
|
|
|
gcc -Wall -Wunused -DNETFILTER_VERSION=\"1.2.6\" -rdynamic -o $1 $1.c \
|
|
/usr/local/lib/iptables.o /usr/local/lib/libiptc.a -ldl</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Save it as <TT
|
|
CLASS="FILENAME"
|
|
>ipt-cc</TT
|
|
> and do not forget to
|
|
<EM
|
|
>chmod 0700 ipt-cc</EM
|
|
>.</P
|
|
><P
|
|
>Now compile your <EM
|
|
>p1</EM
|
|
> program:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>bash# <B
|
|
CLASS="COMMAND"
|
|
>./ipt-cc p1</B
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>And run it:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>bash# <B
|
|
CLASS="COMMAND"
|
|
>./p1</B
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>You will get:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>INPUT
|
|
FORWARD
|
|
OUTPUT</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>These are the three built-in iptables chains.</P
|
|
><P
|
|
>Now create some new chains using iptables and run your program again:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>bash# <B
|
|
CLASS="COMMAND"
|
|
>iptables -N chain_1</B
|
|
>
|
|
bash# <B
|
|
CLASS="COMMAND"
|
|
>iptables -N chain_2</B
|
|
>
|
|
bash# <B
|
|
CLASS="COMMAND"
|
|
>./p1</B
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>You will get:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>INPUT
|
|
FORWARD
|
|
OUTPUT
|
|
chain_1
|
|
chain_2</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Try to generate an error initializing tablename to <EM
|
|
>myfilter</EM
|
|
>
|
|
instead of <EM
|
|
>filter</EM
|
|
>. When you compile and execute your program
|
|
again, you will get:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
><EM
|
|
>Error initializing: Table does not exist (do you need to insmod?)</EM
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
><EM
|
|
>iptables</EM
|
|
> informs you that <EM
|
|
>myfilter</EM
|
|
> does
|
|
not exist as a table.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN355">11.5. iptc_is_chain</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_is_chain</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Check if a chain exists.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>int iptc_is_chain(const char *chain, const iptc_handle_t handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function checks to see if the chain described in the parameter
|
|
<EM
|
|
>chain</EM
|
|
> exists in the table.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>chain</EM
|
|
> is a char pointer containing the name of
|
|
the chain we want to check to. <EM
|
|
>handle</EM
|
|
> is a pointer to a
|
|
structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that was
|
|
obtained by a previous call to <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>integer value 1 (true) if the chain exists; integer value 0 (false)
|
|
if the chain does not exist.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN376">11.6. iptc_builtin</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_builtin</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Is this a built-in chain?</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>int iptc_builtin(const char *chain, const iptc_handle_t handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function is used to check if a given chain name is a built-in
|
|
chain or not.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>chain</EM
|
|
> is a char pointer containing the name of
|
|
the chain we want to check to. <EM
|
|
>handle</EM
|
|
> is a pointer to a
|
|
structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that was
|
|
obtained by a previous call to <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Returns integer value 1 (true) if the given chain name is the name
|
|
of a builtin chain; returns integer value 0 (false) is not.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN396">11.7. iptc_first_rule</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_first_rule</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Get first rule in the given chain.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>const struct ipt_entry *iptc_first_rule(const char *chain, iptc_handle_t *handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function returns a pointer to the first rule in the given chain
|
|
name; NULL for an empty chain.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>chain</EM
|
|
> is a char pointer containing the name of
|
|
the chain we want to get the rules to. <EM
|
|
>handle</EM
|
|
> is a
|
|
pointer to a structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that was
|
|
obtained by a previous call to <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Returns a pointer to an <EM
|
|
>ipt_entry</EM
|
|
> structure
|
|
containing information about the first rule of the chain. See below
|
|
for an explanation of this structure.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN417">11.8. iptc_next_rule</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_next_rule</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Get the next rule in the given chain.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>const struct ipt_entry *iptc_next_rule(const struct ipt_entry *prev, iptc_handle_t *handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function returns a pointer to the next rule in the given chain
|
|
name; NULL means the end of the chain.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>prev</EM
|
|
> is a pointer to a structure of type
|
|
<EM
|
|
>ipt_entry</EM
|
|
> that must be obtained first by a previous call to
|
|
the function <EM
|
|
>iptc_first_rule</EM
|
|
>. In order to get the second
|
|
and subsequent rules you have to pass a pointer to the structure containing the
|
|
information about the previous rule of the chain. <EM
|
|
>handle</EM
|
|
> is
|
|
a pointer to a structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that was
|
|
obtained by a previous call to <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Returns a pointer to an <EM
|
|
>ipt_entry</EM
|
|
> structure
|
|
containing information about the next rule of the chain. See below
|
|
for an explanation of this structure.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN440">11.9. iptc_get_target</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_get_target</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Get a pointer to the target name of this entry.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>const char *iptc_get_target(const struct ipt_entry *e, iptc_handle_t *handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function gets the target of the given rule. If it is an extended
|
|
target, the name of that target is returned. If it is a jump to another chain,
|
|
the name of that chain is returned. If it is a verdict (eg. DROP), that name
|
|
is returned. If it has no target (an accounting-style rule), then the empty
|
|
string is returned. Note that this function should be used instead of using
|
|
the value of the <EM
|
|
>verdict</EM
|
|
> field of the
|
|
<EM
|
|
>ipt_entry</EM
|
|
> structure directly, as it offers the above further
|
|
interpretations of the standard verdict.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>e</EM
|
|
> is a pointer to a structure of type
|
|
<EM
|
|
>ipt_entry</EM
|
|
> that must be obtained first by a previous call to
|
|
the function <EM
|
|
>iptc_first_rule</EM
|
|
> or the function
|
|
<EM
|
|
>iptc_next_rule</EM
|
|
>. <EM
|
|
>handle</EM
|
|
> is
|
|
a pointer to a structure of type <EM
|
|
>iptc_handle_t</EM
|
|
> that was
|
|
obtained by a previous call to <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Returns a char pointer to the target name. See <EM
|
|
>Description</EM
|
|
>
|
|
above for more information.</P
|
|
><P
|
|
>Now it is time to explain the <EM
|
|
>ipt_entry</EM
|
|
> structure; these pieces
|
|
of code are taken from <EM
|
|
>iptables</EM
|
|
> package sources:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>/* Internet address. */
|
|
struct in_addr {
|
|
__u32 s_addr;
|
|
};
|
|
|
|
/* Yes, Virginia, you have to zero the padding. */
|
|
struct ipt_ip {
|
|
/* Source and destination IP addr */
|
|
struct in_addr src, dst;
|
|
/* Mask for src and dest IP addr */
|
|
struct in_addr smsk, dmsk;
|
|
char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
|
|
unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
|
|
|
|
/* Protocol, 0 = ANY */
|
|
u_int16_t proto;
|
|
|
|
/* Flags word */
|
|
u_int8_t flags;
|
|
/* Inverse flags */
|
|
u_int8_t invflags;
|
|
};
|
|
|
|
struct ipt_counters
|
|
{
|
|
u_int64_t pcnt, bcnt; /* Packet and byte counters */
|
|
};
|
|
|
|
/* This structure defines each of the firewall rules. Consists of 3
|
|
parts which are 1) general IP header stuff 2) match specific
|
|
stuff 3) the target to perform if the rule matches */
|
|
struct ipt_entry
|
|
{
|
|
struct ipt_ip ip;
|
|
|
|
/* Mark with fields that we care about. */
|
|
unsigned int nfcache;
|
|
|
|
/* Size of ipt_entry + matches */
|
|
u_int16_t target_offset;
|
|
/* Size of ipt_entry + matches + target */
|
|
u_int16_t next_offset;
|
|
|
|
/* Back pointer */
|
|
unsigned int comefrom;
|
|
|
|
/* Packet and byte counters. */
|
|
struct ipt_counters counters;
|
|
|
|
/* The matches (if any), then the target. */
|
|
unsigned char elems[0];
|
|
};</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>An <EM
|
|
>ipt_entry</EM
|
|
> structure contains:</P
|
|
><P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>An <EM
|
|
>ipt_ip</EM
|
|
> structure containing (for the rule) the
|
|
source address and netmask <EM
|
|
>(ip.src.s_addr, ip.smsk.s_addr)</EM
|
|
>,
|
|
the destination address and netmask <EM
|
|
>(ip.dst.s_addr, ip.dmsk.s_addr)</EM
|
|
>,
|
|
the protocol <EM
|
|
>(ip.proto)</EM
|
|
>, a flags field <EM
|
|
>(invflags)</EM
|
|
>
|
|
to check for inverse <EM
|
|
>(!)</EM
|
|
> selections
|
|
<EM
|
|
>(eg. ! 192.168.2.0/24, ! eth0, ! tcp, etc)</EM
|
|
>, the input
|
|
interface <EM
|
|
>(iniface)</EM
|
|
>, the output interface
|
|
<EM
|
|
>(outiface)</EM
|
|
>, the input <EM
|
|
>(iniface_mask)</EM
|
|
>
|
|
and output <EM
|
|
>(outiface_mask)</EM
|
|
> interface masks and the
|
|
<EM
|
|
>flags</EM
|
|
> field to check for fragmented packets.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>An <EM
|
|
>ipt_counters</EM
|
|
> structure containing the packet
|
|
<EM
|
|
>(pcnt)</EM
|
|
> and byte <EM
|
|
>(bcnt)</EM
|
|
> counter
|
|
of the rule. This information is important for bandwidth measurement.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><EM
|
|
>target_offset</EM
|
|
> that is used to get the target information
|
|
of the rule.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>Unknown fields: <EM
|
|
>nfcache, comefrom, elems, next_offset</EM
|
|
>.
|
|
If someone can give me a feedback about these fields I would be grateful.</P
|
|
></LI
|
|
></UL
|
|
><P
|
|
>A simple way to work with all this information is to borrow
|
|
some functions from <TT
|
|
CLASS="FILENAME"
|
|
>iptables-save.c</TT
|
|
> by Paul
|
|
Russell and Harald Welte.</P
|
|
><P
|
|
>Here is another sample program <EM
|
|
>Program #2</EM
|
|
> written with
|
|
a lot of help from Russell-Welte:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>/*
|
|
* How to use libiptc- program #2
|
|
* /usr/local/src/p1.c
|
|
*/
|
|
|
|
#include <getopt.h>
|
|
#include <sys/errno.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include <time.h>
|
|
#include "libiptc/libiptc.h"
|
|
#include "iptables.h"
|
|
|
|
<EM
|
|
>/* Here begins some of the code taken from iptables-save.c **************** */</EM
|
|
>
|
|
#define IP_PARTS_NATIVE(n) \
|
|
(unsigned int)((n)>>24)&0xFF, \
|
|
(unsigned int)((n)>>16)&0xFF, \
|
|
(unsigned int)((n)>>8)&0xFF, \
|
|
(unsigned int)((n)&0xFF)
|
|
|
|
#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
|
|
|
|
/* This assumes that mask is contiguous, and byte-bounded. */
|
|
static void
|
|
print_iface(char letter, const char *iface, const unsigned char *mask,
|
|
int invert)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (mask[0] == 0)
|
|
return;
|
|
|
|
printf("-%c %s", letter, invert ? "! " : "");
|
|
|
|
for (i = 0; i < IFNAMSIZ; i++) {
|
|
if (mask[i] != 0) {
|
|
if (iface[i] != '\0')
|
|
printf("%c", iface[i]);
|
|
} else {
|
|
/* we can access iface[i-1] here, because
|
|
* a few lines above we make sure that mask[0] != 0 */
|
|
if (iface[i-1] != '\0')
|
|
printf("+");
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf(" ");
|
|
}
|
|
|
|
/* These are hardcoded backups in iptables.c, so they are safe */
|
|
struct pprot {
|
|
char *name;
|
|
u_int8_t num;
|
|
};
|
|
|
|
/* FIXME: why don't we use /etc/protocols ? */
|
|
static const struct pprot chain_protos[] = {
|
|
{ "tcp", IPPROTO_TCP },
|
|
{ "udp", IPPROTO_UDP },
|
|
{ "icmp", IPPROTO_ICMP },
|
|
{ "esp", IPPROTO_ESP },
|
|
{ "ah", IPPROTO_AH },
|
|
};
|
|
|
|
static void print_proto(u_int16_t proto, int invert)
|
|
{
|
|
if (proto) {
|
|
unsigned int i;
|
|
const char *invertstr = invert ? "! " : "";
|
|
|
|
for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
|
|
if (chain_protos[i].num == proto) {
|
|
printf("-p %s%s ",
|
|
invertstr, chain_protos[i].name);
|
|
return;
|
|
}
|
|
|
|
printf("-p %s%u ", invertstr, proto);
|
|
}
|
|
}
|
|
|
|
static int print_match(const struct ipt_entry_match *e,
|
|
const struct ipt_ip *ip)
|
|
{
|
|
struct iptables_match *match
|
|
= find_match(e->u.user.name, TRY_LOAD);
|
|
|
|
if (match) {
|
|
printf("-m %s ", e->u.user.name);
|
|
|
|
/* some matches don't provide a save function */
|
|
if (match->save)
|
|
match->save(ip, e);
|
|
} else {
|
|
if (e->u.match_size) {
|
|
fprintf(stderr,
|
|
"Can't find library for match `%s'\n",
|
|
e->u.user.name);
|
|
exit(1);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* print a given ip including mask if neccessary */
|
|
static void print_ip(char *prefix, u_int32_t ip, u_int32_t mask, int invert)
|
|
{
|
|
if (!mask && !ip)
|
|
return;
|
|
|
|
printf("%s %s%u.%u.%u.%u",
|
|
prefix,
|
|
invert ? "! " : "",
|
|
IP_PARTS(ip));
|
|
|
|
if (mask != 0xffffffff)
|
|
printf("/%u.%u.%u.%u ", IP_PARTS(mask));
|
|
else
|
|
printf(" ");
|
|
}
|
|
|
|
/* We want this to be readable, so only print out neccessary fields.
|
|
* Because that's the kind of world I want to live in. */
|
|
static void print_rule(const struct ipt_entry *e,
|
|
iptc_handle_t *h, const char *chain, int counters)
|
|
{
|
|
struct ipt_entry_target *t;
|
|
const char *target_name;
|
|
|
|
/* print counters */
|
|
if (counters)
|
|
printf("[%llu:%llu] ", e->counters.pcnt, e->counters.bcnt);
|
|
|
|
/* print chain name */
|
|
printf("-A %s ", chain);
|
|
|
|
/* Print IP part. */
|
|
print_ip("-s", e->ip.src.s_addr,e->ip.smsk.s_addr,
|
|
e->ip.invflags & IPT_INV_SRCIP);
|
|
|
|
print_ip("-d", e->ip.dst.s_addr, e->ip.dmsk.s_addr,
|
|
e->ip.invflags & IPT_INV_DSTIP);
|
|
|
|
print_iface('i', e->ip.iniface, e->ip.iniface_mask,
|
|
e->ip.invflags & IPT_INV_VIA_IN);
|
|
|
|
print_iface('o', e->ip.outiface, e->ip.outiface_mask,
|
|
e->ip.invflags & IPT_INV_VIA_OUT);
|
|
|
|
print_proto(e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
|
|
|
|
if (e->ip.flags & IPT_F_FRAG)
|
|
printf("%s-f ",
|
|
e->ip.invflags & IPT_INV_FRAG ? "! " : "");
|
|
|
|
/* Print matchinfo part */
|
|
if (e->target_offset) {
|
|
IPT_MATCH_ITERATE(e, print_match, &e->ip);
|
|
}
|
|
|
|
/* Print target name */
|
|
target_name = iptc_get_target(e, h);
|
|
if (target_name && (*target_name != '\0'))
|
|
printf("-j %s ", target_name);
|
|
|
|
/* Print targinfo part */
|
|
t = ipt_get_target((struct ipt_entry *)e);
|
|
if (t->u.user.name[0]) {
|
|
struct iptables_target *target
|
|
= find_target(t->u.user.name, TRY_LOAD);
|
|
|
|
if (!target) {
|
|
fprintf(stderr, "Can't find library for target `%s'\n",
|
|
t->u.user.name);
|
|
exit(1);
|
|
}
|
|
|
|
if (target->save)
|
|
target->save(&e->ip, t);
|
|
else {
|
|
/* If the target size is greater than ipt_entry_target
|
|
* there is something to be saved, we just don't know
|
|
* how to print it */
|
|
if (t->u.target_size !=
|
|
sizeof(struct ipt_entry_target)) {
|
|
fprintf(stderr, "Target `%s' is missing "
|
|
"save function\n",
|
|
t->u.user.name);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
<EM
|
|
>/* Here ends some of the code taken from iptables-save.c ****************** */</EM
|
|
>
|
|
|
|
int main(void)
|
|
{
|
|
iptc_handle_t h;
|
|
const struct ipt_entry *e;
|
|
const char *chain = NULL;
|
|
const char *tablename = "filter";
|
|
const int counters = 1;
|
|
|
|
program_name = "p2";
|
|
program_version = NETFILTER_VERSION;
|
|
|
|
/* initialize */
|
|
h = iptc_init(tablename);
|
|
if ( !h ) {
|
|
printf("Error initializing: %s\n", iptc_strerror(errno));
|
|
exit(errno);
|
|
}
|
|
|
|
/* print chains and their rules */
|
|
for (chain = iptc_first_chain(&h); chain; chain = iptc_next_chain(&h)) {
|
|
printf("%s\n", chain);
|
|
for (e = iptc_first_rule(chain, &h); e; e = iptc_next_rule(e, &h)) {
|
|
print_rule(e, &h, chain, counters);
|
|
}
|
|
}
|
|
|
|
exit(0);
|
|
|
|
} /* main */</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>The function <EM
|
|
>print_rule</EM
|
|
> borrowed from
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>iptables-save.c</TT
|
|
> prints the information
|
|
about a rule into a readable form using:</P
|
|
><P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
><EM
|
|
>print_ip</EM
|
|
> to print the addresses, </P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><EM
|
|
>print_iface</EM
|
|
> to print the interfaces, </P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><EM
|
|
>print_proto</EM
|
|
> to print the protocols, </P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><EM
|
|
>iptc_get_target</EM
|
|
> to get and print the targets
|
|
(using <EM
|
|
>save</EM
|
|
>).</P
|
|
></LI
|
|
></UL
|
|
><P
|
|
>In <EM
|
|
>main</EM
|
|
> we iterate through each chain and
|
|
for each one we iterate through each rule printing it.</P
|
|
><P
|
|
>The arguments of <EM
|
|
>print_rule</EM
|
|
> are:</P
|
|
><P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>e = pointer to an <EM
|
|
>ipt_entry</EM
|
|
> structure containing
|
|
information about the rule.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>h = pointer to an <EM
|
|
>iptc_handle_t</EM
|
|
> structure returned by
|
|
<EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>chain = name of the chain.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>counters = 0: do not print counters; 1: print them.</P
|
|
></LI
|
|
></UL
|
|
><P
|
|
>OK, compile and run program <EM
|
|
>p2</EM
|
|
>:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>bash# <B
|
|
CLASS="COMMAND"
|
|
>./ipt-cc p2</B
|
|
>
|
|
bash# <B
|
|
CLASS="COMMAND"
|
|
>./p2</B
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>You will get:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>INPUT
|
|
FORWARD
|
|
OUTPUT
|
|
chain_1
|
|
chain_2</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Now modify the environment using <EM
|
|
>iptables</EM
|
|
> to add some rules:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>bash# <B
|
|
CLASS="COMMAND"
|
|
>iptables -A INPUT -p tcp -i eth0 -s ! 192.168.1.1 --dport 20 -j ACCEPT</B
|
|
>
|
|
bash# <B
|
|
CLASS="COMMAND"
|
|
>iptables -A chain_1 -p udp -o eth1 -s 192.168.2.0/24 --sport 33 -j DROP</B
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Now if you run again <EM
|
|
>p2</EM
|
|
> you will get:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>INPUT
|
|
[0:0] -A INPUT -s ! 192.168.1.1 -i eth0 -p tcp -m tcp --dport 20 -j ACCEPT
|
|
FORWARD
|
|
OUTPUT
|
|
chain_1
|
|
[0:0] -A chain_1 -s 192.168.2.0/255.255.255.0 -o eth1 -p udp -m udp --sport 33 -j DROP
|
|
chain_2</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>We have now rules printed for <EM
|
|
>INPUT</EM
|
|
> and
|
|
<EM
|
|
>chain_1</EM
|
|
> chains. The numbers in the
|
|
brackets at left are packet and byte counters respectively.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN556">11.10. iptc_get_policy</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_get_policy</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Get the policy of a given built-in chain.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>const char *iptc_get_policy(const char *chain, struct ipt_counters *counter, iptc_handle_t *handle)</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function gets the policy of a built-in chain, and fills in the
|
|
<EM
|
|
>counters</EM
|
|
> argument with the hit statistics on
|
|
that policy.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
>You have to pass as arguments the name of the built-in chain you want
|
|
to get the policy to, a pointer to an <EM
|
|
>ipt_counters</EM
|
|
>
|
|
structure to be filled by the function and the
|
|
<EM
|
|
>iptc_handle_t</EM
|
|
> structure identifying the table we are
|
|
working to. The <EM
|
|
>ipt_counters</EM
|
|
> structure was explained
|
|
in previous section; do not forget that <EM
|
|
>iptc_handle_t</EM
|
|
>
|
|
must be obtained by a previous call to the function <EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Returns a char pointer to the policy name.</P
|
|
><P
|
|
>Using pieces of programs 1 and 2 we can write <EM
|
|
>program #3</EM
|
|
>:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>/*
|
|
* How to use libiptc- program #3
|
|
* /usr/local/src/p3.c
|
|
*/
|
|
|
|
#include <getopt.h>
|
|
#include <sys/errno.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include <time.h>
|
|
#include "libiptc/libiptc.h"
|
|
#include "iptables.h"
|
|
|
|
int main(void)
|
|
{
|
|
iptc_handle_t h;
|
|
const char *chain = NULL;
|
|
const char *policy = NULL;
|
|
const char *tablename = "filter";
|
|
struct ipt_counters counters;
|
|
|
|
program_name = "p3";
|
|
program_version = NETFILTER_VERSION;
|
|
|
|
/* initialize */
|
|
h = iptc_init(tablename);
|
|
if ( !h ) {
|
|
printf("Error initializing: %s\n", iptc_strerror(errno));
|
|
exit(errno);
|
|
}
|
|
|
|
/* print built-in chains, their policies and counters */
|
|
printf("BUILT-IN POLICY PKTS-BYTES\n");
|
|
printf("-----------------------------\n");
|
|
for (chain = iptc_first_chain(&h); chain; chain = iptc_next_chain(&h)) {
|
|
if ( !iptc_builtin(chain, h) )
|
|
continue;
|
|
if ( (policy = iptc_get_policy(chain, &counters, &h)) )
|
|
printf("%-10s %-10s [%llu:%llu]\n",
|
|
chain, policy, counters.pcnt, counters.bcnt);
|
|
}
|
|
|
|
exit(0);
|
|
|
|
} /* main */</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>OK, compile and run program <EM
|
|
>p3</EM
|
|
>:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>bash# <B
|
|
CLASS="COMMAND"
|
|
>./ipt-cc p3</B
|
|
>
|
|
bash# <B
|
|
CLASS="COMMAND"
|
|
>./p3</B
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>You will get something like this:</P
|
|
><TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
>BUILT-IN POLICY PKTS-BYTES
|
|
----------------------------
|
|
INPUT ACCEPT [0:0]
|
|
FORWARD ACCEPT [0:0]
|
|
OUTPUT ACCEPT [0:0]</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN588">11.11. iptc_read_counter</H2
|
|
><P
|
|
><B
|
|
>Name: </B
|
|
>iptc_read_counter</P
|
|
><P
|
|
><B
|
|
>Usage: </B
|
|
>Read counters of a rule in a chain.</P
|
|
><P
|
|
><B
|
|
>Prototype: </B
|
|
>struct ipt_counters *iptc_read_counter(const ipt_chainlabel chain,
|
|
unsigned int rulenum, iptc_handle_t *handle);</P
|
|
><P
|
|
><B
|
|
>Description: </B
|
|
>This function read and returns packet and byte counters of the entry
|
|
rule in chain <EM
|
|
>chain</EM
|
|
> positioned at
|
|
<EM
|
|
>rulenum</EM
|
|
>. Counters are returned in a pointer to a
|
|
type structure <EM
|
|
>ipt_counters</EM
|
|
>. Rule numbers start at
|
|
1 for the first rule.</P
|
|
><P
|
|
><B
|
|
>Parameters: </B
|
|
><EM
|
|
>chain</EM
|
|
> is a char pointer to the name of the chain to
|
|
be readed; <EM
|
|
>rulenum</EM
|
|
> is an integer value defined the
|
|
position in the chain of rules of the rule which counters will be read.
|
|
<EM
|
|
>handle</EM
|
|
> is a pointer to a structure of type
|
|
<EM
|
|
>iptc_handle_t</EM
|
|
> that was obtained by a previous call to
|
|
<EM
|
|
>iptc_init</EM
|
|
>.</P
|
|
><P
|
|
><B
|
|
>Returns: </B
|
|
>Returns a pointer to an <EM
|
|
>ipt_counters</EM
|
|
> structure
|
|
containing the byte and packet counters readed. </P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="howtoprg.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="mfunction.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>How to create your program(s)</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
> </TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Functions to modify firewalling rules and statistics</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |