:
:On Sat, Dec 14, 2002 at 12:38:13PM -0800, Matthew Dillon wrote:
:>     then, as usual, IPFW with the new kernel and
:>     old world fails utterly and now the fragging machine can't access the
:
:Hear hear!!  I am >< tempted to have /sbin/ipfw moved to src/sys.

    How about something like this (patch enclosed).  If there are no
    objections I will commit it along with a documentation update, and
    maybe also add some RC code give the sysad a chance to ipfw unbreak if
    ipfw otherwise fails during the boot sequence.

                                        -Matt
                                        Matthew Dillon 
                                        <[EMAIL PROTECTED]>


Index: sbin/ipfw/ipfw2.c
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw2.c,v
retrieving revision 1.18
diff -u -r1.18 ipfw2.c
--- sbin/ipfw/ipfw2.c   26 Nov 2002 22:53:14 -0000      1.18
+++ sbin/ipfw/ipfw2.c   14 Dec 2002 22:08:11 -0000
@@ -3307,6 +3307,30 @@
                printf("Flushed all %s.\n", do_pipe ? "pipes" : "rules");
 }
 
+static void
+unbreak()
+{
+       if (!do_force && !do_quiet) { /* need to ask user */
+               int c;
+
+               printf("Are you sure? [yn] ");
+               fflush(stdout);
+               do {
+                       c = toupper(getc(stdin));
+                       while (c != '\n' && getc(stdin) != '\n')
+                               if (feof(stdin))
+                                       return; /* and do not flush */
+               } while (c != 'Y' && c != 'N');
+               printf("\n");
+               if (c == 'N')   /* user said no */
+                       return;
+       }
+       if (setsockopt(s, IPPROTO_IP, IP_FW_UNBREAK, NULL, 0) < 0)
+               err(EX_UNAVAILABLE, "setsockopt(IP_FW_UNBREAK)");
+       if (!do_quiet)
+               printf("Flushed all rules and installed a pass-through.\n");
+}
+
 static int
 ipfw_main(int ac, char **av)
 {
@@ -3398,6 +3422,8 @@
                delete(ac, av);
        else if (!strncmp(*av, "flush", strlen(*av)))
                flush();
+       else if (!strncmp(*av, "unbreak", strlen(*av)))
+               unbreak();
        else if (!strncmp(*av, "zero", strlen(*av)))
                zero(ac, av);
        else if (!strncmp(*av, "resetlog", strlen(*av)))
Index: sys/netinet/in.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in.h,v
retrieving revision 1.73
diff -u -r1.73 in.h
--- sys/netinet/in.h    29 Oct 2002 16:46:13 -0000      1.73
+++ sys/netinet/in.h    14 Dec 2002 21:32:07 -0000
@@ -393,6 +393,7 @@
 #define        IP_FW_ZERO              53   /* clear single/all firewall counter(s) */
 #define        IP_FW_GET               54   /* get entire firewall rule chain */
 #define        IP_FW_RESETLOG          55   /* reset logging counters */
+#define        IP_FW_UNBREAK           56   /* flush and install a pass-thru rule */
 
 #define        IP_DUMMYNET_CONFIGURE   60   /* add/configure a dummynet pipe */
 #define        IP_DUMMYNET_DEL         61   /* delete a dummynet pipe from chain */
Index: sys/netinet/ip_fw2.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.19
diff -u -r1.19 ip_fw2.c
--- sys/netinet/ip_fw2.c        20 Nov 2002 19:07:27 -0000      1.19
+++ sys/netinet/ip_fw2.c        14 Dec 2002 21:41:52 -0000
@@ -2535,6 +2535,7 @@
                break;
 
        case IP_FW_FLUSH:
+       case IP_FW_UNBREAK:
                /*
                 * Normally we cannot release the lock on each iteration.
                 * We could do it here only because we start from the head all
@@ -2551,6 +2552,22 @@
                s = splimp();
                free_chain(&layer3_chain, 0 /* keep default rule */);
                splx(s);
+
+               /*
+                * If unbreaking the rulechain, which a sysad may have to do
+                * if IP_FW_ADD fails due to a userland/kernelland mismatch,
+                * install a pass-through rule.
+                */
+               if (sopt->sopt_name == IP_FW_UNBREAK) {
+                       rule = (struct ip_fw *)rule_buf; /* XXX do a malloc */
+                       bzero(rule, sizeof(*rule));
+                       rule->rulenum = 2;
+                       rule->cmd_len = 1;
+                       rule->set = 1;
+                       rule->cmd[0].len = 1;
+                       rule->cmd[0].opcode = O_ACCEPT;
+                       error = add_rule(&layer3_chain, rule);
+               }
                break;
 
        case IP_FW_ADD:
Index: sys/netinet/raw_ip.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.107
diff -u -r1.107 raw_ip.c
--- sys/netinet/raw_ip.c        20 Nov 2002 19:00:54 -0000      1.107
+++ sys/netinet/raw_ip.c        14 Dec 2002 21:33:58 -0000
@@ -399,6 +399,7 @@
                case IP_FW_ADD:
                case IP_FW_DEL:
                case IP_FW_FLUSH:
+               case IP_FW_UNBREAK:
                case IP_FW_ZERO:
                case IP_FW_RESETLOG:
                        if (IPFW_LOADED)

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to