[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20081027044303.52643C64089@host1.ystp.ac.ir>
Date: Mon, 27 Oct 2008 08:13:03 +0330 (IRST)
From: hamid.jafarian@...il.com (hamid jafarian)
to: Netfilter-devel <netfilter-devel@...r.kernel.org>
cc: Amin Azez <azez@...mechanic.net>
subject: [PATCH 02/09]IPtablestng/KernelSpace - create pkt_tables.h
create pkt_tables.h file:Contains all of the new structures and semantics.
this patch creates a new file named pkt_tables.h. New definitions for tables/cahins/entries, structures used for management activities, and also structurs that are needed for kernelspace/userspace communication are located in this file.
some important structures are:
pkt_table: new definition for tables: as Containor of builtin/userdefined chains.
pktt_regtable: for table registeration and subsequent accesses to the table by table's modules(e.g. unregister table)
pktt_chain: new definition for chains: as Containor of entries. He also has an element of type 'xt_target': by this, all of the chains can be used as target.
pktt_entry: new definition for entries
pktt_command: cammnad structre for communicating between kernel/user spaces
pktt_classifier: key feature to define/implement and use from diferent classification algorithms.
diff --git a/include/linux/netfilter/pkt_tables.h b/include/linux/netfilter/pkt_tables.h
new file mode 100644
index 0000000..c5729f3
--- /dev/null
+++ b/include/linux/netfilter/pkt_tables.h
@@ -0,0 +1,542 @@
+/* Packet Tables Code
+ *
+ * Copyright (C) 2005-2008 Hamid Jafarian(hm.t.) <hamid.jafarian@...il.com>
+ */
+
+#ifndef _PKT_TABLES_H
+#define _PKT_TABLES_H
+#ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <asm/atomic.h>
+#include <net/net_namespace.h>
+
+
+#define pktt_info( str, args...)
+#if 0
+#define pktt_error( str, args...)
+
+ #define pktt_info( str, args...) \
+ printk( KERN_INFO "%s: " str "\n", __FUNCTION__, ## args)
+#endif
+#define pktt_error( str, args...) \
+ printk( KERN_ERR "%s: " str "\n", __FUNCTION__, ## args)
+
+#endif
+#include <linux/types.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+#define PKTT_FUNCTION_MAXNAMELEN 30
+#define PKTT_TABLE_MAXNAMELEN 32
+#define PKTT_CHAIN_MAXNAMELEN PKTT_TABLE_MAXNAMELEN
+
+/* verdict for users */
+#define PKTT_CONTINUE NF_MAX_VERDICT+3
+#define PKTT_RETURN NF_MAX_VERDICT+4
+/**
+ * enum policy - define chain policies
+ */
+enum pktt_chain_policy {cDROP=NF_DROP ,cACCEPT=NF_ACCEPT ,cRETURN=PKTT_RETURN ,
+ cQUEUE=NF_QUEUE};
+
+struct pktt_counters
+{
+ u_int64_t pcnt, bcnt; /* Packet and byte counters */
+};
+
+/**
+ * name of the linear classifier
+ */
+#define PKTT_LC_NAME "linear"
+
+#ifdef __KERNEL__
+struct pktt_entry
+{
+ struct list_head list;
+
+ /**
+ * helper pointer for classifiers
+ */
+ void *helper_data;
+
+ /**
+ * for easy indexing in the link list
+ */
+ u_int32_t rank;
+
+ /**
+ * this is a helper pointer, by this we can transfrom
+ * the user data from "pktt_user_entry" to "pktt_entry".
+ */
+ unsigned char pktt_user_entry[0];
+
+ /**
+ * the protocol family
+ */
+ u_int16_t family;
+
+ union{
+ struct ipt_ip ip4;
+ } pkt_header;
+
+ /**
+ * Mark with fields that we care about.
+ */
+ unsigned int nfcache;
+
+ /**
+ * Size of matches
+ */
+ u_int16_t target_offset;
+
+ /**
+ * size of padded memory: pktt_user_entry + matches + target
+ */
+ u_int32_t size;
+
+ /*
+ * Packet and byte counters. per CPU
+ */
+ struct pktt_counters counters[NR_CPUS];
+
+ /**
+ * The matches (if any), then target.
+ */
+ unsigned char elems[0];
+};
+#endif /* __KERNEL__ */
+
+/**
+ * this is a small image from "pktt_entry" that the users
+ * use this to transform entry information to the kernel.
+ */
+#ifdef __KERNEL__
+struct pktt_user_entry /* used in the kernel space */
+#else
+struct pktt_entry /* used in the user space */
+#endif
+{
+ /**
+ * the protocol family
+ */
+ u_int16_t family;
+
+ union{
+ struct ipt_ip ip4;
+ } pkt_header;
+
+ unsigned int nfcache;
+
+ u_int16_t target_offset;
+
+ u_int32_t size;
+
+ struct pktt_counters counters;
+
+ unsigned char elems[0];
+};
+
+/* Helper functions */
+static __inline__ struct xt_entry_target *
+pktt_entry_get_target(const struct pktt_entry *e)
+{
+ return (void *)e->elems + e->target_offset;
+}
+
+#ifdef __KERNEL__
+struct pktt_chain;
+
+/**
+ * struct pktt_classifier - use this to define a classifier.
+ *
+ * - Note, at the same time, different chains can use from one classifier
+ * to manage their search activities.
+ *
+ * - In one chain all of this functions will be called sequentially.. thus
+ * for one chain (one use): you don't need to use any lock to manage
+ * critical sections.
+ *
+ * - But if in your algoritm, different uses( means: using in different chains )
+ * have side affects on each other, you should manage them by your
+ * appropriate locks.
+ *
+ * BEST IDEA: try to use from implementations with no side affects on
+ * each other for different and multiple uses.
+ *
+ * - this functions ( except 'init' ) is called from spin locked protected
+ * areas. thus sleeping on them ( rescheduling the system ) is equal to die..
+ *
+ * - kmalloc and kfree are the best choices for memory allocations..
+ */
+struct pktt_classifier
+{
+ struct list_head list;
+
+ const char name[PKTT_FUNCTION_MAXNAMELEN-1];
+
+ /* initialize the classifier .. this is the first one that be called.
+ * it must return a pointer to a context, other functions will use
+ * this context to communicate with the classifier.
+ * NOTE:
+ * different chains can use from one classifier at the same time.
+ */
+ void *(*init)(struct pktt_chain *chain);
+
+ /* flushing the classifier
+ * ( detaching all of the rules from the classifier )
+ */
+ void (*flush)(void *c_context);
+
+ /* attaching an entry to the classifier
+ */
+ int (*attach_rule)(void *c_context, struct pktt_entry *e);
+
+ /* detaching an entry from the classifier
+ */
+ int (*detach_rule)(void *c_context, struct pktt_entry *e);
+
+ /* destroying the classifier .. this is the last one that be called.
+ */
+ void (*destroy)(void *c_context);//, struct pktt_entry *e);
+
+ /* called when the chain recieves a packet.
+ * he will return an entry with the lowest cost(rank) between
+ * the entries that match the packet.
+ *
+ * RETURN: NULL means "there is no matched entry for this packet".
+ */
+ struct pktt_entry *(*first_match)(void *c_context,
+ const struct sk_buff *skb ,
+ const struct net_device * in_dev ,
+ const struct net_device * out_dev);
+
+ /* the next entry that match the packet.
+ * RETURN NULL means there is no more entry for this packet.
+ */
+ struct pktt_entry *(*next_match )(void *c_context ,
+ const struct pktt_entry *prev_entry,
+ const struct sk_buff *skb,
+ const struct net_device * in_dev,
+ const struct net_device * out_dev);
+ /* OWNER */
+ struct module *owner;
+
+ unsigned short family;
+};
+
+/**
+ * pktt_chain_target - allow us to use chains as target
+ */
+struct pktt_chain_target
+{
+ struct xt_entry_target target;
+ unsigned long chain;
+};
+
+/**
+ * struct pktt_chain - defines the chains in the tabels
+ * @name: a unique human readable name for this chain
+ * @table: name of the table that the chain belongs to.
+ * @my_hooks: is a hook mask. determine the hooks that the packet flow may come
+ from them.
+ * @refcnt: refrence counter .. HOWmany used in targets?
+ * @target: prepare this chance to use from the chain as a target
+ * @entries: list of rules in this chain.
+ * @num_entries: number of rules(entries) in this chain
+ * @size: size of the chain in Byte (size of rules)
+ * @classifier: chain classifier
+ * @context: classifier context
+ * @policy: chain policy
+ */
+struct pktt_chain{
+ struct list_head list;
+
+ char name[PKTT_CHAIN_MAXNAMELEN];
+
+ struct pkt_table *table;
+ unsigned int my_hooks;
+
+ atomic_t refcnt;
+ struct xt_target target;
+
+ struct list_head entries;
+ __u32 num_entries;
+ __u64 size;
+
+ struct pktt_classifier *classifier;
+ void *context;
+
+ enum pktt_chain_policy policy;
+};
+
+/**
+ * struct pkt_table - defines the tables in the classifier
+ * @name: a unique human readable name for this table
+ * @valid_hooks: What hooks you will enter on
+ * @chains: list of table chains
+ * @hook_entry: entry points for IP hooks
+ * @num_chains: number of table chains
+ * @lock: protect entries management ( user - kernel )
+ * @family: defines the protocol family that he belongs to.
+ * @owner: table owner
+ */
+struct pkt_table{
+ struct list_head list;
+
+ char name[PKTT_TABLE_MAXNAMELEN];
+
+ unsigned int valid_hooks;
+
+ struct list_head chains;
+ struct pktt_chain *hook_entry[NF_INET_NUMHOOKS];
+ __u32 num_chains;
+
+ rwlock_t lock;
+
+ unsigned short family;
+
+ struct module *owner;
+};
+
+/* struct pktt_regtable - infos for registering a table
+ * @name: a unique human readable name for the table
+ * @valid_hooks: What hooks you will enter on
+ * @hooks_policy: policy of each hook ( just valid hooks )
+ * @family: defines the protocol family that he belongs to.
+ * @owner: i am owner
+ * @table: the pointer to the table that is registered. this is filled by
+ the pktt_register_table function.
+ */
+struct pktt_regtable{
+ char name[PKTT_TABLE_MAXNAMELEN];
+
+ unsigned int valid_hooks;
+ enum pktt_chain_policy hooks_policy[NF_INET_NUMHOOKS];
+
+ unsigned short family;
+
+ struct module *owner;
+ struct pkt_table *table;
+};
+#endif /* __KERNEL__ */
+
+/**
+ * struct pktt_regchain - infos for registering a chain
+ * @name: a unique human readable name for the chain
+ * @policy: chain policy
+ */
+struct pktt_regchain{
+ char name[PKTT_CHAIN_MAXNAMELEN];
+ enum pktt_chain_policy policy;
+};
+
+/**
+ * commands for communicating with the user level to manage the classifier.
+ * they are the "iptables" cammands ; like -A -D ...
+ *
+ * all of them needs a table and a chain name: except the IPT_TABLE_GET_INFO
+ * that just needs table name.
+ * some also needs rule number. other needs entry or chain information.
+ */
+// used with set socket option
+#define PKTT_ENTRY_ADD 0x0000U /* adding an entry to a chain */
+ /* format: #/table-name/chain-name/rule-number/entry--informations--... */
+ /* NOTE:
+ * rule-number >= 1 : insert at this position
+ * rule-number >= chain->num_entries : append
+ */
+#define PKTT_ENTRY_DEL_WITH_RULE 0x0001U /* deleting an entry: use rule match */
+ /* format: #/table-name/chain-name/ entry--informations--... */
+#define PKTT_ENTRY_DEL_WITH_NUM 0x0002U /* deleting an entry: use rule number */
+ /* format: #/table-name/chain-name/rule-number */
+#define PKTT_ENTRY_REPLACE 0x0004U
+ /* format: #/table-name/chain-name/rule-number/ entry-informations-...*/
+#define PKTT_ENTRY_SET_COUNTER 0x0008U
+ /* format: #/table-name/chain-name/rule-number/counters */
+#define PKTT_CHAIN_FLUSH 0x0010U
+ /* format: #/table-name/chain-name */
+#define PKTT_CHAIN_ZERO 0x0020U
+ /* format: #/table-name/chain-name */
+#define PKTT_CHAIN_NEW 0x0040U
+ /* format: #/table-name/chain-name */
+#define PKTT_CHAIN_DELETE 0x0080U
+ /* format: #/table-name/chain-name */
+#define PKTT_CHAIN_RENAME 0x0100U
+ /* format: #/table-name/chain-name/new-chain-name */
+#define PKTT_CHAIN_SET_POLICY 0x0200U
+ /* format: #/table-name/chain-name/Policy */
+ /* NOTE:
+ * Policy is a number ( enum policy )
+ */
+#define PKTT_CHAIN_CHG_CLASSIFIER 0x0400U /*change the chain classifier*/
+ /* format: #/table-name/chain-name/new-classifier */
+
+// used with get socket option
+#define PKTT_TABLE_GET_INFO 0x0800U /* just get table info */
+ /* format: #/table-name */
+#define PKTT_TABLE_CHAINS_GET_INFO 0x1000U /*also the information of table chains*/
+ /* format: #/table-name */
+#define PKTT_CHAIN_GET_INFO 0x2000U /* get a table chain info */
+ /* format: #/table-name/chain-name */
+#define PKTT_CHAIN_GET_ENTRIES 0x4000U /* get the entries of a chain */
+ /* format: #/table-name/chain-name */
+#define PKTT_ENTRY_GET_COUNTERS 0x8000U
+ /* format: #/table-name/chain-name/rule-number */
+
+/**
+ * struct pktt_command - use from this structure to send (from user level) and recieve (in the kernel level) the commands.
+ * @command: is command number
+ * @family: network family
+ * @table_name: the table that the command must be execed on it
+ * @chain_name: the chain that the command must be execed on it
+ * @index: index of insertion ( for PKTT_ENTRY_ADD )
+ * @rule_number: rule number for deleting or replacing
+ (for PKTT_ENTRY_DEL_WITH_NUM and PKTT_ENTRY_REPLACE)
+ * @new_chain_name: new name for renaming the chain @chain_name
+ ( PKTT_CHAIN_RENAME )
+ * @policy: for setting the chain policy ( PKTT_CHAIN_SET_POLICY )
+ * @data: a pointer to the payload.
+ the payload is an entry information for the commands that need
+ entry informations. the payload is an instance of the
+ "pktt_entry" structure.
+ */
+#define pktt_command_t u_int16_t
+struct pktt_command{
+ pktt_command_t command;
+
+ __u16 family;
+
+ char table_name[PKTT_TABLE_MAXNAMELEN];
+ char chain_name[PKTT_CHAIN_MAXNAMELEN];
+
+ union{
+ struct{
+ __u32 rule_number;
+ struct pktt_counters counter;
+ } ent;
+
+ char new_chain_name[PKTT_CHAIN_MAXNAMELEN];
+ char new_classifier[PKTT_FUNCTION_MAXNAMELEN-1];
+
+ __u8 policy;
+ } ext;
+
+ unsigned char data[0];
+};
+
+/**
+ * the two structures that is mentioned below are for communicating
+ * with the user level:
+ *
+ * the answer of the PKTT_TABLE_GET_INFO command is an instance of the
+ * pkt_table_info structure.. by this the user can see how many chains
+ * the table has and can allocate sufficient memory to call the
+ * PKTT_GET_TABLE_CHAINS_INFO command.
+ *
+ * answer of the PKTT_TABLE_CHAIN_GET_INFO command is an instance of the
+ * pkt_table_info structure with "num_chains" instance of the
+ * pktt_chain_info structure as its payload. by this command the user
+ * can learn about the chains and allocate sufficient memory to call
+ * the PKTT_CHAIN_GET_ENTRIES command.
+ *
+ * if user know the name of a chain, he can use from the PKTT_CHAIN_GET_INFO.
+ * its answer is an instance of the pktt_chain_info structure. he can use
+ * from this to allocate sufficient memory to call the
+ * PKTT_CHAIN_GET_ENTRIES command.
+ *
+ * for getting a chain entries the user must call the PKTT_CHAIN_GET_ENTRIES
+ * command. its answer is an instance of the pktt_chain_info structure
+ * with its entries as his payload.
+ *
+ */
+struct pkt_table_info{
+ char name[PKTT_TABLE_MAXNAMELEN];
+ u_int32_t num_chains;
+ unsigned int valid_hooks;
+
+ unsigned char chains_info[0];
+};
+
+struct pktt_chain_info{
+ char name[PKTT_CHAIN_MAXNAMELEN];
+
+ u_int64_t size;
+ u_int32_t num_entries;
+ u_int16_t refcnt;
+
+ char classifier_name[PKTT_FUNCTION_MAXNAMELEN-1];
+
+ u_int8_t policy;
+
+ unsigned char entries[0];
+};
+
+/**
+ * PKTT_ENTRY_MATCH_ITERATE - iterate on the matches of an entry
+ * @e: pointer to the begining of the entry
+ * @fn: function that must be called for each match
+ *
+ * NOTE: @fn should returns 0 to iteration be continued
+ */
+#define PKTT_ENTRY_MATCH_ITERATE(e, fn, args...) \
+({ \
+ unsigned int __i; \
+ int __ret = 0; \
+ struct xt_entry_match *__match; \
+ \
+ for (__i = 0; \
+ __i < ((e)->target_offset); \
+ __i += __match->u.match_size) { \
+ __match = (void *)(e)->elems + __i; \
+ \
+ __ret = fn(__match , ## args); \
+ if (__ret != 0) \
+ break; \
+ } \
+ __ret; \
+})
+
+/**
+ * PKTT_ENTRY_ITERATE - iterate on the entries of a chain
+ * @entries: address of the head of chain entries
+ * @fn: function that must be called for each entry
+ *
+ * NOTE: @fn should returns 0 to iteration be continued
+ */
+#define PKTT_ENTRY_ITERATE(entries, fn, args...) \
+({ \
+ int __ret = 0; \
+ struct pktt_entry *__i=(void *)(entries)->next; \
+ \
+ while ((void *)__i!=(void *)(entries)){ \
+ __ret = fn(__i , ## args); \
+ if (__ret != 0) \
+ break; \
+ \
+ __i = (void *)__i->list.next; \
+ } \
+ __ret; \
+})
+
+#ifdef __KERNEL__
+
+//extern struct pktt_classifier *pktt_find_classifier(int af, const char *name);
+
+extern int pktt_register_table(struct net *net, struct pktt_regtable *regtable);
+extern void pktt_unregister_table(struct pktt_regtable *regtable);
+
+extern int pktt_register_classifier(struct pktt_classifier *classifier);
+extern void pktt_unregister_classifier(struct pktt_classifier *classifier);
+
+extern unsigned int pktt_table_trigger(struct sk_buff *pskb,
+ unsigned int hook,
+ const struct net_device *in,
+ const struct net_device *out,
+ struct pktt_regtable *regtable);
+
+extern int pktt_proto_init(struct net *net, unsigned short family);
+extern void pktt_proto_exit(struct net *net, unsigned short family);
+#endif /* __KERNEL__ */
+
+#endif /* _PKT_TABLES_H */
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists