Fix for bug in IPFilters ipfs tool

Frank Knobbe frank at knobbe.us
Sun Mar 11 20:48:12 UTC 2007


Greetings,

A couple years ago, I had sent a patch to Darren for ipfs in ipfilter
(patched on FreeBSD 5.3). I never heard back from him, and assumed that
either it wasn't in proper format or already being worked on or he was
too busy.

Now that I'm upgrading my systems to FBSD 6.2, I encountered the same
problem, and roughly the same fix has to be applied again, so it doesn't
appear like it had been looked at. Hence I'm posting again (this time to
the list).

My setup is such that I have two router connections from my hosting
provider which I feed to two small switched which are linked with a
cross-over cable. The server has two network cards which connect to each
switch. Only one card is active at a time. I got a script running that
pings the default gateway and when it fails, it does the following:
- Bring interface A down, and B up.
- Remove the IP address from i/f A and assign to i/f B.
- Run sed over rc.conf, ipf.rules and ipnat.rules and change the
interface name from A to B.
- Save currently active ipfilter rules (using ipfstat), run sed over
those to change the i/f name, and reload them.
- And finally, save the ipfilter state table, run ipfs over it to change
the i/f names, and reload the state table.

This way the server achieves complete redundancy. Any router, switch,
cable, NIC can fail, and the server will switch to the other network
card while preserving connection states. Works like a charm.

But only after I had worked on ipfs. Out of the box, ipfs did not
properly make the interface change in the saved state files. In FBSD
6.2, the command to change the interfaces (-i) is even disabled,
probably because it never worked :)

Below is a patch that will fix ipfs such that it is able to successfully
change the interface names in the saved state files. The patch below
also enables the -i flag again. After applying this patch, one can
change interfaces as outlined above, and have ipfs rename them in the
state files, allowing a clean fail-over between interfaces within
ipfilter and also preserving the connection state. Any established
connection will remain active.

This is my first bug/fix report, so please be gentle if I cross-posted
too much. I would appreciate if someone could apply the patch to ipfs.c
so that other users can make use of it. The version of ipfs this was
diff'ed from is:

/*      $FreeBSD: src/contrib/ipfilter/tools/ipfs.c,v 1.3.2.1 2006/08/24
07:37:1
0 guido Exp $   */

---8<------------------------------------------------------------------------
--- ipfs.c.org  Sun Mar 11 14:19:32 2007
+++ ipfs.c      Sun Mar 11 14:21:24 2007
@@ -133,6 +133,14 @@
                        strcpy(ips.ips_is.is_ifname[1], s);
                        rw = 1;
                }
+                if (!strncmp(ips.ips_is.is_ifname[2], ifs, olen + 1)) {
+                        strcpy(ips.ips_is.is_ifname[2], s);
+                        rw = 1;
+                }
+                if (!strncmp(ips.ips_is.is_ifname[3], ifs, olen + 1)) {
+                        strcpy(ips.ips_is.is_ifname[3], s);
+                        rw = 1;
+                }
                if (rw == 1) {
                        if (lseek(fd, pos, SEEK_SET) != pos) {
                                perror("lseek");
@@ -190,6 +198,14 @@
                        strcpy(nat->nat_ifnames[1], s);
                        rw = 1;
                }
+                if (!strncmp(nat->nat_ifnames[2], ifs, olen + 1)) {
+                        strcpy(nat->nat_ifnames[2], s);
+                        rw = 1;
+                }
+                if (!strncmp(nat->nat_ifnames[3], ifs, olen + 1)) {
+                        strcpy(nat->nat_ifnames[3], s);
+                        rw = 1;
+                }
                if (rw == 1) {
                        if (lseek(fd, pos, SEEK_SET) != pos) {
                                perror("lseek");
@@ -216,7 +232,7 @@
        char *dirname = NULL, *filename = NULL, *ifs = NULL;
 
        progname = argv[0];
-       while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1)
+       while ((c = getopt(argc, argv, "d:f:i:lNnSRruvWw")) != -1)
                switch (c)
                {
                case 'd' :
---8<------------------------------------------------------------------------


Regards,
Frank



-- 
It is said that the Internet is a public utility. As such, it is best
compared to a sewer. A big, fat pipe with a bunch of crap sloshing
against your ports.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: This is a digitally signed message part
Url : http://lists.freebsd.org/pipermail/freebsd-bugs/attachments/20070311/4b4832f2/attachment.pgp


More information about the freebsd-bugs mailing list