|
The Cobra Project
Component based Routing Architecture for Linux 2.4+ |
|
I've released COBRA 1.01. It fixes some small bugs and typos. I've also released PBRD 0.98, a control protocol for COBRA. It allows to do flow based routing along paths and also allows to remotly bind flows to cobra plugins.
I did the last changes. I've added my semester thesis.
So, finally I found the time to test out the new instance hash table code. It works fine. I've added status information about loaded instances. You can see a sample output here (I've loaded 5 instances):
xcore:/ # cat /proc/net/rp_status Registered Router Plugins: 2 Registered Router Plugins Instances: 5 Plugin TEST Module RP_TEST Instances 1,2,3 Plugin LOG Module RP_LOG Instances 4,5 xcore:/ #
I've added reconfiguration over /proc/net/rp_status. I think everything works now. I've made a sample walktrough... In it I will create 3 instances of the TEST router plugin, 1 instance of the LOG plugin (each of them configured in an other way). After this setup, I will add a secondary filter to one of the TEST instances so that this instance will be called for two different streams. After having done this, I will reconfigure the LOG plugin instance. Afterwards I will remove each of the filters for those instances and then when no filter is setup anymore I will unload all modules.
Let's do it:
xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.2 -j RP --plugin TEST --autoinstance --config 'initial config string for first instance' libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: parse() trying to load module ipt_RP libipt_RP: autoinstance, requesting unique instance from kernel. libipt_RP: got unique instance 1 from kernel. Router plugin instance is 1 libipt_RP: load_module() trying to load module rp_TEST xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.3 -j RP --plugin TEST --autoinstance --config 'initial config string for second instance' libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: parse() trying to load module ipt_RP libipt_RP: autoinstance, requesting unique instance from kernel. libipt_RP: got unique instance 2 from kernel. Router plugin instance is 2 libipt_RP: load_module() trying to load module rp_TEST xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.4 -j RP --plugin TEST --autoinstance --config 'initial config string for third instance' libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: parse() trying to load module ipt_RP libipt_RP: autoinstance, requesting unique instance from kernel. libipt_RP: got unique instance 3 from kernel. Router plugin instance is 3 libipt_RP: load_module() trying to load module rp_TEST xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.5 -j RP --plugin LOG --autoinstance --config 'initial config string for first instance' libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: parse() trying to load module ipt_RP libipt_RP: autoinstance, requesting unique instance from kernel. libipt_RP: got unique instance 4 from kernel. Router plugin instance is 4 libipt_RP: load_module() trying to load module rp_LOG xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.6 -j RP --plugin TEST --instance 1 libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: load_module() trying to load module rp_TEST xcore:/ # iptables -t rp -L Chain PREROUTING (policy ACCEPT) target prot opt source destination RP all -- 172.16.7.2 anywhere RP TEST#1 RP all -- trash.guindehi.ch anywhere RP TEST#2 RP all -- 172.16.7.4 anywhere RP TEST#3 RP all -- 172.16.7.5 anywhere RP LOG#4 RP all -- 172.16.7.6 anywhere RP TEST#1 Chain POSTROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination xcore:/ # cat /proc/net/rp_status Registered Router Plugins: 2 Registered Router Plugins Instances: 4 Plugin TEST Module RP_TEST Instances 1,2,3 Plugin LOG Module RP_LOG Instances 4 xcore:/ # cat > /proc/net/rp_status LOG#4 new configuration for instance 4 xcore:/ # iptables -t rp -D PREROUTING 1 xcore:/ # iptables -t rp -D PREROUTING 1 xcore:/ # iptables -t rp -D PREROUTING 1 xcore:/ # iptables -t rp -D PREROUTING 1 xcore:/ # iptables -t rp -D PREROUTING 1 xcore:/ # rmmod rp_TEST rp_LOG iptable_rp ipt_RP ip_tables xcore:/ #
Here you see the debug output. You can see the loading and uloading of the router plugins and you also see that all configuration requests have been executed...
May 18 18:08:54 xcore kernel: ip_tables: (c)2000 Netfilter core team May 18 18:08:54 xcore kernel: RPT: init() called... May 18 18:08:54 xcore kernel: RPT: init() - create_proc_entry('/proc/net/rp_instance') succeeded... May 18 18:08:54 xcore kernel: RPT: init() - create_proc_entry('/proc/net/rp_status') succeeded... May 18 18:08:54 xcore kernel: RPT: init() succeded... May 18 18:08:54 xcore kernel: RPT: pf_instance_read - returning instance 1 May 18 18:08:54 xcore kernel: RP: rp_init(TEST) called... May 18 18:08:54 xcore kernel: RP_TEST: load() called... May 18 18:08:54 xcore kernel: RP_TEST: load() succeded... May 18 18:08:54 xcore kernel: RPT: rp_register(TEST) called... May 18 18:08:54 xcore kernel: RP: rp_init(TEST) succeded... May 18 18:08:54 xcore kernel: RP_TABLE: init() called... May 18 18:08:54 xcore kernel: RP_TABLE: registering table rp... May 18 18:08:54 xcore kernel: RP_TABLE: registering ipt_ops[0]... May 18 18:08:54 xcore kernel: RP_TABLE: registering ipt_ops[1]... May 18 18:08:54 xcore kernel: RP_TABLE: registering ipt_ops[2]... May 18 18:08:54 xcore kernel: RP_TABLE: registering ipt_ops[3]... May 18 18:08:54 xcore kernel: RP_TABLE: registering ipt_ops[4]... May 18 18:08:54 xcore kernel: RP_TABLE: init() succeded May 18 18:08:54 xcore kernel: RPT: configuring plugin TEST instance 1. May 18 18:08:54 xcore kernel: RPT: config() dispatching to plugin TEST#1 May 18 18:08:54 xcore kernel: RP_TEST: config() called for plugin TEST#1 with config 'initial config string for first instance' May 18 18:08:54 xcore kernel: RPT: checkentry(TEST): adding plugin instance 1 May 18 18:09:04 xcore kernel: RPT: pf_instance_read - returning instance 2 May 18 18:09:04 xcore kernel: RPT: configuring plugin TEST instance 2. May 18 18:09:04 xcore kernel: RPT: config() dispatching to plugin TEST#2 May 18 18:09:04 xcore kernel: RP_TEST: config() called for plugin TEST#2 with config 'initial config string for second instance' May 18 18:09:04 xcore kernel: RPT: checkentry(TEST): adding plugin instance 2 May 18 18:09:16 xcore kernel: RPT: pf_instance_read - returning instance 3 May 18 18:09:16 xcore kernel: RPT: configuring plugin TEST instance 3. May 18 18:09:16 xcore kernel: RPT: config() dispatching to plugin TEST#3 May 18 18:09:16 xcore kernel: RP_TEST: config() called for plugin TEST#3 with config 'initial config string for third instance' May 18 18:09:16 xcore kernel: RPT: checkentry(TEST): adding plugin instance 3 May 18 18:09:32 xcore kernel: RPT: pf_instance_read - returning instance 4 May 18 18:09:32 xcore kernel: RP: rp_init(LOG) called... May 18 18:09:32 xcore kernel: RP_LOG: load() called... May 18 18:09:32 xcore kernel: RP_LOG: load() succeded... May 18 18:09:32 xcore kernel: RPT: rp_register(LOG) called... May 18 18:09:32 xcore kernel: RP: rp_init(LOG) succeded... May 18 18:09:32 xcore kernel: RPT: configuring plugin LOG instance 4. May 18 18:09:32 xcore kernel: RPT: config() dispatching to plugin LOG#4 May 18 18:09:32 xcore kernel: RP_LOG: config() called for plugin LOG#4 with config 'initial config string for first instance' May 18 18:09:32 xcore kernel: RPT: checkentry(LOG): adding plugin instance 4 May 18 18:10:23 xcore kernel: RPT: hashprint(TEST) May 18 18:10:23 xcore kernel: RPT: hashprint(TEST) - Instance 1 May 18 18:10:23 xcore kernel: RPT: hashprint(TEST) - Instance 2 May 18 18:10:23 xcore kernel: RPT: hashprint(TEST) - Instance 3 May 18 18:10:23 xcore kernel: RPT: hashprint(LOG) May 18 18:10:23 xcore kernel: RPT: hashprint(LOG) - Instance 4 May 18 18:10:23 xcore kernel: RPT: pf_status_read - returning 156 bytes May 18 18:10:50 xcore kernel: RPT: pf_status_write - accepting 39 bytes May 18 18:10:50 xcore kernel: RPT: reconfiguring plugin LOG instance 4. May 18 18:10:50 xcore kernel: RP_LOG: reconfig() called for plugin LOG#4 with config 'new configuration for instance 4' May 18 18:11:53 xcore kernel: RP_TEST: rp_exit(TEST) called... May 18 18:11:53 xcore kernel: RPT: rp_unregister(TEST) called... May 18 18:11:53 xcore kernel: RPT: rp_unregister(TEST): removing instance 1 May 18 18:11:53 xcore kernel: RPT: rp_unregister(TEST): removing instance 2 May 18 18:11:53 xcore kernel: RPT: rp_unregister(TEST): removing instance 3 May 18 18:11:53 xcore kernel: RPT: rp_unregister(LOG): removing instance 4 May 18 18:11:53 xcore kernel: RP_TEST: unload() called... May 18 18:11:53 xcore kernel: RP_TEST: unload() succeded... May 18 18:11:53 xcore kernel: RP_TEST: rp_exit(TEST) succeded... May 18 18:11:53 xcore kernel: RP_TEST: rp_exit(LOG) called... May 18 18:11:53 xcore kernel: RPT: rp_unregister(LOG) called... May 18 18:11:53 xcore kernel: RP_LOG: unload() called... May 18 18:11:53 xcore kernel: RP_LOG: unload() succeded... May 18 18:11:53 xcore kernel: RP_TEST: rp_exit(LOG) succeded... May 18 18:11:53 xcore kernel: RP_TABLE: fini() called... May 18 18:11:53 xcore kernel: RP_TABLE: unregistering ipt_ops[0].. May 18 18:11:53 xcore kernel: RP_TABLE: unregistering ipt_ops[1].. May 18 18:11:53 xcore kernel: RP_TABLE: unregistering ipt_ops[2].. May 18 18:11:53 xcore kernel: RP_TABLE: unregistering ipt_ops[3].. May 18 18:11:53 xcore kernel: RP_TABLE: unregistering ipt_ops[4].. May 18 18:11:53 xcore kernel: RP_TABLE: unregistering rp table... May 18 18:11:53 xcore kernel: RP_TABLE: fini() succeded May 18 18:11:53 xcore kernel: RPT: fini() called... May 18 18:11:53 xcore kernel: RPT: fini() succeded...
Success on the whole line! Questions? Comments? Ralph? Lukas?
I think that's it!
Now it's time for some documentation!
I added an instance hash table. The code is written and compiles but is yet untested.
So, I found time to work further on the project. I've implemented a second /proc file named /proc/net/rp_status over which one can get status informations over which router plugins are loaded. The runtime configuration of router plugins will by done by writing information to that file. I've included a sample session:
xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.2 -j RP --plugin LOG --instance 0 libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: load_module() trying to load module rp_LOG xcore:/ # lsmod Module Size Used by iptable_rp 3376 0 (autoclean) (unused) rp_LOG 3736 0 (unused) ipt_RP 4504 1 [rp_LOG] ip_tables 14488 2 [iptable_rp ipt_RP] ipv6 156928 -1 (autoclean) ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci] xcore:/ # la /proc/net/rp* -rw-rw-rw- 1 root root 0 May 6 18:57 /proc/net/rp_instance -rw-rw-rw- 1 root root 0 May 6 18:57 /proc/net/rp_status xcore:/ # cat /proc/net/rp_status Registred Router Plugins: 1 Plugin LOG Module RP_LOG xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.2 -j RP --plugin TEST --instance 0 libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: load_module() trying to load module rp_TEST xcore:/ # cat /proc/net/rp_status Registred Router Plugins: 2 Plugin TEST Module RP_TEST Plugin LOG Module RP_LOG xcore:/ #Now the only thing to solve is the instance configuration of single router plugins at load time and on runtime.
Yes, I've finally come round to implementing /proc support in ipt_RP. At the moment one file /proc/net/rp_instance will be created which will output one of the next free instance numbers. These numbers will be unique. It's a central way to receive unique instance numbers for loading plugins. iptables will use these instance numbers to allocate unique instance numbers to loaded plugin instances [nice said, right? ;-))]
Doing this in the command line:
xcore:/ # modprobe ip_tables xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.1 -j RP --plugin LOG --instance 0 libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: load_module() trying to load module rp_LOG xcore:/ # xcore:/ # la /proc/net/rp_instance -r--r--r-- 1 root root 0 Apr 25 16:29 /proc/net/rp_instance xcore:/ # cat /proc/net/rp_instance 1 xcore:/ # cat /proc/net/rp_instance 2 xcore:/ # cat /proc/net/rp_instance 3 xcore:/ # cat /proc/net/rp_instance 4 xcore:/ # cat /proc/net/rp_instance 5 xcore:/ # cat /proc/net/rp_instance 6
The debug log output will look like this:
Apr 25 16:29:20 xcore kernel: RPT: init() called... Apr 25 16:29:20 xcore kernel: RPT: init() succeded... Apr 25 16:29:20 xcore kernel: RP: rp_init(LOG) called... Apr 25 16:29:20 xcore kernel: RP_LOG: load() called... Apr 25 16:29:20 xcore kernel: RP_LOG: load() succeded... Apr 25 16:29:20 xcore kernel: RPT: rp_register(LOG) called... hashing... Apr 25 16:29:20 xcore kernel: RPT: hashfn(LOG) = 34 Apr 25 16:29:20 xcore kernel: RP: rp_init(LOG) succeded... Apr 25 16:29:20 xcore kernel: RP_TABLE: init() called... Apr 25 16:29:20 xcore kernel: RP_TABLE: registering table rp... Apr 25 16:29:20 xcore kernel: RP_TABLE: registering ipt_ops[0]... Apr 25 16:29:20 xcore kernel: RP_TABLE: registering ipt_ops[1]... Apr 25 16:29:20 xcore kernel: RP_TABLE: registering ipt_ops[2]... Apr 25 16:29:20 xcore kernel: RP_TABLE: registering ipt_ops[3]... Apr 25 16:29:20 xcore kernel: RP_TABLE: registering ipt_ops[4]... Apr 25 16:29:20 xcore kernel: RP_TABLE: init() succeded Apr 25 16:30:10 xcore kernel: RPT: proc read - returning instance 1 Apr 25 16:30:13 xcore kernel: RPT: proc read - returning instance 2 Apr 25 16:30:14 xcore kernel: RPT: proc read - returning instance 3 Apr 25 16:30:15 xcore kernel: RPT: proc read - returning instance 4 Apr 25 16:30:15 xcore kernel: RPT: proc read - returning instance 5 Apr 25 16:30:15 xcore kernel: RPT: proc read - returning instance 6
Implemented rp_LOG, a small router plugin which dumps matched packets via printk. This plugin exists only to demonstrate what packets are received by the plgin framework.
After configuring the plugin like this:
xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.1 -j RP --plugin LOG --instance 0You get the following output:
Apr 10 20:03:32 xcore kernel: RPT: target() dispatching to plugin LOG#0 Apr 10 20:03:32 xcore kernel: RP_LOG: target() called for plugin LOG#0 for hock 0 Apr 10 20:03:32 xcore kernel: RP_LOG: IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:00:50:04:78:9c:e9:08:00 SRC=172.16.7.1 DST=172.16.7.255 LEN=252 TOS=0x00 PREC=0xC0 TTL=1 ID=39933 PROTO=UDP SPT=520 DPT=520 LEN=232 [...]Nice, isn't it? I know what you wanna say! It's exactly the same dump routine as in ipt_LOG... ;-)
Had a short meeting with Ralph and Lukas. We discussed part two of the Cobra project which consists of implementing the active router plugin part. They will write down a target description for me...
Added a score table for bug solvers! Tremblin pushed me to do that since he found three bugs for me, two prototype errors and my braindead ghash hashcmp() bug...
Yeah! What a weekend! Didn't work... No further comments ;-)
The router plugin framework works! Look at the following run:
xcore:/ # modprobe ip_tables xcore:/ # lsmod Module Size Used by ip_tables 14488 0 (unused) ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci] xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.1 -j RP --plugin TEST --instance 0 libipt_RP: init() called... libipt_RP: init() succeded... libipt_RP: load_module() trying to load rp_TEST libipt_RP: load_module() executing '/sbin/modprobe rp_TEST' xcore:/ # lsmod Module Size Used by rp_TEST 1236 0 (unused) ipt_RP 2824 1 [rp_TEST] iptable_rp 3376 0 (autoclean) (unused) ip_tables 14488 2 [iptable_rp ipt_RP] ipv6 156928 -1 (autoclean) ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci] xcore:/ # iptables -t rp -L Chain PREROUTING (policy ACCEPT) target prot opt source destination RP all -- agamemnon-eth1.guindehi.ch anywhere RP TEST#0 Chain POSTROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
This generates the following debug output:
Apr 3 23:34:33 xcore kernel: ip_tables: (c)2000 Netfilter core team Apr 3 23:34:53 xcore kernel: RPT: init() called... Apr 3 23:34:53 xcore kernel: RPT: init() succeded... Apr 3 23:34:53 xcore kernel: RP: rp_init(TEST) called... Apr 3 23:34:53 xcore kernel: RP_TEST: load() called... Apr 3 23:34:53 xcore kernel: RP_TEST: load() succeded... Apr 3 23:34:53 xcore kernel: RPT: rp_register(TEST) called... hashing... Apr 3 23:34:53 xcore kernel: RPT: hashfn(TEST) = 0 Apr 3 23:34:53 xcore kernel: RP: rp_init(TEST) succeded... Apr 3 23:34:53 xcore kernel: RP_TABLE: init() called... Apr 3 23:34:53 xcore kernel: RP_TABLE: registering table rp... Apr 3 23:34:53 xcore kernel: RP_TABLE: registering ipt_ops[0]... Apr 3 23:34:53 xcore kernel: RP_TABLE: registering ipt_ops[1]... Apr 3 23:34:53 xcore kernel: RP_TABLE: registering ipt_ops[2]... Apr 3 23:34:53 xcore kernel: RP_TABLE: registering ipt_ops[3]... Apr 3 23:34:53 xcore kernel: RP_TABLE: registering ipt_ops[4]... Apr 3 23:34:53 xcore kernel: RP_TABLE: init() succeded Apr 3 23:35:41 xcore kernel: RPT: target() called for plugin TEST#0 Apr 3 23:35:41 xcore kernel: RPT: hashfn(TEST) = 0 Apr 3 23:35:41 xcore kernel: RPT: hashcmp(TEST,TEST) = 0 Apr 3 23:35:41 xcore kernel: RPT: hasheq(TEST,TEST) = 1 Apr 3 23:35:41 xcore kernel: RPT: target() dispatching to plugin TEST#0 Apr 3 23:35:41 xcore kernel: RP_TEST: target() called for plugin TEST#0 for hock 0 [...]
As you can see the netfilter target RPT is called and dispatches the arriving packets to the router plugin framework and it's test plugin rp_TEST which has been successfully and automatically loaded on creation of a new RP target rule in the iptable 'rp'.
So next I will have to clean up the code, write some documentation implement the /proc configuration and add a --init flag to iptables, that should be all... Hopefully Ralph does not get new ideas... ;-)
I've checked in the new working code...
Hmm... shuffled the code around. Looks nicer now. ipt_RP.h only defines those things that are needed and excludes the ghash.h code if _IPT_RP_ghash is not defined.
Got ipt_RP.c to compile with ghash.h. rp_register() and rp_unregister() use it. But there is a problem. I can put something in the hash, but when I try to find it again it fails... will have to search the bug.
I coded the rp_init() and rp_exit() defines, moved the code to rp.h changed ipt_RP.c to include a rp_register() function and included the register callup to ipt_RP in rp_init(). I had a hell of a day tracing all those f***ing "function declaration isn't a prototype" errors. Used gcc -E option a lot to trace preprocessor problems. Tremblin came by this night. Together we fixed the last of those fancy bugs. Hey, thanks Tremblin! Did you know that func() is not the same than func(void)?! I did not...
Anyway! Registering of loading modules works! Look at this debug output:
Mar 27 22:10:06 xcore kernel: ip_tables: (c)2000 Netfilter core team Mar 27 22:10:06 xcore kernel: RPT: init() called... Mar 27 22:10:06 xcore kernel: RPT: init() succeded... Mar 27 22:10:06 xcore kernel: RP: rp_init(TEST) called... Mar 27 22:10:06 xcore kernel: RP_TEST: load() called... Mar 27 22:10:06 xcore kernel: RP_TEST: load() succeded... Mar 27 22:10:06 xcore kernel: RPT: rp_register() called.. Mar 27 22:10:06 xcore kernel: RP: rp_init(TEST) succeded... Mar 27 22:10:37 xcore kernel: RP_TABLE: init() called...
rp_register() already receives the callback function pointer for the ipt_RP target! Hey, even depmod works perfectly with my new modules and sees all dependencies! Look at this:
xcore:/ # modprobe rp_TEST xcore:/ # lsmod Module Size Used by rp_TEST 1220 0 (unused) ipt_RP 1296 0 [rp_TEST] ip_tables 14488 1 [ipt_RP] ipv6 156928 -1 (autoclean) ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci]So this says rp_TEST needs ipt_RP with needs ip_tables. The module iptable_rp is not yet loaded and will get loaded as soon as you use the -t rp flag with iptables... Perfect!
Didn't code much. Discussed the RP configuration problem with Ralph. RP's will be configured by /proc. I will add an --init option for initialization parameters to iptables. Need to find out if there is already a hash structure available in the kernel. I need this to dispatch (in ipt_RP.c, the target) to the right router plugin instance. Tried to code two defines named rp_init() and rp_exit(). They should work like module_init() and module_exit(). But the defines do not work. I get tons of errors... We will see tomorrow.
Tonight I have a date with a good old friend of mine. I didn't see her for
a long time! We will go out for dinner...
I'm still a little groggy from last night... I've made a small announcement of Cobra on the netfilter-devl mailing list. I think it was a bit early in the development to make such an anouncement, but Ralph pushed me to do it. I hope nobody kicks my butt because of the stolen webserver layout ;-)
Did nothing today. Had to relax because I will go out this night again. This time it's time for a good house party... This will be fun!
Still busy coding libipt_RP.c.
Yeah! The shared library works and proves that the second module ipt_RP works
nicely! This works out just perfectly!
Look at this:
xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.1 -j RP --plugin TEST --instance 0 xcore:/ # iptables -t rp -A PREROUTING -s 172.16.7.2 -j RP --plugin TEST --instance 1 xcore:/ # iptables -t rp -A PREROUTING -p TCP --sport 25 -j RP --plugin DEMO --instance 0 xcore:/ # iptables -t rp -A PREROUTING -p TCP --sport 25 -j RP --plugin DEMO --instance 1 xcore:/ # iptables -t rp -L Chain PREROUTING (policy ACCEPT) target prot opt source destination RP all -- 172.16.7.1 anywhere RP TEST#0 RP all -- 172.16.7.2 anywhere RP TEST#1 RP tcp -- anywhere anywhere tcp spt:25 RP DEMO#0 RP tcp -- anywhere anywhere tcp spt:25 RP DEMO#1 Chain POSTROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination xcore:/ # lsmod Module Size Used by ipt_RP 1212 4 (autoclean) ipv6 156928 -1 (autoclean) iptable_rp 3024 0 (autoclean) (unused) ip_tables 14488 2 [ipt_RP iptable_rp] ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci]
Really, I like this framework! Hey Rusty, this is way cool! Ralph, what do you think? Looks great, doesn't it? I will have to check, if the RP dispatcher really sees and gets those packets matching the filters, but I think it will, because, I've already seen the ipt_hook() called a lot (see further down), and this function does the upcall to ip_do_table(). It simple has to work! I will check this, but before I will have to take a nap of sleep.
I'm really happy with my progress! It seems that we will meet our targets! So, let's go to bed now...
... and back infront of the keyboard! It seems that my RP target receives maching packets:
Mar 23 13:21:34 xcore kernel: RPT: target() called: plugin 'TEST', instance 0 Mar 23 13:24:06 xcore last message repeated 23 times Mar 23 13:25:03 xcore last message repeated 15 times
So, now I have to build the RP plugin displatcher and figure out how to build a loadable module which ipt_RP can load on need.
I began writing a test router plugin named rp_TEST.c. It will do nothing except getting loaded by the ipt_RP router plugin dispatcher and it will be called with the matching packets. I will have to figure a way to configure RP instances. Don't know how at the moment. I've added a new config option in the kernel and made CONFIG_IP_NF_RP_DEBUG configurable since those messages will make a real performance impact. I've updated Documentation/Configure.help. After the new rp_TEST module loads I will try to figure out how to get it loaded when the user adds a new rule with this plugin as target. Eventually I can go the easy way and get iptables to load the module from userspace when it sees the new plugin name. This would be cool, because it's easy in userspace to check for an existing module and such... we will see!
Yeah! The first router plugin can be loaded by hand:
xcore:/ # modprobe rp_TEST xcore:/ # lsmod Module Size Used by rp_TEST 708 0 (unused) ipt_RP 1212 1 (autoclean) iptable_rp 3024 0 (autoclean) (unused) ip_tables 14488 2 [ipt_RP iptable_rp] ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci]
This router plugin module still does nothing and is empty, but it's the first step. Now I have to get iptables to automatically load it on rule addition. First I wanted to do this in the final_check method, but there I do not get my target_info pointer. I will have to store the information in static variables. I will think a bit about this one. I do not like this solution...
... It's time for weekend! I will go to the gym now, and afterwards I will do some dancing with some friends of mine! Off we go...
Success on the whole line! Look at this small shell protocol:
xcore:~ # modprobe ip_tables xcore:~ # lsmod Module Size Used by ip_tables 17784 0 (unused) ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci] xcore:~ # iptables -t rp -L Chain PREROUTING (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination xcore:~ # lsmod Module Size Used by iptable_rp 3056 0 (autoclean) (unused) ip_tables 17784 1 [iptable_rp] ne2k-pci 5436 1 (autoclean) 8390 7184 0 (autoclean) [ne2k-pci]
My new `rp' table works as expected! Let's see what happens if I enter a filter ;-))
I've added an Email Page to the Cobra main page where I will publish interesting emails concerning Cobra. Doing this I decided that it would be nicer if all web pages would have a standard design and converted them all to template based pages...
I made the time tracking page private. Only folks coming from the domain guindehi.ch
may read it. Others will get a fancy access denied web page. I hope you will
not go crazy about this, but nobody except me need to know how much time it
has cost me to build the thingy! I need to finish this fast, and I can't have
someone telling me I have to implement this and that because I was too fast...
... Sorry guys!
Yeah, it seems that my hooks work, look at this:
Mar 22 13:34:43 xcore kernel: RP: ipt_hook() called... Mar 22 18:42:19 xcore last message repeated 224 times Mar 22 18:42:43 xcore last message repeated 66 times
This happened after some typing in a shell on the box used remotely by ssh! So each of the tcp packets really flow through my hooks up to ip_table's ipt_do_table() function...
I'm currently hacking on ipt_RP.c. Hopefully I will have a runing target named RP soon.
I've setup the cobra mailing list. Feel free to join. The cobra main web page explains how. It's hosted by DataCore GmbH and is reachable under majordomo@datacore.ch. The list itself is named cobra@datacore.ch. DataCore is a really cool ISP and Consulting company which kindly hosts our mailing list.
Yeah! ipt_RP.c compiles... I can not yet use it as a target because iptables complains that it does not find the corresponding shared library to configure it. So I will have to write that user space shared library first. It's ongoing... The library is named libipt_RP.c. I'm busy coding it. Hopefully I will finish it today ;-)) Yeah, it's after midnight! I will have to switch to the next entry in my diary now...
Ah! One thing I forgot! Today Stefan Raab lost his box fight against Regina! He got really kicked and it was fun to look how Regina played with his nose! Hope you all saw it ;-))
I just gave Ralph a call and discussed on which hooks we want to be able to call RP modules. He told me that this has to be configurable, and that it should be possible to add RPs on every hook. So I have to go back to the roots and add all hooks to iptable_rp.c. *grumble* I just kicked them out of the source yesterday...
I added the right lines to net/ipv4/netfilter/Config.in, added documentation
to Documentation/Configure.html and patched the Makefile so that iptable_rp.c
will get compiled. I've fixed the compilation errors in iptable.c and the module
builds now. The built kernel still boots, but as soon as I try to load the iptable_rp
module I get a "Init_module: Invalid argument" error. I do not yet
see why. I've added a lot of kprintf()'s I can't find out where they should
appear or else they do not appear... Arghh... it's the 9th kernel I've built!
Enough for now!
After I've come home for the gym I had to fix that f***ing module! I've some searching and rereading code I've found the bugs! There where some array sizes wrong so that ipt_register_table() complained with invalid argument.
The iptable_rp module loads and unloads now. It also seems to register the table as well as the five hooks. On an unload (rmmod) it correctly unregisters the table as well as the hooks. I'm happy for today. Ralph, am I fast enough? ;-))
It looks really pretty:
Module Size Used by iptable_rp 2928 0 (unused) ip_tables 14488 1 [iptable_rp]Tomorrow I will have to compile the user space iptable binary so that I can play around with the new table! Now it's time to go to bed!
I just found out that the CVS documentation (the PDF file) on the main page was a broken. I loaded it into Adobe Acrobat Distiller, which detected the error and fixed it. Now it's readable again.
I hat a meeting with Ralph and Lukas. We discussed the second project I will eventually do with them. Its target would be to extend the plugin loader in a way so that we can load plugins over the network. It's open if encryption and authentication would be also part of it. We will see... It seems that Ralph and Lukas are speculating the my work will be usable for them ;-)) The probably wont be happy when I fail with it, because they would have to find another madman who would do the work for them ;-)
I did some source reading in linux-2.4.2/net/ipv4/netfilter. After some thinking I adapted a iptable_rp.c. We will see if this works. It should implement a new table named 'rp' on the NF_IP_POST_ROUTING hook. For now I think it's enough to hook in there. We should see all the system packets which will leave the system. Source NAT also plugs in there. It looks simple to plug into some more hooks if there is need for it.
I added LXR a source and identifier browser. After 1.5 hour of `find . -type f -exec grep SOME_IDENTIFIER {} \;` I had enough and remembered Ralph saying that LXR is cool. I took a look at it, found it cool too and installed it. It's now on the main page available. It indexes the CVS Linux source. I've even added a Makefile target to update the index, so it will be also possible to browser our own kernel source extensions...
It's now 0120, I'm drunk (since a was to lazy to do some cooking I went for a mexican bar to eat something and drink come Caipirinias with my friend Ueli) and I have to get some sleep... Tomorrow I will try to compile iptable.rp.c. This will get funny!
Today I began the kernel compile session two. After a long time I found out that the kernel works if I disable sound and usb. Since I anyway do not use those features I've disabled them. Sometime in the future I will have to include usb... The beauty works fine now on my router. IPv6 and Netfilter for IPv6 is compiled in. I gave Ralph a long phone call and discussed the new target description he sent me. It seems that we have found a way so that both of us are happy ;-))
The next problem I found was that the tlan.o module always crashes my test box. It seems that this driver does not work reliably under 2.4.2. I searched through my old cards and found a NE2000 pci card. The ne2k-pci.o module seems to work fine under 2.4.2 so I switched to that and disabled the onboard ethernet card. Finally I have a working test box running my own compiled 2.4.2. Now I will have to add the shared memory and semaphore patches my friend Tremblin made so that also Oracle will be happy with this kernel. Yeah, you probably ask yourself why that... It's because I want to have one, and only one, kernel to maintain. So even that I build a new module for netfilter I want the kernel to be exactly the same as on my other boxes...
I checked in iptables 1.2 as a vendor branch. Hopefully I will be able to update
the iptables source after my changes are made. It looks good as far as I can
tell looking at it with cvsweb... we will see when the next version appears.
The Linux source code was also checked in as a vendor branch... hopefully the
same applies here...
In short words: We are ready to do some kernel hacking...
I have setup the CVS repository and made an initial checkin. I also wrote a time tracking page and moved the webserver to its new address cobra.digital-impact.ch. I've added cvsweb.cgi to the main webpage. Doing this I found out that cvs 1.10.8 has a bug which prevents the checking of cvsweb.cgi (cvs crashes on checkin) and upgraded cvs to version 1.11. I tried a long time to setup CVSROOT/passwd for new users without an account (we need this for anonymous access), but failed. The only user for which it works is mine, it looks to me as if the user name mapping does not work for users like cvs which do not have a local account and should be mapped to my account.
I began compiling Linux 2.4.2, wrote a Makefile to automate this and found out that the configuration I have chosen crashes on my router after kernel decompression. Fiddled a long time with the kernel option but did not yet found out what causes the crashes. I checked in the source to cvs. The kernel crashes if when I take on old configuration.. ;-(
I had a meeting with Ralph, my Assistant. We discussed the targets of my work, defined a small timeline (which I still have to adapt and put on the web). We also took a look at the current netfilter documentation (which I've already put on the main webpage).
I set up the web page cobra.digital-impact.ch/cobra and made a first webserver design.
Last update: Wednesday, 26 December, 2001 23:37 |
© 2001 by Digital
Impact GmbH, Amir Guindehi
|