Penguin
Diff: HowToQueryinglibiptcHOWTO
EditPageHistoryDiffInfoLikePages

Differences between current version and predecessor to the previous major change of HowToQueryinglibiptcHOWTO.

Other diffs: Previous Revision, Previous Author, or view the Annotated Edit History

Newer page: version 3 Last edited on Sunday, October 31, 2004 1:35:26 am by AristotlePagaltzis
Older page: version 2 Last edited on Friday, June 7, 2002 1:07:23 am by perry Revert
@@ -1,2796 +1 @@
-Querying libiptc HOWTO  
-!!!Querying libiptc HOWTO  
-!Leonardo Balliache  
-  
-leonardo@opalsoft.net  
-  
-  
-  
-Version .1 - April 30, 2002  
-  
-  
-__Revision History__Revision .12002-04-30Revised by: lbInitial release.----; __Table of Contents__; 1. Legal Notice; 2. Translations; 3. Disclaimer; 4. Credits; 5. Objectives; 6. What is libiptc?; 7. How did I obtain this knowledge?; 8. Previous knowledge and system requirements; 9. Installing iptables + libiptc; 10. How to create your program(s); 11. Functions to query libiptc: ; 11.1. iptc_init; 11.2. iptc_strerror; 11.3. iptc_first_chain; 11.4. iptc_next_chain; 11.5. iptc_is_chain; 11.6. iptc_builtin; 11.7. iptc_first_rule; 11.8. iptc_next_rule; 11.9. iptc_get_target; 11.10. iptc_get_policy; 11.11. iptc_read_counter; 12. Functions to modify firewalling rules and statistics: ; 12.1. iptc_commit; 12.2. iptc_insert_entry; 12.3. iptc_replace_entry; 12.4. iptc_append_entry; 12.5. iptc_delete_num_entry; 12.6. iptc_flush_entries; 12.7. iptc_zero_entries; 12.8. iptc_create_chain; 12.9. iptc_delete_chain; 12.10. iptc_rename_chain; 12.11. iptc_set_policy; 12.12. iptc_zero_counter; 12.13. iptc_set_counter; 13. Bandwidth meter; 14. Controlling flows; 15. Some interesting links; 16. About the author  
-!!!1. Legal Notice  
-  
-This document is free; you can redistribute it and/or modify it under the  
-terms of the GNU General Public License as published by the Free Software  
-Foundation; either version 2 of the License, or (at your option) any later  
-version. This document is distributed in the hope that it will be useful,  
-but WITHOUT ANY WARRANTY; without even the implied warranty of  
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General  
-Public License for more details. You can get a copy of the GNU GPL  
-here.  
-  
-----  
-!!!2. Translations  
-  
-If you want to translate this document you are free to do so. However,  
-you will need to do the following:  
-  
-  
-  
-  
-  
-  
-#  
-  
-  
-Check first that another version of the document doesn't already  
-exist at your local LDP.  
-  
-  
-#  
-#  
-  
-  
-Maintain all sections (including 'Legal Notice', 'Translation',  
-'Credits', etc., etc.) of the document.  
-  
-  
-#  
-#  
-  
-  
-No need to ask me to translate! You just have to let me know  
-(if you want) about your translation.  
-  
-  
-#  
-  
-  
-Thank for your translation.  
-  
-----  
-!!!3. Disclaimer  
-  
-I took this "disclaimer" from  
-Linux-Advance Networking Overview by  
-Saravanan Radhakrishnan (08-1999) because it applies in my own case:  
-  
-  
-  
-All the text in this document is completely based on my understanding  
-of implementations of various features. I have read some documents and  
-have seen the code myself, and I described them based on my understanding.  
-If the reader notices any concept description which appears to be contrary  
-to their understanding of the concept, the issue can be taken up for  
-discussion and corrections will be made to the document as necessary. I  
-would appreciate any suggestions and comments made in order to improve the  
-quality of this document.  
-  
-----  
-!!!4. Credits  
-  
-I want to thank the following people and organizations who had helped me,  
-directly or not, to make this document possible:  
-  
-  
-  
-  
-  
-  
-*  
-  
-My wife Cielo and my sons Jose, Dario and Gustavo by their patient and  
-support.  
-  
-  
-*  
-*  
-  
-Linux Documentation Project  
-for publishing and uploading my document.  
-  
-  
-*  
-*  
-  
-  
-The site http://www.docum.org  
-drived by Stef Coene that give me some ideas for writing this document.  
-  
-  
-*  
-*  
-  
-  
-Paul "Rusty" Rusell who write the kernel firewall code,  
-the excelent package ''iptables'' and the  
-associated library ''libiptc''.  
-  
-  
-*  
-*  
-  
-  
-Harald Welte who write the utility ''iptables-save''.  
-  
-  
-*  
-*  
-  
-  
-Alexey Kuznetsov who write the kernel queue discipline code and the  
-excelent package ''iproute2''.  
-  
-  
-*  
-*  
-  
-  
-Tabatha Persad from the  
-Linux Documentation Project  
-who revised my english syntax and writing, gave me several ideas to  
-improve the content and encouraged me to learn and use !DocBook to write  
-the final version of this document.  
-  
-  
-*----  
-!!!5. Objectives  
-  
-This HOWTO explains how to use the ''libiptc'' library  
-included in the ''iptables'' package. This document can  
-show you how to use short C or C++ programs to query the internal structure  
-of the firewalling code, to check chains and rules, packet and byte counters,  
-and in a second phase, if you are a little "brave", to modify  
-them.  
-  
-  
-  
-You can find the latest version of this document at  
-Querying libiptc HOWTO.html.  
-  
-  
-  
-If you have suggestions to help make this document better, please submit  
-your ideas to me at the following address:  
-leonardo@opalsoft.net.  
-  
-  
-  
-While I wrote this HOWTO, I developed a simple bandwith meter using  
-user-defined chains to get the data to be measured. This idea was conceived  
-looking at __monitor.pl__, a simple perl program for bandwith  
-measurement, written by Stef Coene at  
-http://www.docum.org.  
-I recommend this site to people interested in bandwidth control and  
-measurement.  
-  
-----  
-!!!6. What is libiptc?  
-  
-''libiptc'' is the library that is used to communicate  
-with netfilter, the internal kernel code in charge of firewalling and packet  
-filtering. This code and ''iptables'' were written by Paul  
-"Rusty" Russell. ''iptables'' was developed  
-using ''libiptc'' calls to get the job done.  
-  
-  
-  
-If you want to have more information about ''iptables'',  
-''libiptc'' and the firewalling code, have a look at  
-links at the end of this document.  
-  
-----  
-!!!7. How did I obtain this knowledge?  
-  
-  
-Just looking at code in ''iptables 1.2.6'' package and  
-especially at program ''iptables-save.c'' that use  
-''libiptc'' to dump information from firewalling  
-kernel code.  
-  
-  
-  
-  
-I will try to be very pragmatic and clear in order to make this HOWTO  
-useful.  
-  
-----  
-!!!8. Previous knowledge and system requirements  
-  
-You have to have some previous knowledge to follow this document:  
-  
-  
-  
-  
-  
-  
-#  
-  
-''Very important:''  
-You must know how to use the ''iptables'' package as a  
-user, such as how to create or list rules and user chains. You do not need  
-to be a firewall expert, but you should know how to use  
-''iptables'' fluently.  
-  
-  
-#  
-#  
-  
-You have to have kernel sources installed in your system, in  
-/usr/src/linux as usual.  
-  
-  
-  
-I am using a ''2.4.16'' kernel in a  
-''SuSE 7.1'' Linux environment. You need  
-''2.4.x'' kernel code to follow this HOWTO, preferably kernel  
-''2.4.16''. For ''SuSE'' you can  
-get the kernel sources at  
-ftp://ftp.gwdg.de/pub/linux/suse/ftp.suse.com/suse/i386/update.  
-  
-  
-#  
-#  
-  
-You have to know how to compile the kernel if you have to update your kernel  
-version. After activating the netfilter options using  
-__make menuconfig__, you  
-must compile and install the kernel as usual.  
-  
-  
-#  
-#  
-  
-Reboot your new kernel using __init 6__. Ensure that you  
-backup a copy of your previous kernel in ''lilo'' in case  
-you encounter a problem and need to retrace your steps.  
-  
-  
-#  
-#  
-  
-Be sure that your new ''2.4.x'' kernel is running fine.  
-To install ''iptables-1.2.6'' you will need to patch the  
-kernel again (and re-compile and install it), and it is better if you follow  
-the previous two steps to ensure that your kernel is running right before  
-applying new iptables patches.  
-  
-  
-#----  
-!!!9. Installing iptables + libiptc  
-  
-To install ''libiptc'' follow these steps:  
-  
-  
-  
-  
-  
-  
-#  
-  
-Download ''iptables-1.2.6.tar.bz2'' from  
-http://netfilter.samba.org/.  
-  
-  
-#  
-#  
-  
-Copy the ''iptables'' tar file into  
-/usr/local/src:  
-  
-  
-bash# __cp iptables-1.2.6.tar.bz2 /usr/local/src__  
-#  
-#  
-  
- Unpack:  
-  
-  
-bash# __tar xjvf iptables-1.2.6.tar.bz2__  
-#  
-#  
-  
- Go into the iptables directory:  
-  
-  
-bash# __cd iptables-1.2.6__  
-#  
-#  
-  
-Check to see if your kernel needs some aditional patches with:  
-  
-  
-bash# __make pending-patches__ ''KERNEL_DIR=/usr/src/linux''  
-  
-If your kernel source is located somewhere other than in  
-/usr/src/linux, replace the kernel source directory in  
-the command line above with your source directory.  
-  
-  
-  
-Be careful with this option. This command invokes  
-''patch-o-matic'', a new patch verification utility by  
-Rusty Russell. The utility will show you a list of new patches (some  
-proposed, some submitted, some accepted) available for your kernel source.  
-As Rusty himself says, "Some of these new patches have bugs",  
-and you do not have to apply all of them.  
-  
-  
-  
-Read the information showed for each patch carefully and answer with  
-__y__ (apply the patch) or __N__ (skip this patch).  
-In some cases answering __y__ will try to apply the patch, but  
-if the patch finds some differences between your sources, it will be  
-skipped and the next new one presented.  
-  
-  
-  
-I did not apply any of the proposed patches and kept my kernel in its  
-original state before continuing to the next step.  
-  
-  
-#  
-#  
-  
-Make the iptables package with:  
-  
-  
-bash# __make__ ''KERNEL_DIR=/usr/src/linux''  
-  
-Again, if your kernel source is not at /usr/src/linux,  
-replace the kernel source directory in the command above.  
-  
-  
-  
-If all goes right the compiler will finish without errors.  
-  
-  
-#  
-#  
-  
-Before the next step, check to see if you have installed iptables package by  
-typing:  
-  
-  
-bash# __rpm -q iptables__  
-  
-If the iptables rpm is installed, you will see the name and version of the  
-package, similar to:  
-  
-  
-  
-''iptables-1.1.2-13''  
-  
-  
-  
-In this case un-install with:  
-  
-  
-bash# __rpm -e iptables__  
-#  
-#  
-  
-Install the new created package:  
-  
-  
-bash# __make install__ ''KERNEL_DIR=/usr/src/linux''  
-  
-Again, check your kernel source directory.  
-  
-  
-  
-This command will install the binaries (''iptables, iptables-save,  
-iptables-restore'') in /usr/local/sbin, the manuals  
-in /usr/local/man/man8 and the modules in  
-/usr/local/lib/iptables.  
-  
-  
-#  
-#  
-  
-Finally install the headers, development libraries and associated  
-development man pages, with:  
-  
-  
-bash# __make install-devel__  
-  
-This command will install the ''libiptc'' library  
-in /usr/local/lib.  
-  
-  
-  
-I think something must be wrong with this command. It does not install all  
-headers files properly, so you must install them yourself using:  
-  
-  
-bash# __cd /usr/local/src/iptables-1.2.6__  
-bash# __cp include/iptables.h /usr/local/include__  
-bash# __cp include/iptables_common.h /usr/local/include__  
-bash# __mkdir /usr/local/include/libiptc__  
-bash# __cp include/libiptc/libiptc.h /usr/local/include/libiptc__  
-bash# __cp include/libiptc/ipt_kernel_headers.h /usr/local/include/libiptc__  
-bash# __cp iptables.o /usr/local/lib__  
-  
-iptables.o is needed above to compile programs to get  
-rule information from netfilter.  
-  
-  
-  
-Now you are ready to create programs that can communicate directly with libiptc.  
-  
-  
-#----  
-!!!10. How to create your program(s)  
-  
-Create your program(s) in /usr/local/src;  
-this way you will not have problems with gcc looking for files in the "include" section.  
-  
-  
-  
-Your program(s) would be something like this:  
-  
-  
-/* My program */  
-#include `getopt.hb  
-#include `sys/errno.hb  
-#include `stdio.hb  
-#include `fcntl.hb  
-#include `stdlib.hb  
-#include `string.hb  
-#include `dlfcn.hb  
-#include `time.hb  
-#include "libiptc/libiptc.h"  
-#include "iptables.h"  
-int main(void)  
-{  
-'' /* Use always this part for your programs .... From here ... **** */''  
-iptc_handle_t h;  
-const char *chain = NULL;  
-const char *tablename = NULL;  
-program_name = "my_program";  
-program_version = NETFILTER_VERSION;  
-'' /* .... To here .... ******************************************** */''  
-'' /* From here you write your own code */''  
-.... your code ...  
-....  
-....  
-} /* main */  
-  
-  
-  
-  
-*  
-  
-The "include" section is ''a must'' in your c/c++ program(s).  
-  
-  
-*  
-*  
-  
-If you are using c++ do not forget to write extern "C" for  
-these include.  
-  
-  
-*----  
-!!!11. Functions to query libiptc  
-  
-This section explains which functions allow you to query libiptc. We will use  
-the header file of ''libiptc'',  
-file usr/local/include/libiptc/libiptc.h,  
-containing prototypes of each function as a reference to develop our explanation.  
-  
-  
-  
-I have also included a brief description (when available) taken from  
-Linux netfilter Hacking HOWTO within each function explanation.  
-  
-----  
-!!11.1. iptc_init  
-  
-__Name: __iptc_init  
-  
-  
-  
-__Usage: __Takes a snapshot of the rules.  
-  
-  
-  
-__Prototype: __iptc_handle_t iptc_init(const char *tablename)  
-  
-  
-  
-__Description: __This function must be called as initiator before any other function can be  
-called.  
-  
-  
-  
-__Parameters: __''tablename'' is the name of the table we need to query  
-and/or modify; this could be ''filter'',  
-''mangle'', ''nat'', etc.  
-  
-  
-  
-__Returns: __Pointer to a structure of type ''iptc_handle_t'' that must  
-be used as main parameter for the rest of functions we will call  
-from ''libiptc''. ''iptc_init'' returns the  
-pointer to the structure or NULL if it fails. If this happens you can invoke  
-''iptc_strerror'' to get information about the error.  
-See below.  
-  
-  
-  
-Have a look at this section of code in file iptables-save.c  
-for how to invoke this function:  
-  
-  
- h = iptc_init(tablename);  
-if (!h)  
-exit_error(OTHER_PROBLEM, "Can't initialize: %s\n",iptc_strerror(errno));----  
-!!11.2. iptc_strerror  
-  
-__Name: __iptc_strerror  
-  
-  
-  
-__Usage: __Translates error numbers into more human-readable form.  
-  
-  
-  
-__Prototype: __const char *iptc_strerror(int err)  
-  
-  
-  
-__Description: __This function returns a more meaningful explanation of a failure code in  
-the iptc library. If a function fails, it will always set  
-''errno''. This value can be passed to  
-''iptc_strerror()'' to yield an error message.  
-  
-  
-  
-__Parameters: __''err'' is an integer indicating the error number.  
-  
-  
-  
-__Returns: __Char pointer containing the error description.  
-  
-----  
-!!11.3. iptc_first_chain  
-  
-__Name: __iptc_first_chain  
-  
-  
-  
-__Usage: __Iterator functions to run through the chains.  
-  
-  
-  
-__Prototype: __const char *iptc_first_chain(iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function returns the first chain name in the table.  
-  
-  
-  
-__Parameters: __Pointer to a structure of type ''iptc_handle_t'' that was  
-obtained by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Char pointer to the name of the chain.  
-  
-----  
-!!11.4. iptc_next_chain  
-  
-__Name: __iptc_next_chain  
-  
-  
-  
-__Usage: __Iterator functions to run through the chains.  
-  
-  
-  
-__Prototype: __const char *iptc_next_chain(iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function returns the next chain name in the table; NULL means  
-no more chains.  
-  
-  
-  
-__Parameters: __Pointer to a structure of type ''iptc_handle_t'' that was  
-obtained by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Char pointer to the name of the chain.  
-  
-  
-  
-These two previous functions allow to us to iterate through the chains of the table  
-getting the name of each of the chains; ''iptc_first_chain''  
-returns the name of the first chain of the table; ''iptc_next_chain''  
-returns the name of next chains and NULL when the function reaches the end.  
-  
-  
-  
-We can create ''Program #1'' to exercise our understanding of  
-these previous four functions:  
-  
-  
-/*  
-* How to use libiptc- program #1  
-* /usr/local/src/p1.c  
-*/  
-#include `getopt.hb  
-#include `sys/errno.hb  
-#include `stdio.hb  
-#include `fcntl.hb  
-#include `stdlib.hb  
-#include `string.hb  
-#include `dlfcn.hb  
-#include `time.hb  
-#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(8h); chain; chain = iptc_next_chain(8h)) {  
-printf("%s\n", chain);  
-}  
-exit();  
-} /* main */  
-  
-Write this program and save it as p1.c  
-in /usr/local/src.  
-  
-  
-  
-Now write this "bash" script to simplify the compiling process:  
-  
-  
-#!/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  
-  
-Save it as ipt-cc and do not forget to  
-''chmod 0700 ipt-cc''.  
-  
-  
-  
-Now compile your ''p1'' program:  
-  
-  
-bash# __./ipt-cc p1__  
-  
-And run it:  
-  
-  
-bash# __./p1__  
-  
-You will get:  
-  
-  
-INPUT  
-FORWARD  
-OUTPUT  
-  
-These are the three built-in iptables chains.  
-  
-  
-  
-Now create some new chains using iptables and run your program again:  
-  
-  
-bash# __iptables -N chain_1__  
-bash# __iptables -N chain_2__  
-bash# __./p1__  
-  
-You will get:  
-  
-  
-INPUT  
-FORWARD  
-OUTPUT  
-chain_1  
-chain_2  
-  
-Try to generate an error initializing tablename to ''myfilter''  
-instead of ''filter''. When you compile and execute your program  
-again, you will get:  
-  
-  
-''Error initializing: Table does not exist (do you need to insmod?)''  
-  
-''iptables'' informs you that ''myfilter'' does  
-not exist as a table.  
-  
-----  
-!!11.5. iptc_is_chain  
-  
-__Name: __iptc_is_chain  
-  
-  
-  
-__Usage: __Check if a chain exists.  
-  
-  
-  
-__Prototype: __int iptc_is_chain(const char *chain, const iptc_handle_t handle)  
-  
-  
-  
-__Description: __This function checks to see if the chain described in the parameter  
-''chain'' exists in the table.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer containing the name of  
-the chain we want to check to. ''handle'' is a pointer to a  
-structure of type ''iptc_handle_t'' that was  
-obtained by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __integer value 1 (true) if the chain exists; integer value 0 (false)  
-if the chain does not exist.  
-  
-----  
-!!11.6. iptc_builtin  
-  
-__Name: __iptc_builtin  
-  
-  
-  
-__Usage: __Is this a built-in chain?  
-  
-  
-  
-__Prototype: __int iptc_builtin(const char *chain, const iptc_handle_t handle)  
-  
-  
-  
-__Description: __This function is used to check if a given chain name is a built-in  
-chain or not.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer containing the name of  
-the chain we want to check to. ''handle'' is a pointer to a  
-structure of type ''iptc_handle_t'' that was  
-obtained by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if the given chain name is the name  
-of a builtin chain; returns integer value 0 (false) is not.  
-  
-----  
-!!11.7. iptc_first_rule  
-  
-__Name: __iptc_first_rule  
-  
-  
-  
-__Usage: __Get first rule in the given chain.  
-  
-  
-  
-__Prototype: __const struct ipt_entry *iptc_first_rule(const char *chain, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function returns a pointer to the first rule in the given chain  
-name; NULL for an empty chain.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer containing the name of  
-the chain we want to get the rules to. ''handle'' is a  
-pointer to a structure of type ''iptc_handle_t'' that was  
-obtained by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns a pointer to an ''ipt_entry'' structure  
-containing information about the first rule of the chain. See below  
-for an explanation of this structure.  
-  
-----  
-!!11.8. iptc_next_rule  
-  
-__Name: __iptc_next_rule  
-  
-  
-  
-__Usage: __Get the next rule in the given chain.  
-  
-  
-  
-__Prototype: __const struct ipt_entry *iptc_next_rule(const struct ipt_entry *prev, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function returns a pointer to the next rule in the given chain  
-name; NULL means the end of the chain.  
-  
-  
-  
-__Parameters: __''prev'' is a pointer to a structure of type  
-''ipt_entry'' that must be obtained first by a previous call to  
-the function ''iptc_first_rule''. 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. ''handle'' is  
-a pointer to a structure of type ''iptc_handle_t'' that was  
-obtained by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns a pointer to an ''ipt_entry'' structure  
-containing information about the next rule of the chain. See below  
-for an explanation of this structure.  
-  
-----  
-!!11.9. iptc_get_target  
-  
-__Name: __iptc_get_target  
-  
-  
-  
-__Usage: __Get a pointer to the target name of this entry.  
-  
-  
-  
-__Prototype: __const char *iptc_get_target(const struct ipt_entry *e, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __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 ''verdict'' field of the  
-''ipt_entry'' structure directly, as it offers the above further  
-interpretations of the standard verdict.  
-  
-  
-  
-__Parameters: __''e'' is a pointer to a structure of type  
-''ipt_entry'' that must be obtained first by a previous call to  
-the function ''iptc_first_rule'' or the function  
-''iptc_next_rule''. ''handle'' is  
-a pointer to a structure of type ''iptc_handle_t'' that was  
-obtained by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns a char pointer to the target name. See ''Description''  
-above for more information.  
-  
-  
-  
-Now it is time to explain the ''ipt_entry'' structure; these pieces  
-of code are taken from ''iptables'' package sources:  
-  
-  
-/* 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[[];  
-};  
-  
-An ''ipt_entry'' structure contains:  
-  
-  
-  
-  
-  
-  
-*  
-  
-An ''ipt_ip'' structure containing (for the rule) the  
-source address and netmask ''(ip.src.s_addr, ip.smsk.s_addr)'',  
-the destination address and netmask ''(ip.dst.s_addr, ip.dmsk.s_addr)'',  
-the protocol ''(ip.proto)'', a flags field ''(invflags)''  
-to check for inverse ''(!)'' selections  
-''(eg. ! 192.168.2./24, ! eth0, ! tcp, etc)'', the input  
-interface ''(iniface)'', the output interface  
-''(outiface)'', the input ''(iniface_mask)''  
-and output ''(outiface_mask)'' interface masks and the  
-''flags'' field to check for fragmented packets.  
-  
-  
-*  
-*  
-  
-An ''ipt_counters'' structure containing the packet  
-''(pcnt)'' and byte ''(bcnt)'' counter  
-of the rule. This information is important for bandwidth measurement.  
-  
-  
-*  
-*  
-  
-''target_offset'' that is used to get the target information  
-of the rule.  
-  
-  
-*  
-*  
-  
-Unknown fields: ''nfcache, comefrom, elems, next_offset''.  
-If someone can give me a feedback about these fields I would be grateful.  
-  
-  
-*  
-  
-A simple way to work with all this information is to borrow  
-some functions from iptables-save.c by Paul  
-Russell and Harald Welte.  
-  
-  
-  
-Here is another sample program ''Program #2'' written with  
-a lot of help from Russell-Welte:  
-  
-  
-/*  
-* How to use libiptc- program #2  
-* /usr/local/src/p1.c  
-*/  
-#include `getopt.hb  
-#include `sys/errno.hb  
-#include `stdio.hb  
-#include `fcntl.hb  
-#include `stdlib.hb  
-#include `string.hb  
-#include `dlfcn.hb  
-#include `time.hb  
-#include "libiptc/libiptc.h"  
-#include "iptables.h"  
-''/* Here begins some of the code taken from iptables-save.c **************** */''  
-#define IP_PARTS_NATIVE(n) \  
-(unsigned int)((n)bb24)80xFF, \  
-(unsigned int)((n)bb16)80xFF, \  
-(unsigned int)((n)bb8)80xFF, \  
-(unsigned int)((n)80xFF)  
-#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[[] == )  
-return;  
-printf("-%c %s", letter, invert ? "! " : "");  
-for (i = ; i ` IFNAMSIZ; i++) {  
-if (mask[[i] != ) {  
-if (iface[[i] != '\')  
-printf("%c", iface[[i]);  
-} else {  
-/* we can access iface[[i-1 ] here, because  
-* a few lines above we make sure that mask[[] != 0 */  
-if (iface[[i-1] != '\')  
-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 = ; 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-bu.user.name, TRY_LOAD);  
-if (match) {  
-printf("-m %s ", e-bu.user.name);  
-/* some matches don't provide a save function */  
-if (match-bsave)  
-match-bsave(ip, e);  
-} else {  
-if (e-bu.match_size) {  
-fprintf(stderr,  
-"Can't find library for match `%s'\n",  
-e-bu.user.name);  
-exit(1);  
-}  
-}  
-return ;  
-}  
-/* 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 88 !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-bcounters.pcnt, e-bcounters.bcnt);  
-/* print chain name */  
-printf("-A %s ", chain);  
-/* Print IP part. */  
-print_ip("-s", e-bip.src.s_addr,e-bip.smsk.s_addr,  
-e-bip.invflags 8 IPT_INV_SRCIP);  
-print_ip("-d", e-bip.dst.s_addr, e-bip.dmsk.s_addr,  
-e-bip.invflags 8 IPT_INV_DSTIP);  
-print_iface('i', e-bip.iniface, e-bip.iniface_mask,  
-e-bip.invflags 8 IPT_INV_VIA_IN);  
-print_iface('o', e-bip.outiface, e-bip.outiface_mask,  
-e-bip.invflags 8 IPT_INV_VIA_OUT);  
-print_proto(e-bip.proto, e-bip.invflags 8 IPT_INV_PROTO);  
-if (e-bip.flags 8 IPT_F_FRAG)  
-printf("%s-f ",  
-e-bip.invflags 8 IPT_INV_FRAG ? "! " : "");  
-/* Print matchinfo part */  
-if (e-btarget_offset) {  
-IPT_MATCH_ITERATE(e, print_match, 8e-bip);  
-}  
-/* Print target name */  
-target_name = iptc_get_target(e, h);  
-if (target_name 88 (*target_name != '\'))  
-printf("-j %s ", target_name);  
-/* Print targinfo part */  
-t = ipt_get_target((struct ipt_entry *)e);  
-if (t-bu.user.name[[]) {  
-struct iptables_target *target  
-= find_target(t-bu.user.name, TRY_LOAD);  
-if (!target) {  
-fprintf(stderr, "Can't find library for target `%s'\n",  
-t-bu.user.name);  
-exit(1);  
-}  
-if (target-bsave)  
-target-bsave(8e-bip, 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-bu.target_size !=  
-sizeof(struct ipt_entry_target)) {  
-fprintf(stderr, "Target `%s' is missing "  
-"save function\n",  
-t-bu.user.name);  
-exit(1);  
-}  
-}  
-}  
-printf("\n");  
-}  
-''/* Here ends some of the code taken from iptables-save.c ****************** */''  
-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(8h); chain; chain = iptc_next_chain(8h)) {  
-printf("%s\n", chain);  
-for (e = iptc_first_rule(chain, 8h); e; e = iptc_next_rule(e, 8h)) {  
-print_rule(e, 8h, chain, counters);  
-}  
-}  
-exit();  
-} /* main */  
-  
-The function ''print_rule'' borrowed from  
-iptables-save.c prints the information  
-about a rule into a readable form using:  
-  
-  
-  
-  
-  
-  
-*  
-  
-''print_ip'' to print the addresses,  
-  
-  
-*  
-*  
-  
-''print_iface'' to print the interfaces,  
-  
-  
-*  
-*  
-  
-''print_proto'' to print the protocols,  
-  
-  
-*  
-*  
-  
-''iptc_get_target'' to get and print the targets  
-(using ''save'').  
-  
-  
-*  
-  
-In ''main'' we iterate through each chain and  
-for each one we iterate through each rule printing it.  
-  
-  
-  
-The arguments of ''print_rule'' are:  
-  
-  
-  
-  
-  
-  
-*  
-  
-e = pointer to an ''ipt_entry'' structure containing  
-information about the rule.  
-  
-  
-*  
-*  
-  
-h = pointer to an ''iptc_handle_t'' structure returned by  
-''iptc_init''.  
-  
-  
-*  
-*  
-  
-chain = name of the chain.  
-  
-  
-*  
-*  
-  
-counters = : do not print counters; 1: print them.  
-  
-  
-*  
-  
-OK, compile and run program ''p2'':  
-  
-  
-bash# __./ipt-cc p2__  
-bash# __./p2__  
-  
-You will get:  
-  
-  
-INPUT  
-FORWARD  
-OUTPUT  
-chain_1  
-chain_2  
-  
-Now modify the environment using ''iptables'' to add some rules:  
-  
-  
-bash# __iptables -A INPUT -p tcp -i eth0 -s ! 192.168.1.1 --dport 20 -j ACCEPT__  
-bash# __iptables -A chain_1 -p udp -o eth1 -s 192.168.2./24 --sport 33 -j DROP__  
-  
-Now if you run again ''p2'' you will get:  
-  
-  
-INPUT  
-[[:] -A INPUT -s ! 192.168.1.1 -i eth0 -p tcp -m tcp --dport 20 -j ACCEPT  
-FORWARD  
-OUTPUT  
-chain_1  
-[[:] -A chain_1 -s 192.168.2./255.255.255.0 -o eth1 -p udp -m udp --sport 33 -j DROP  
-chain_2  
-  
-We have now rules printed for ''INPUT'' and  
-''chain_1'' chains. The numbers in the  
-brackets at left are packet and byte counters respectively.  
-  
-----  
-!!11.10. iptc_get_policy  
-  
-__Name: __iptc_get_policy  
-  
-  
-  
-__Usage: __Get the policy of a given built-in chain.  
-  
-  
-  
-__Prototype: __const char *iptc_get_policy(const char *chain, struct ipt_counters *counter, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function gets the policy of a built-in chain, and fills in the  
-''counters'' argument with the hit statistics on  
-that policy.  
-  
-  
-  
-__Parameters: __You have to pass as arguments the name of the built-in chain you want  
-to get the policy to, a pointer to an ''ipt_counters''  
-structure to be filled by the function and the  
-''iptc_handle_t'' structure identifying the table we are  
-working to. The ''ipt_counters'' structure was explained  
-in previous section; do not forget that ''iptc_handle_t''  
-must be obtained by a previous call to the function ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns a char pointer to the policy name.  
-  
-  
-  
-Using pieces of programs 1 and 2 we can write ''program #3'':  
-  
-  
-/*  
-* How to use libiptc- program #3  
-* /usr/local/src/p3.c  
-*/  
-#include `getopt.hb  
-#include `sys/errno.hb  
-#include `stdio.hb  
-#include `fcntl.hb  
-#include `stdlib.hb  
-#include `string.hb  
-#include `dlfcn.hb  
-#include `time.hb  
-#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(8h); chain; chain = iptc_next_chain(8h)) {  
-if ( !iptc_builtin(chain, h) )  
-continue;  
-if ( (policy = iptc_get_policy(chain, 8counters, 8h)) )  
-printf("%-10s %-10s [[%llu:%llu]\n",  
-chain, policy, counters.pcnt, counters.bcnt);  
-}  
-exit();  
-} /* main */  
-  
-OK, compile and run program ''p3'':  
-  
-  
-bash# __./ipt-cc p3__  
-bash# __./p3__  
-  
-You will get something like this:  
-  
-  
-BUILT-IN POLICY PKTS-BYTES  
-----------------------------  
-INPUT ACCEPT [[:]  
-FORWARD ACCEPT [[:]  
-OUTPUT ACCEPT [[:]----  
-!!11.11. iptc_read_counter  
-  
-__Name: __iptc_read_counter  
-  
-  
-  
-__Usage: __Read counters of a rule in a chain.  
-  
-  
-  
-__Prototype: __struct ipt_counters *iptc_read_counter(const ipt_chainlabel chain,  
-unsigned int rulenum, iptc_handle_t *handle);  
-  
-  
-  
-__Description: __This function read and returns packet and byte counters of the entry  
-rule in chain ''chain'' positioned at  
-''rulenum''. Counters are returned in a pointer to a  
-type structure ''ipt_counters''. Rule numbers start at  
-1 for the first rule.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be readed; ''rulenum'' is an integer value defined the  
-position in the chain of rules of the rule which counters will be read.  
-''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call to  
-''iptc_init''.  
-  
-  
-  
-__Returns: __Returns a pointer to an ''ipt_counters'' structure  
-containing the byte and packet counters readed.  
-  
-----  
-!!!12. Functions to modify firewalling rules and statistics  
-  
-For those of you who are a little brave, ''libiptc''  
-has a group of functions to directly modify the firewalling rules and  
-statistics ''(use of iptables is really the safest way)''.  
-  
-  
-  
-These functions are not covered by this HOWTO and I will limit myself  
-to presenting improved information taken from  
-libiptc.h and the  
-Linux netfilter Hacking HOWTO by Rusty Russell.  
-  
-----  
-!!12.1. iptc_commit  
-  
-__Name: __iptc_commit  
-  
-  
-  
-__Usage: __Makes the actual changes.  
-  
-  
-  
-__Prototype: __int iptc_commit(iptc_handle_t *handle)  
-  
-  
-  
-__Description: __The tables that you change are not written back until the  
-''iptc_commit()'' function is called. This means it  
-is possible for two library users operating on the same chain to race  
-each other; locking would be required to prevent this, and it is not  
-currently done. There is no race with counters, however; counters are  
-added back in to the kernel in such a way that counter increments  
-between the reading and writing of the table still show up in the new  
-table. ''To protect the status of the system you must commit  
-your changes''.  
-  
-  
-  
-__Parameters: __''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call  
-to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.2. iptc_insert_entry  
-  
-__Name: __iptc_insert_entry  
-  
-  
-  
-__Usage: __Insert a new rule in a chain.  
-  
-  
-  
-__Prototype: __int iptc_insert_entry(const ipt_chainlabel chain, const struct ipt_entry *e,  
-unsigned int rulenum, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function insert a rule defined in structure type  
-''ipt_entry'' in chain ''chain'' into  
-position defined by integer value ''rulenum''. Rule numbers  
-start at 1 for the first rule.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be modified; ''e'' is a pointer to a structure of type  
-''ipt_entry'' that contains information about the rule to  
-be inserted. The programmer must fill the fields of this structure with  
-values required to define his or her rule before passing the pointer as  
-parameter to the function. ''rulenum'' is an integer  
-value defined the position in the chain of rules where the new rule will  
-be inserted. Rule numbers start at 1 for the first rule.  
-''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call to  
-''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.3. iptc_replace_entry  
-  
-__Name: __iptc_replace_entry  
-  
-  
-  
-__Usage: __Replace an old rule in a chain with a new one.  
-  
-  
-  
-__Prototype: __int iptc_replace_entry(const ipt_chainlabel chain, const struct ipt_entry *e,  
-unsigned int rulenum, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function replace the entry rule in chain ''chain''  
-positioned at ''rulenum'' with the rule defined in structure  
-type ''ipt_entry''. Rule numbers start at 1 for the first rule.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be modified; ''e'' is a pointer to a structure of type  
-''ipt_entry'' that contains information about the rule to  
-be inserted. The programmer must fill the fields of this structure with  
-values required to define his or her rule before passing the pointer as  
-parameter to the function. ''rulenum'' is an integer  
-value defined the position in the chain of rules where the old rule will  
-be replaced by the new one. Rule numbers start at 1 for the first rule.  
-''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call to  
-''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.4. iptc_append_entry  
-  
-__Name: __iptc_append_entry  
-  
-  
-  
-__Usage: __Append a new rule in a chain.  
-  
-  
-  
-__Prototype: __int iptc_append_entry(const ipt_chainlabel chain, const struct ipt_entry *e,  
-iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function append a rule defined in structure type  
-''ipt_entry'' in chain ''chain''  
-(equivalent to insert with rulenum = length of chain).  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be modified; ''e'' is a pointer to a structure of type  
-''ipt_entry'' that contains information about the rule to  
-be appended. The programmer must fill the fields of this structure with  
-values required to define his or her rule before passing the pointer as  
-parameter to the function. ''handle'' is a pointer to a  
-structure of type ''iptc_handle_t'' that was obtained by  
-a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.5. iptc_delete_num_entry  
-  
-__Name: __iptc_delete_num_entry  
-  
-  
-  
-__Usage: __Delete a rule in a chain.  
-  
-  
-  
-__Prototype: __int iptc_delete_num_entry(const ipt_chainlabel chain, unsigned int rulenum,  
-iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function delete the entry rule in chain ''chain''  
-positioned at ''rulenum''. Rule numbers start at 1 for the  
-first rule.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be modified; ''rulenum'' is an integer value defined the  
-position in the chain of rules where the rule will be deleted.  
-''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call to  
-''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.6. iptc_flush_entries  
-  
-__Name: __iptc_flush_entries  
-  
-  
-  
-__Usage: __Empty a chain.  
-  
-  
-  
-__Prototype: __int iptc_flush_entries(const ipt_chainlabel chain, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function flushes the rule entries in the given chain (ie. empties chain).  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be flushed; ''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call to  
-''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.7. iptc_zero_entries  
-  
-__Name: __iptc_zero_entries  
-  
-  
-  
-__Usage: __Zeroes the chain counters.  
-  
-  
-  
-__Prototype: __int iptc_zero_entries(const ipt_chainlabel chain, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function zeroes the counters in the given chain.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain  
-which counters will be zero; ''handle'' is a pointer  
-to a structure of type ''iptc_handle_t'' that was obtained  
-by a previous call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.8. iptc_create_chain  
-  
-__Name: __iptc_create_chain  
-  
-  
-  
-__Usage: __Create a new chain.  
-  
-  
-  
-__Prototype: __int iptc_create_chain(const ipt_chainlabel chain, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function create a new chain in the table.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain  
-to be created; ''handle'' is a pointer to a structure  
-of type ''iptc_handle_t'' that was obtained by a previous  
-call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.9. iptc_delete_chain  
-  
-__Name: __iptc_delete_chain  
-  
-  
-  
-__Usage: __Delete a chain.  
-  
-  
-  
-__Prototype: __int iptc_delete_chain(const ipt_chainlabel chain, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function delete the chain identified by the char pointer  
-''chain'' in the table.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain  
-to be deleted; ''handle'' is a pointer to a structure  
-of type ''iptc_handle_t'' that was obtained by a previous  
-call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.10. iptc_rename_chain  
-  
-__Name: __iptc_rename_chain  
-  
-  
-  
-__Usage: __Rename a chain.  
-  
-  
-  
-__Prototype: __int iptc_rename_chain(const ipt_chainlabel oldname, const ipt_chainlabel newname,  
-iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function rename the chain identified by the char pointer  
-''oldname'' to a new name ''newname''  
-in the table.  
-  
-  
-  
-__Parameters: __''oldname'' is a char pointer to the name of the chain  
-to be renamed, ''newname'' is the new name;  
-''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous  
-call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.11. iptc_set_policy  
-  
-__Name: __iptc_set_policy  
-  
-  
-  
-__Usage: __Set the policy in a built-in chain.  
-  
-  
-  
-__Prototype: __int iptc_set_policy(const ipt_chainlabel chain, const ipt_chainlabel policy,  
-struct ipt_counters *counters, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function set the policy in chain ''chain'' to the  
-value represented by the char pointer ''policy''. If you  
-want to set at the same time the counters of the chain, fill those values  
-in a structure of type ''ipt_counters'' and pass a pointer  
-to it as parameter ''counters''. Be careful: the chain  
-''must be'' a built-in chain.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be modified; ''policy'' is a char pointer to the name of  
-the policy to be set. ''counters'' is a pointer to an  
-''ipt_counters'' structure to be used to set the counters  
-of the chain. ''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call to  
-''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.12. iptc_zero_counter  
-  
-__Name: __iptc_zero_counter  
-  
-  
-  
-__Usage: __Zero counters of a rule in a chain.  
-  
-  
-  
-__Prototype: __int iptc_zero_counter(const ipt_chainlabel chain, unsigned int rulenum,  
-iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function zero packet and byte counters of the entry rule in chain  
-''chain'' positioned at ''rulenum''.  
-Rule numbers start at 1 for the first rule.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be modified; ''rulenum'' is an integer value defined the  
-position in the chain of rules of the rule which counters will be zero.  
-''handle'' is a pointer to a structure of type  
-''iptc_handle_t'' that was obtained by a previous call to  
-''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!12.13. iptc_set_counter  
-  
-__Name: __iptc_set_counter  
-  
-  
-  
-__Usage: __Set counters of a rule in a chain.  
-  
-  
-  
-__Prototype: __int iptc_set_counter(const ipt_chainlabel chain, unsigned int rulenum,  
-struct ipt_counters *counters, iptc_handle_t *handle)  
-  
-  
-  
-__Description: __This function set packet and byte counters of the entry rule in chain  
-''chain'' positioned at ''rulenum''  
-with values passed in a type structure ''ipt_counters''.  
-Rule numbers start at 1 for the first rule.  
-  
-  
-  
-__Parameters: __''chain'' is a char pointer to the name of the chain to  
-be modified; ''rulenum'' is an integer value defined the  
-position in the chain of rules of the rule which counters will be set.  
-''counters'' is a pointer to an  
-''ipt_counters'' structure to be used to set the counters  
-of the rule; the programmer must fill the fields of this structure with  
-values to be set. ''handle'' is a pointer to a structure  
-of type ''iptc_handle_t'' that was obtained by a previous  
-call to ''iptc_init''.  
-  
-  
-  
-__Returns: __Returns integer value 1 (true) if successful; returns integer value  
-(false) if fails. In this case ''errno'' is set to the  
-error number generated. Use ''iptc_strerror'' to get a  
-meaningful information about the problem. If errno == , it means there  
-was a version error (ie. upgrade ''libiptc'').  
-  
-----  
-!!!13. Bandwidth meter  
-  
-In this chapter I am going to develop a simple bandwidth meter using  
-the following functions from ''libiptc'':  
-  
-  
-  
-  
-  
-  
-*  
-  
-To initialize the system:  
-''iptc_handle_t iptc_init(const char *tablename)''.  
-  
-  
-*  
-*  
-  
-  
-To catch from errors:  
-''const char *iptc_strerror(int err)''.  
-  
-  
-*  
-*  
-  
-  
-To iterate through the chains of the table:  
-''const char *iptc_first_chain(iptc_handle_t *handle)'' and  
-''const char *iptc_next_chain(iptc_handle_t *handle)''.  
-  
-  
-*  
-*  
-  
-  
-To read packet and byte counters for a specific rule:  
-''struct ipt_counters *iptc_read_counter(const ipt_chainlabel chain,  
-unsigned int rulenum, iptc_handle_t *handle)''.  
-  
-  
-*  
-  
-Also the function ''gettimeofday'' will be used to  
-measure elapsed time and the function ''getopt'' to  
-get options from the command line.  
-  
-  
-  
-I don't know really if the term ''bandwidth meter'' is  
-well used here. I interpret ''bandwidth'' as a reference to  
-a flow capacity; perhaps a better term could be ''flow meter''.  
-  
-  
-  
-Here is the ''bandwidth meter'' bw.c.  
-It's well commented to be easy followed by everyone:  
-  
-  
-/*  
-* How to use libiptc- program #4  
-* /usr/local/src/bw.c  
-* By Leonardo Balliache - 04.09.2002  
-* e-mail: leonardo@opalsoft.net  
-* --WELL COMMENTED-- to be easy followed by everyone.  
-*/  
-/* include files required */  
-#include `getopt.hb  
-#include `sys/errno.hb  
-#include `sys/time.hb  
-#include `stdio.hb  
-#include `fcntl.hb  
-#include `stdlib.hb  
-#include `string.hb  
-#include `dlfcn.hb  
-#include `time.hb  
-#include `unistd.hb  
-#include "libiptc/libiptc.h"  
-#include "iptables.h"  
-/* colors to differentiate chains measures */  
-#define RED "\033[[41m\033[[37m"  
-#define GREEN "\033[[42m\033[[30m"  
-#define ORANGE "\033[[43m\033[[30m"  
-#define BLUE "\033[[44m\033[[37m"  
-#define MAGENTA "\033[[45m\033[[37m"  
-#define CYAN "\033[[46m\033[[30m"  
-#define WHITE "\033[[47m\033[[30m"  
-#define BLACK "\033[[40m\033[[37m"  
-#define RESET "\033[[00m"  
-/* maximum number of chains to be processed */  
-#define MAXUSERCHAINS 7  
-/* time between measures in seconds; adjust as you like */  
-#define SLEEPTIME 1  
-/* structure to count bytes per chain */  
-struct bwcnt {  
-int start; /* the chain was initialized */  
-u_int64_t icnt; /* bytes through; previous measure */  
-u_int64_t ocnt; /* bytes through; current measure */  
-double bw; /* bandwitdh (flow) on this chain */  
-};  
-/* function to calculate differences of time in seconds.  
-* micro-seconds precision.  
-*/  
-double delta(struct timeval a, struct timeval b)  
-{  
-if (a.tv_usec 8 b.tv_usec) {  
-a.tv_sec--;  
-a.tv_usec += 1000000;  
-}  
-return a.tv_sec-b.tv_sec + (a.tv_usec-b.tv_usec)/1000000.;  
-}  
-/* main function */  
-int main(int argc, char *argv[[])  
-{  
-int i, j, ok;  
-double totbw;  
-iptc_handle_t h;  
-int c, act_bw = ;  
-const char *chain = NULL;  
-const char *tablename = "filter";  
-struct timeval ti, to;  
-struct bwcnt bw[[MAXUSERCHAINS];  
-struct ipt_counters *counters;  
-char *col[[9] = { RED,GREEN,ORANGE,BLUE,MAGENTA,CYAN,WHITE,BLACK,RESET };  
-program_name = "bw";  
-program_version = NETFILTER_VERSION;  
-/* check options  
-* we have 2 options:  
-* -c = display current flow (each SLEEPTIME).  
-* -a = display average flow (from start); default option.  
-*/  
-while ((c = getopt (argc, argv, "ac")) != -1)  
-switch (c) {  
-case 'a':  
-act_bw = ;  
-break;  
-case 'c':  
-act_bw = 1;  
-break;  
-case '?':  
-if (isprint(optopt))  
-fprintf (stderr, "Unknown option `-%c'.\n", optopt);  
-else  
-fprintf (stderr,"Unknown option character `\\x%x'.\n",optopt);  
-exit(1);  
-default:  
-abort();  
-}  
-/* initialize array of chains */  
-memset(8bw, , MAXUSERCHAINS * sizeof(struct bwcnt));  
-/* get time to start meter on variable ti */  
-gettimeofday(8ti, NULL);  
-/* fire meter loop */  
-if ( act_bw )  
-printf("Displaying current flow values ...\n");  
-else  
-printf("Displaying average flow values ...\n");  
-/* forever loop; abort the program with ^C */  
-while ( 1 ) {  
-/* you have to initialize for each measure to be done */  
-if ( !(h = iptc_init(tablename)) ) {  
-printf("Error initializing: %s\n", iptc_strerror(errno));  
-exit(errno);  
-}  
-ok = ; /* we start a new loop */  
-gettimeofday(8to, NULL); /* have a time shoot */  
-/* iterate through each chain of the table */  
-for (chain = iptc_first_chain(8h), i = ;  
-chain;  
-chain = iptc_next_chain(8h)) {  
-if ( iptc_builtin(chain, h) )  
-continue; /* if it is a built-in chain, ignore it */  
-/* ok, read the counters of this chain */  
-if ( !(counters = iptc_read_counter(chain, , 8h)) ) {  
-printf("Error reading %s: %s\n", chain, iptc_strerror(errno));  
-exit(errno);  
-}  
-/* check that we do not have more chains than we can process */  
-if ( i b= MAXUSERCHAINS ) {  
-printf("Maximum of %d user chains exceeded!!\n", MAXUSERCHAINS);  
-exit(1);  
-}  
-/* this chain counter has not been initialized; initialize it */  
-if ( bw[[i].start == 0 ) {  
-bw[[i].icnt = counters-bbcnt;  
-bw[[i].start = 1;  
-}  
-/* this chain has a previous measure; take the current one */  
-else {  
-bw[[i].ocnt = counters-bbcnt;  
-if ( bw[[i].ocnt == bw[[i].icnt ) /* no new bytes flowing? */  
-bw[[i].bw = ; /* flow is zero */  
-else  
-/* flow in this chain is:  
-* current bytes count (bw[[i].octn) *minus*  
-* previous bytes count (bw[[i].icnt) *divided by*  
-* 128.0 to convert bytes to kbits *and divided by*  
-* difference in times in seconds *to get*  
-* flow in kbits/sec that is what we want.  
-*/  
-bw[[i].bw = (bw[[i].ocnt - bw[[i].icnt) / (128.0 * delta(to, ti));  
-/* do you want current flow of this chain? initialize previous  
-* bytes count to current bytes count; we get the flow in last  
-* SLEEPTIME elapsed time.  
-*/  
-if ( act_bw )  
-bw[[i].icnt = bw[[i].ocnt;  
-ok = 1; /* ok, we have some measure to show */  
-}  
-++i; /* next chain, please */  
-}  
-/* we iterate and i == ; we do not have user chains at all */  
-if ( i == 0 ) {  
-printf("No user chains to meter!!\n");  
-exit(1);  
-}  
-/* do you want to measure current flow? initialize previous time  
-* to actual time; we get the time elapsed in last SLEEPTIME.  
-*/  
-if ( act_bw )  
-ti = to;  
-/* do we have something to show? ok, display it */  
-if ( ok ) {  
-totbw = ;  
-for ( j = ; j ` i; ++j ) {  
-totbw = totbw + bw[[j].bw; /* calculate total flow */  
-}  
-printf("%s%6.1fk:%s ", col[[7], totbw, col[[8]); /* display total */  
-for ( j = ; j ` i; ++j ) { /* display flow of each chain in color */  
-printf("%s%6.1fk%s ", col[[j], bw[[j].bw, col[[8]);  
-}  
-printf("\n");  
-}  
-sleep(SLEEPTIME); /* rest a little; you go too fast */  
-} /* give us enough time in order to let some bytes flow */  
-exit(); /* bye, we have our measures!! */  
-} /* main */  
-  
-Write your program and compile as before:  
-  
-  
-bash# __./ipt-cc bw__  
-  
-Before using the meter we need to set our environment.  
-  
-  
-  
-First, we have to have at least 2 PCs connected in a network. This is our  
-diagram configuration:  
-  
-  
-+--------+ eth0 eth0 +--------+  
-| PC #1 +-----------------+ PC #2 |  
-+--------+ +--------+  
-eth0=192.168.1.1 eth0=192.168.1.2  
-  
-Second, we need to install a very nice and useful package called  
-''netcat'' written by Hobbit. This  
-''excellent'' package will help us to inject and receive  
-a flow of bytes between 2 NICs. If you don't have the package in your  
-system, download it from http://rr.sans.org/audit/netcat.php.  
-  
-  
-  
-The version that I use is ''1.10-277''. To install it follow  
-these instructions:  
-  
-  
-bash# __cp netcat-1.10.tar.gz /usr/local/src__  
-bash# __tar xzvf netcat-1.10.tar.gz__  
-bash# __cd netcat-1.10__  
-  
-My version requires to make a patch first; check yours if you have a file  
-with a ''.dif'' extension and apply it too:  
-  
-  
-bash# __patch -p0 -i netcat-1.10.dif__  
-  
-Next compile the package using ''make'':  
-  
-  
-bash# __make linux__  
-  
-Copy the binary ''nc'' to your user bin directory:  
-  
-  
-bash# __cp nc /usr/bin__  
-  
-And also to the second PC in your network:  
-  
-  
-bash# __scp nc 192.168.1.2:/usr/bin__  
-  
-We are going to use ''netcat'' to  
-"listen" to a flow of bytes from PC #2 and  
-to "talk" from PC #1. Using tty1 to tty4  
-consoles on PC #2 let's start ''netcat'' to  
-listen from this PC. Go to PC #2 and in tty1 type:  
-  
-  
-bash# __nc -n -v -l -s 192.168.1.2 -p 1001 b/dev/null__  
-  
-''netcat'' must respond with:  
-  
-  
-listening on [[192.168.1.2] 1001 ...  
-  
-This command started ''netcat'' to listen from address  
-''192.168.1.2'' using port number ''1001''.  
-Arguments are: ''-n'' = use numeric address identification;  
-''-v'' = verbose; ''-l'' = listen. All the  
-flow that ''netcat'' receives in  
-''192.168.1.2:1001'' will be redirected to the  
-"black hole" in /dev/null.  
-  
-  
-  
-Repeat the command in tty2, tty3 and tty4; change to tty2 using  
-__ALT-F2__ and after logging in write:  
-  
-  
-bash# __nc -n -v -l -s 192.168.1.2 -p 1002 b/dev/null__  
-  
-Now we are "listening" to the same address but port  
-number ''1002''.  
-  
-  
-  
-Go on now with tty3:  
-  
-  
-bash# __nc -n -v -l -s 192.168.1.2 -p 1003 b/dev/null__  
-  
-And tty4:  
-  
-  
-bash# __nc -n -v -l -s 192.168.1.2 -p 1004 b/dev/null__  
-  
-Now we are listening in PC #2, address  
-''192.168.1.2'' in ports ''1001'',  
-''1002'', ''1003'' and  
-''1004''.  
-  
-  
-  
-Come back to PC #1 and let's set the environment to allow  
-''iptables'' to help us to complete our tests:  
-  
-  
-  
-On PC #1, type the into tty1 as follows:  
-  
-  
-bash# __iptables -F__  
-bash# __iptables -X__  
-bash# __iptables -N chn_1__  
-bash# __iptables -N chn_2__  
-bash# __iptables -N chn_3__  
-bash# __iptables -N chn_4__  
-bash# __iptables -A chn_1 -j ACCEPT__  
-bash# __iptables -A chn_2 -j ACCEPT__  
-bash# __iptables -A chn_3 -j ACCEPT__  
-bash# __iptables -A chn_4 -j ACCEPT__  
-bash# __iptables -A OUTPUT -o eth0 -p tcp --dport 1001 -j chn_1__  
-bash# __iptables -A OUTPUT -o eth0 -p tcp --dport 1002 -j chn_2__  
-bash# __iptables -A OUTPUT -o eth0 -p tcp --dport 1003 -j chn_3__  
-bash# __iptables -A OUTPUT -o eth0 -p tcp --dport 1004 -j chn_4__  
-  
-These commands will:  
-  
-  
-  
-  
-  
-  
-*  
-  
-Flush all chains in table ''filter''.  
-  
-  
-*  
-*  
-  
-  
-Delete all user chains in table ''filter''.  
-  
-  
-*  
-*  
-  
-  
-Create user chains ''chn_1'',  
-''chn_2'', ''chn_3'' and  
-''chn_4''.  
-  
-  
-*  
-*  
-  
-  
-Establish a target ''ACCEPT'' in each user chain.  
-  
-  
-*  
-*  
-  
-  
-Create 4 rules in chain ''OUTPUT'' that matches  
-port numbers ''1001'' to  
-''1004'' and target it to user chains  
-''chn_1'' to ''chn_4''.  
-  
-  
-*  
-  
-Now start the ''bw'' meter using current values:  
-  
-  
-bash# __./bw -c__  
-  
-It must respond with:  
-  
-  
-Displaying current flow values ...  
-.0k: .0k .0k .0k .0k  
-.0k: .0k .0k .0k .0k  
-.0k: .0k .0k .0k .0k  
-.0k: .0k .0k .0k .0k  
-  
-It informs that measures are current flows. Every line is a measure  
-taken each ''SLEEPTIME'' lapse (1 second in our  
-program). First column (in black) are total flow, next columns (in red,  
-green, orange and blue) are flows in chains ''chn_1'',  
-''chn_2'', ''chn_3'' and  
-''chn_4'' respectively. Of course we do not have any  
-flow now. However let ''bw'' run and continue reading.  
-  
-  
-  
-Let's start now one of our byte flows; go to tty2 in PC #1 with  
-__ALT-F2__ and after logging in, type:  
-  
-  
-bash# __yes 000000000000000000 | nc -n -v -s 192.168.1.1 -p 2001 192.168.1.2 1001__  
-  
-''netcat'' responds with:  
-  
-  
-(UNKNOWN) [[192.168.1.2] 1000 (?) open  
-  
-Now we have a flow of bytes from PC #1 to PC #2. ''yes''  
-generates a constant flow of zeroes; this flow is piped to  
-''netcat'' through address ''192.168.1.1'',  
-port ''2001'' and sends it to PC #2, address  
-''192.168.1.2'', port ''1001''  
-(where PC #2 is listening).  
-  
-  
-  
-Check now the display of ''bw'' in tty1:  
-  
-  
-7653.2k: 7653.2k .0k .0k .0k  
-7829.5k: 7829.5k .0k .0k .0k  
-7786.7k: 7786.7k .0k .0k .0k  
-7892.1k: 7982.1k .0k .0k .0k  
-  
-Your mileage can vary depending of the physical characteristics of your  
-system. In mine I have a flow of aproximately 7700 kbits/sec in the first  
-chain ''chn_1'' which corresponds to port number  
-''1001'' in PC #2.  
-  
-  
-  
-Let's start now the second bytes flow; go to tty3 in PC #1 with  
-__ALT-F3__ and after logging in, type:  
-  
-  
-bash# __yes 000000000000000000 | nc -n -v -s 192.168.1.1 -p 2002 192.168.1.2 1002__  
-  
-''netcat'' responds with:  
-  
-  
-(UNKNOWN) [[192.168.1.2] 1002 (?) open  
-  
-Now we have 2 flows of bytes from PC #1 to PC #2; one from  
-''192.168.1.1:2001'' to  
-''192.168.1.2:1001'' and another from  
-''192.168.1.1:2002'' to  
-''192.168.1.2:1002''.  
-  
-  
-  
-Now check the display of ''bw'' in tty1:  
-  
-  
-7819.6k: 4144.2k 3675.4k .0k .0k  
-8090.5k: 3923.9k 4166.6k .0k .0k  
-7794.7k: 3920.8k 3873.9k .0k .0k  
-7988.3k: 3754.6k 4233.7k .0k .0k  
-  
-Now we have 2 flows; each of them is more or less 50% of the total flow  
-going out of the computer. The Linux kernel tries to balance the bandwidth  
-available between the 2 channels of output.  
-  
-  
-  
-To continue, start the 2 aditional flows through channels  
-''192.168.1.1:2003-192.168.1.2:1003'' and  
-''192.168.1.1:2004-192.168.1.2:1004''.  
-  
-  
-  
-In tty4 type:  
-  
-  
-bash# __yes 000000000000000000 | nc -n -v -s 192.168.1.1 -p 2003 192.168.1.2 1003__  
-  
-In tty5 type:  
-  
-  
-bash# __yes 000000000000000000 | nc -n -v -s 192.168.1.1 -p 2004 192.168.1.2 1004__  
-  
-The display of ''bw'' in tty1 will be something like:  
-  
-  
-8120.6k: 1705.3k 2354.9k 1898.6k 2161.8k  
-7765.3k: 1634.2k 2560.2k 2011.4k 1559.5k  
-7911.9k: 1699.8k 2090.3k 1768.0k 2353.8k  
-8309.4k: 1734.5k 1999.7k 1999.9k 2575.3k  
-  
-Total bandwidth is distributed between the 4 channels of flow.  
-  
-----  
-!!!14. Controlling flows  
-  
-In this chapter we are going to try to control the flows using the Linux  
-kernel queue disciplines. Perhaps, depending on how you compiled your  
-kernel, you will again need to run __make menuconfig__,  
-re-configure your options, re-compile and re-install your kernel.  
-  
-  
-  
-This chapter ''is not'' and  
-''does not pretend to be'' a tutorial about the  
-implementation of ''QoS (Quality of Service)'' in Linux.  
-If you don't have previous experience with ''QoS''  
-it's better to read some references at the end of this document to acquire  
-the concepts required for ''QoS'' implementation.  
-  
-  
-  
-With this advice, I'm not going to explain in detail each of the  
-commands needed to control flows in Linux because it is not the goal of  
-this HOWTO. However, the implementation of some of these techniques will  
-serve us to show the bandwidth meter (based on ''libiptc'')  
-behaviour.  
-  
-  
-  
-First check if you have QoS implementation options implemented in your  
-kernel. Run __make menuconfig__, follow the menu to  
-''Networking options'' and look for last menu of this  
-option ''QoS and/or fair queueing''. Here use (or check  
-if they are active) these options:  
-  
-  
- [[*] QoS and/or fair queueing  
-`Mb CBQ packet scheduler  
-`Mb CSZ packet scheduler  
-[[*] ATM pseudo-scheduler  
-`Mb The simplest PRIO pseudoscheduler  
-`Mb RED queue  
-`Mb SFQ queue  
-`Mb TEQL queue  
-`Mb TBF queue  
-`Mb GRED queue  
-`Mb Diffserv field marker  
-`Mb Ingress Qdisc  
-[[*] QoS support  
-[[*] Rate estimator  
-[[*] Packet classifier API  
-`Mb TC index classifier  
-`Mb Routing table based classifier  
-`Mb Firewall based classifier  
-`Mb U32 classifier  
-`Mb Special RSVP classifier  
-`Mb Special RSVP classifier for IPv6  
-[[*] Traffic policing (needed for in/egress)  
-  
-Save your configuration, recompile your kernel and modules, and  
-re-install it. We are going to use the  
-''CBQ packet scheduler'' to implement some queues  
-to control bytes flow in our PC #1 NIC.  
-  
-  
-  
-Personally I preferred the excellent ''HTB queueing  
-discipline implementation'' by Martin Devera but actually this  
-implementation is not in standard Linux (but it will be); for  
-implementing it you have to patch your kernel before recompiling and  
-it's better not to complicate things more. However I have to say that  
-this queue discipline is a lot more simple to use than  
-''CBQ'' happens to be. More information on  
-''HTB queueing discipline'' are linked at the end of  
-this document.  
-  
-  
-  
-Having compiled and re-installed your kernel you have to install the  
-''iproute2'' package that will be used to run the  
-commands needed to implement the queues. Download this package from  
-ftp://ftp.inr.ac.ru/ip-routing.  
-  
-  
-  
-I'm working with version ''2.2.4-now-ss001007''. To install  
-it follow these instructions:  
-  
-  
-bash# __cp iproute2-2.2.4-now-ss001007.tar.gz /usr/local/src__  
-bash# __tar xzvf iproute2-2.2.4-now-ss001007.tar.gz__  
-bash# __cd iproute2__  
-bash# __make__  
-  
-After ''make'' compiles the ''iproute2''  
-package successfully the ''ip'' utility will be in  
-iproute2/ip directory and the  
-''tc'' utility in iproute2/tc  
-directory. Copy both of them to /usr/bin directory:  
-  
-  
-bash# __cp ip/ip /usr/bin__  
-bash# __cp tc/tc /usr/bin__  
-  
-Now, using the ''tc'' utility, we are going to create a  
-''CBQ'' queue in the interface ''eth0'' of  
-the PC #1 computer. This queue will have 4 classes as children and each of  
-these classes will be used to control the 4 flows from  
-''192.168.1.1'' to ''192.168.1.2''  
-through ports ''1001'' to ''1004''.  
-  
-  
-  
-Write and run the following commands:  
-  
-  
-bash# __tc qdisc add dev eth0 root handle 1:0 cbq bandwidth 10Mbit \  
-avpkt 1000 cell 8__  
-  
-This command creates the main (root) cbq queue 1:0 in the  
-''eth0'' interface; the bandwidth of this queue is  
-10Mbit/sec corresponding to our Ethernet interface.  
-  
-  
-  
-Now write and run:  
-  
-  
-bash# __tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit \  
-rate 1000kbit prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded__  
-  
-This command create the main cbq class 1:1. The rate of this class  
-will be 1000kbit/sec.  
-  
-  
-  
-Now we are going to create 4 classes ownned by this class; the classes  
-will have rates of 100kbit, 200kbit, 300kbit and 400kbit respectively.  
-Write and run these commands:  
-  
-  
-bash# __tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 10Mbit \  
-rate 100kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000__  
-bash# __tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 10Mbit \  
-rate 200kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000__  
-bash# __tc class add dev eth0 parent 1:1 classid 1:5 cbq bandwidth 10Mbit \  
-rate 300kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000__  
-bash# __tc class add dev eth0 parent 1:1 classid 1:6 cbq bandwidth 10Mbit \  
-rate 400kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000__  
-  
-Each of these classes will have a ''sfq'' queue discipline  
-attached to them to dispatch their packets. Write and run these commands:  
-  
-  
-bash# __tc qdisc add dev eth0 parent 1:3 handle 30: sfq perturb 15__  
-bash# __tc qdisc add dev eth0 parent 1:4 handle 40: sfq perturb 15__  
-bash# __tc qdisc add dev eth0 parent 1:5 handle 50: sfq perturb 15__  
-bash# __tc qdisc add dev eth0 parent 1:6 handle 60: sfq perturb 15__  
-  
-These commands create 4 ''sfq'' queue disciplines, one  
-for each class. ''sfq'' queue discipline is some kind of  
-''fair controlling queue''. It tries to give to each connection  
-in an interface same oportunity to their packets to be dispatched to at all.  
-  
-  
-  
-Finally we are going to create filters to assign flows to ports  
-''1001'', ''1002'', ''1003''  
-and ''1004'' to classes ''1:3'',  
-''1:4'', ''1:5'' and  
-''1:6'' respectively. Write and run as follows:  
-  
-  
-bash# __tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \  
-dport 1001 0xffff flowid 1:3__  
-bash# __tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \  
-dport 1002 0xffff flowid 1:4__  
-bash# __tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \  
-dport 1003 0xffff flowid 1:5__  
-bash# __tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \  
-dport 1004 0xffff flowid 1:6__  
-  
-After running all these commands, now check your ''bw''  
-meter (you must be running ''netcat'' listening at ports  
-''1001'' to ''1004'' in PC #2 and  
-talking in PC #1 as was explained in previous chapter and ''bw''  
-running in ''current -c'' mode). You will have something  
-like this:  
-  
-  
-Current flow values ...  
-1099.9k: 108.8k 196.5k 337.9k 456.8k  
-1104.2k: 115.3k 184.9k 339.9k 464.1k  
-1102.1k: 117.3k 174.7k 339.7k 470.5k  
-1114.4k: 113.6k 191.7k 340.7k 468.4k  
-1118.4k: 113.7k 194.3k 340.5k 469.9k  
-  
-''bw'' show us how flows are controlling using queue  
-disciplines of the Linux kernel. As you see,  
-''CBQ queue discipline'' is not a very precise queue but  
-you more or less have a flow of approximately  
-''1000=100+200+300+400'' on interface  
-''eth0''.  
-  
-  
-  
-To step back, write and run as follows:  
-  
-  
-bash# __tc qdisc del dev eth0 root handle 1:0 cbq__  
-  
-on PC #1, to delete the main (root) queue discipline and owned classes  
-and filters.  
-  
-  
-bash# __killall nc__  
-  
-on PC #2 and PC #1, to stop ''netcat''.  
-  
-  
-bash# __iptables -F__  
-bash# __iptables -X__  
-  
-on PC #1, to clear ''iptables'' rules and chains.  
-  
-  
-bash# __Ctrl-C__  
-  
-on PC #1, tty1 to stop ''bw'' bandwidth meter.  
-  
-----  
-!!!15. Some interesting links  
-  
-  
-  
-  
-#  
-  
-  
-iptables-1.2.6 by Paul Russell.  
-  
-  
-#  
-#  
-  
-  
-Linux netfilter Hacking HOWTO by Paul Russell.  
-  
-  
-#  
-#  
-  
-  
-iproute2 by Alexey Kuznetsov.  
-  
-  
-#  
-#  
-  
-  
-Advance routing Linux HOWTO.  
-  
-  
-#  
-#  
-  
-  
-HTB queueing discipline implementation by Martin Devera.  
-  
-  
-#  
-#  
-  
-  
-Linux-Advance Networking Overview by Saravanan Radhakrishnan.  
-  
-  
-#  
-#  
-  
-  
-monitor.pl by Stef Coene.  
-  
-  
-#  
-#  
-  
-  
-netcat by Hobbit.  
-  
-  
-#----  
-!!!16. About the author  
-  
-  
-Leonardo Balliache is a power electrical engineer that left high voltage  
-lines, transformers and protection relays in 1983 to dedicated full of his  
-time to computer sciences.  
-  
-  
-  
-  
-He is the General Manager of !OpalSoft, a venezuelan company dedicated to  
-business packages software development.  
-  
-  
-  
-  
-In 1989 he started learning Unix using Coherent operating system. After  
-this he was interested in Linux and specially in bandwidth bottleneck  
-problems, bandwidth controlling, packet filtering and hierarching, Linux  
-QoS (Quality of Service), advanced routing, network protection, firewalling,  
-private network connection through the Internet and solving line and server  
-load balancing problems.  
-  
-  
-  
-  
-His company will be opening a new area of business offering Linux  
-QoS solution implementations in Venezuela.  
-  
-  
-  
-  
-Married to Cielo, with 3 sons (Jose, Dario, Gustavo), he can be reached at  
-leonardo@opalsoft.net.  
-He is working now (please be patient) to open a QoS Linux information site  
-at http://opalsoft.net/qos/ to interchange knowledge with people  
-interested and to make his works in the Linux "best of all"  
-operating system available to the public .  
-  
-  
-  
-April 30, 2002  
-  
-  
-  
-  
-Caracas, Venezuela  
+Describe [HowToQueryinglibiptcHOWTO ] here.