The following reply was made to PR kern/80642; it has been noted by GNATS.

From: "Andrey V. Elsukov" <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED], [EMAIL PROTECTED]
Cc:  
Subject: Re: kern/80642: [patch] IPFW small patch - new RULE OPTION
Date: Fri, 17 Jun 2005 14:31:20 +0400

 This is a multi-part message in MIME format.
 --------------020602060206080505060104
 Content-Type: text/plain; charset=KOI8-R; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Robert Watson wrote:
  > This patch breaks the ABI by inserting a new type into an implicitly
  > numbered enumeration, renumbering all entries later in the enum.
  > O_BOUND, if added, should be appended to the end, and/or we should
  > number  the operations explicitly.
 
 Ok. I have corrected this.
 * ipfw_bound.diff - the patch with smallest changes, with only bound option.
 * ipfw_bound2.diff - bound and check-bound option.
 
 Examples:
 
 We can limit incoming traffic (internet is external interface):
 # ipfw add allow ip from any to 10.0.0.20 in recv internet bound 10MB
 # ipfw add deny ip from any to 10.0.0.0/24 in recv internet
 
 We can use traffic shaper after excess of a limit:
 # ipfw add allow ip from any to 10.0.0.20 in recv internet bound 10MB
 # ipfw add pipe 1 ip from any to 10.0.0.20 in recv internet
 # ipfw pipe 1 config bw 5Kbit/s queue 10Kbytes
 
 We can block any access after limit excess:
 # ipfw add 100 allow ip from 10.0.0.20 to any out xmit internet \ 
 check-bound 200
 # ipfw add 200 allow ip from any to 10.0.0.20 in recv internet bound \ 10MB
 # ipfw add 300 deny ip from any to any
 
 More details you can read on http://butcher.heavennet.ru/
 -- 
 WBR, Andrey V. Elsukov
 
 --------------020602060206080505060104
 Content-Type: text/plain;
  name="ipfw_bound.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="ipfw_bound.diff"
 
 --- sbin/ipfw/ipfw2.c  Tue Jun  7 18:11:17 2005
 +++ sbin/ipfw/ipfw2.c  Fri Jun 17 13:09:43 2005
 @@ -277,6 +277,7 @@
        TOK_SRCIP6,
  
        TOK_IPV4,
 +      TOK_BOUND,
  };
  
  struct _s_x dummynet_params[] = {
 @@ -403,6 +404,7 @@
        { "dst-ip6",            TOK_DSTIP6},
        { "src-ipv6",           TOK_SRCIP6},
        { "src-ip6",            TOK_SRCIP6},
 +      { "bound",              TOK_BOUND},
        { "//",                 TOK_COMMENT },
  
        { "not",                TOK_NOT },              /* pseudo option */
 @@ -1858,6 +1860,10 @@
                                print_ext6hdr( (ipfw_insn *) cmd );
                                break;
  
 +                      case O_BOUND:
 +                              printf(" bound %u", ((ipfw_insn_u64 
*)cmd)->bound);
 +                              break;
 +
                        default:
                                printf(" [opcode %d len %d]",
                                    cmd->opcode, cmd->len);
 @@ -2515,7 +2521,7 @@
  "     icmp6types LIST | ext6hdr LIST | flow-id N[,N] |\n"
  "     mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
  "     setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
 -"     tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
 +"     tcpdatalen LIST | verrevpath | versrcreach | antispoof | bound VALUE\n"
  );
  exit(0);
  }
 @@ -3683,6 +3689,7 @@
        int i;
  
        int open_par = 0;       /* open parenthesis ( */
 +      int have_bound = 0;
  
        /* proto is here because it is used to fetch ports */
        u_char proto = IPPROTO_IP;      /* default protocol */
 @@ -4492,6 +4499,33 @@
                        fill_comment(cmd, ac, av);
                        av += ac;
                        ac = 0;
 +                      break;
 +
 +              case TOK_BOUND:
 +                      NEED1("bound requires numeric value");
 +                      if (have_bound)
 +                              errx(EX_USAGE, "only one of bound is allowed");
 +                      if (open_par)
 +                              errx(EX_USAGE, "bound cannot be part "
 +                                              "of an or block"); 
 +                      if (cmd->len & F_NOT)
 +                              errx(EX_USAGE, 
 +                              "\"not\" not allowed with bound option"); 
 +                      {
 +                              char *end = NULL;
 +                              uint64_t bound = strtoull(*av, &end, 0);
 +                              if (bound)
 +                              switch (*end){
 +                                      case 'G': bound *= 1024;
 +                                      case 'M': bound *= 1024;
 +                                      case 'K': bound *= 1024;
 +                              };
 +                              cmd->opcode = O_BOUND;
 +                              ((ipfw_insn_u64 *)cmd)->bound = bound;
 +                              cmd->len = F_INSN_SIZE(ipfw_insn_u64) & 
F_LEN_MASK;
 +                              have_bound = 1;
 +                              ac--; av++;
 +                      } 
                        break;
  
                default:
 --- sys/netinet/ip_fw.h        Fri Jun  3 05:10:28 2005
 +++ sys/netinet/ip_fw.h        Fri Jun 17 11:30:30 2005
 @@ -154,6 +154,7 @@
        O_NGTEE,                /* copy to ng_ipfw              */
  
        O_IP4,
 +      O_BOUND,                /* u64 = bound in bytes */
  
        O_LAST_OPCODE           /* not an opcode!               */
  };
 @@ -228,6 +229,14 @@
        ipfw_insn o;
        u_int32_t d[1]; /* one or more */
  } ipfw_insn_u32;
 +
 +/*
 + * This is used to store 64-bit bound value.
 + */
 +typedef struct        _ipfw_insn_u64 {
 +      ipfw_insn o;
 +      u_int64_t bound;
 +} ipfw_insn_u64; 
  
  /*
   * This is used to store IP addr-mask pairs.
 --- sys/netinet/ip_fw2.c       Thu Jun 16 18:55:58 2005
 +++ sys/netinet/ip_fw2.c       Fri Jun 17 11:46:36 2005
 @@ -2251,6 +2251,10 @@
                         * logic to deal with F_NOT and F_OR flags associated
                         * with the opcode.
                         */
 +                      case O_BOUND:
 +                              match = (f->bcnt < ((ipfw_insn_u64 
*)cmd)->bound);
 +                              break;
 +
                        case O_NOP:
                                match = 1;
                                break;
 @@ -3387,6 +3391,11 @@
                case O_PROB:
                case O_ICMPTYPE:
                        if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
 +                              goto bad_size;
 +                      break;
 +              
 +              case O_BOUND:
 +                      if (cmdlen != F_INSN_SIZE(ipfw_insn_u64))
                                goto bad_size;
                        break;
  
 
 --------------020602060206080505060104
 Content-Type: text/plain;
  name="ipfw_bound2.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="ipfw_bound2.diff"
 
 --- sbin/ipfw/ipfw2.c  Tue Jun  7 18:11:17 2005
 +++ sbin/ipfw/ipfw2.c  Fri Jun 17 13:40:54 2005
 @@ -277,6 +277,8 @@
        TOK_SRCIP6,
  
        TOK_IPV4,
 +      TOK_BOUND,
 +      TOK_CHECK_BOUND,
  };
  
  struct _s_x dummynet_params[] = {
 @@ -403,6 +405,8 @@
        { "dst-ip6",            TOK_DSTIP6},
        { "src-ipv6",           TOK_SRCIP6},
        { "src-ip6",            TOK_SRCIP6},
 +      { "bound",              TOK_BOUND},
 +      { "check-bound",        TOK_CHECK_BOUND},
        { "//",                 TOK_COMMENT },
  
        { "not",                TOK_NOT },              /* pseudo option */
 @@ -1636,6 +1640,9 @@
                        flags |= HAVE_PROTO;
                        break;
  
 +              case O_BOUND:
 +                      break;
 +
                default: /*options ... */
                        if (!(cmd->len & (F_OR|F_NOT)))
                                if (((cmd->opcode == O_IP6) &&
 @@ -1858,6 +1865,10 @@
                                print_ext6hdr( (ipfw_insn *) cmd );
                                break;
  
 +                      case O_CHECK_BOUND:
 +                              printf(" check-bound %d", cmd->arg1);
 +                              break;
 +
                        default:
                                printf(" [opcode %d len %d]",
                                    cmd->opcode, cmd->len);
 @@ -1872,6 +1883,8 @@
                }
        }
        show_prerequisites(&flags, HAVE_IP, 0);
 +      if (rule->cmd->opcode == O_BOUND) 
 +              printf(" bound %u", ((ipfw_insn_u64 *)(rule->cmd))->bound);
        if (comment)
                printf(" // %s", comment);
        printf("\n");
 @@ -2515,7 +2528,8 @@
  "     icmp6types LIST | ext6hdr LIST | flow-id N[,N] |\n"
  "     mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
  "     setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
 -"     tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
 +"     tcpdatalen LIST | verrevpath | versrcreach | antispoof | bound VALUE 
|\n"
 +"     check-bound NUM\n"
  );
  exit(0);
  }
 @@ -3677,7 +3691,8 @@
         * various flags used to record that we entered some fields.
         */
        ipfw_insn *have_state = NULL;   /* check-state or keep-state */
 -      ipfw_insn *have_log = NULL, *have_altq = NULL;
 +      ipfw_insn *have_log = NULL, *have_altq = NULL,
 +                *have_bound = NULL;
        size_t len;
  
        int i;
 @@ -4494,6 +4509,39 @@
                        ac = 0;
                        break;
  
 +              case TOK_BOUND:
 +                      NEED1("bound requires numeric value");
 +                      if (have_bound)
 +                              errx(EX_USAGE, "only one of bound is allowed");
 +                      if (open_par)
 +                              errx(EX_USAGE, "bound cannot be part "
 +                                              "of an or block"); 
 +                      if (cmd->len & F_NOT)
 +                              errx(EX_USAGE, 
 +                              "\"not\" not allowed with bound option"); 
 +                      {
 +                              char *end = NULL;
 +                              uint64_t bound = strtoull(*av, &end, 0);
 +                              if (bound)
 +                              switch (*end){
 +                                      case 'G': bound *= 1024;
 +                                      case 'M': bound *= 1024;
 +                                      case 'K': bound *= 1024;
 +                              };
 +                              cmd->opcode = O_BOUND;
 +                              ((ipfw_insn_u64 *)cmd)->bound = bound;
 +                              cmd->len = F_INSN_SIZE(ipfw_insn_u64) & 
F_LEN_MASK;
 +                              have_bound = cmd;
 +                              ac--; av++;
 +                      } 
 +                      break;
 +
 +              case TOK_CHECK_BOUND:
 +                      NEED1("check-bound requires rule number"); 
 +                      fill_cmd(cmd, O_CHECK_BOUND, 0, strtoul(*av, NULL, 0));
 +                      ac--; av++; 
 +                      break;
 +
                default:
                        errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
                }
 @@ -4506,6 +4554,8 @@
  done:
        /*
         * Now copy stuff into the rule.
 +       * If we have a bound option, the first instruction MUST BE 
 +       * a O_BOUND.
         * If we have a keep-state option, the first instruction
         * must be a PROBE_STATE (which is generated here).
         * If we have a LOG option, it was stored as the first command,
 @@ -4514,7 +4564,15 @@
        dst = (ipfw_insn *)rule->cmd;
  
        /*
 -       * First thing to write into the command stream is the match 
probability.
 +       * First write into the command stream bound instruction
 +       */
 +      if (have_bound) {
 +              bcopy(have_bound, dst, F_LEN(have_bound) * sizeof(uint32_t));
 +              dst = next_cmd(dst);
 +      }
 +
 +      /*
 +       * write the match probability  
         */
        if (match_prob != 1) { /* 1 means always match */
                dst->opcode = O_PROB;
 @@ -4531,7 +4589,8 @@
                dst = next_cmd(dst);
        }
        /*
 -       * copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ
 +       * copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ,
 +       * O_BOUND
         */
        for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
                i = F_LEN(src);
 @@ -4541,6 +4600,7 @@
                case O_KEEP_STATE:
                case O_LIMIT:
                case O_ALTQ:
 +              case O_BOUND:
                        break;
                default:
                        bcopy(src, dst, i * sizeof(uint32_t));
 --- sys/netinet/ip_fw.h        Fri Jun  3 05:10:28 2005
 +++ sys/netinet/ip_fw.h        Fri Jun 17 13:18:47 2005
 @@ -154,6 +154,8 @@
        O_NGTEE,                /* copy to ng_ipfw              */
  
        O_IP4,
 +      O_BOUND,                /* u64 = bound in bytes */
 +      O_CHECK_BOUND,          /* u16 = rule number */
  
        O_LAST_OPCODE           /* not an opcode!               */
  };
 @@ -230,6 +232,14 @@
  } ipfw_insn_u32;
  
  /*
 + * This is used to store 64-bit bound value.
 + */
 +typedef struct        _ipfw_insn_u64 {
 +      ipfw_insn o;
 +      u_int64_t bound;
 +} ipfw_insn_u64; 
 +
 +/*
   * This is used to store IP addr-mask pairs.
   */
  typedef struct        _ipfw_insn_ip {
 @@ -351,11 +361,16 @@
   *
   * When assembling instruction, remember the following:
   *
 + *  + if a rule has a "bound" option, then the first instruction
 + *    (at r->cmd) MUST BE an O_BOUND
   *  + if a rule has a "keep-state" (or "limit") option, then the
   *    first instruction (at r->cmd) MUST BE an O_PROBE_STATE
   *  + if a rule has a "log" option, then the first action
   *    (at ACTION_PTR(r)) MUST be O_LOG
   *  + if a rule has an "altq" option, it comes after "log"
 + *
 + * NOTE: actually, O_PROB instruction may be first too. But O_BOUND 
 + *    MUST BE always first (at r->cmd). 
   *
   * NOTE: we use a simple linked list of rules because we never need
   *    to delete a rule without scanning the list. We do not use
 --- sys/netinet/ip_fw2.c       Thu Jun 16 18:55:58 2005
 +++ sys/netinet/ip_fw2.c       Fri Jun 17 13:26:19 2005
 @@ -2251,6 +2251,26 @@
                         * logic to deal with F_NOT and F_OR flags associated
                         * with the opcode.
                         */
 +                      case O_BOUND:
 +                              match = (f->bcnt < ((ipfw_insn_u64 
*)cmd)->bound);
 +                              break;
 +
 +                      case O_CHECK_BOUND:
 +                              {
 +                              struct ip_fw* rule;
 +                              for (rule = f->next; 
 +                                       rule && cmd->arg1 >= rule->rulenum; 
 +                                       rule = rule->next) 
 +                                      if (rule->rulenum == cmd->arg1 && 
 +                                              rule->cmd->opcode == O_BOUND )
 +                                      {
 +                                              match = (rule->bcnt < 
 +                                                      ((ipfw_insn_u64 
*)(rule->cmd))->bound);
 +                                              break;
 +                                      }
 +                              }
 +                              break;
 + 
                        case O_NOP:
                                match = 1;
                                break;
 @@ -3373,6 +3393,7 @@
                case O_EXT_HDR:
                case O_IP6:
                case O_IP4:
 +              case O_CHECK_BOUND:
                        if (cmdlen != F_INSN_SIZE(ipfw_insn))
                                goto bad_size;
                        break;
 @@ -3388,6 +3409,16 @@
                case O_ICMPTYPE:
                        if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
                                goto bad_size;
 +                      break;
 +              
 +              case O_BOUND:
 +                      if (cmdlen != F_INSN_SIZE(ipfw_insn_u64))
 +                              goto bad_size;
 +                      if (cmd != rule->cmd) {
 +                              printf("ipfw: bogus rule, opcode %d must be 
first\n",
 +                                              cmd->opcode);
 +                              return EINVAL;
 +                      } 
                        break;
  
                case O_LIMIT:
 
 --------------020602060206080505060104--
 
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-ipfw
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to