kern/189720: pps action for ipfw
Bill Yuan
bycn82 at gmail.com
Mon May 12 15:40:00 UTC 2014
>Number: 189720
>Category: kern
>Synopsis: pps action for ipfw
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon May 12 15:40:00 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator: Bill Yuan
>Release: FB10Stable
>Organization:
cozilyworks
>Environment:
FreeBSD FB10Stable 10.0-STABLE FreeBSD 10.0-STABLE #0 r265900: Mon May 12 13:41:15 UTC 2014 root at FB10Stable:/usr/obj/usr/src/sys/GENERIC amd64
>Description:
pps action for ipfw
pps: packet for second (millisecond)
usage:
ipfw add pps 1 50 tcp from any to any
man page
pps limit duration
Rule with the pps keyword will allow the first limit packets in
each duration milliseconds
>How-To-Repeat:
>Fix:
Patch attached with submission follows:
Index: sbin/ipfw/ipfw.8
===================================================================
--- sbin/ipfw/ipfw.8 (revision 265916)
+++ sbin/ipfw/ipfw.8 (working copy)
@@ -603,6 +603,14 @@
Note: logging is done after all other packet matching conditions
have been successfully verified, and before performing the final
action (accept, deny, etc.) on the packet.
+.It Cm pps Ar limit duration
+Rule with the
+.Cm pps
+keyword will allow the first
+.Ar limit
+packets in each
+.Ar duration
+milliseconds
.It Cm tag Ar number
When a packet matches a rule with the
.Cm tag
Index: sbin/ipfw/ipfw2.c
===================================================================
--- sbin/ipfw/ipfw2.c (revision 265916)
+++ sbin/ipfw/ipfw2.c (working copy)
@@ -244,6 +244,7 @@
{ "allow", TOK_ACCEPT },
{ "permit", TOK_ACCEPT },
{ "count", TOK_COUNT },
+ { "pps", TOK_PPS },
{ "pipe", TOK_PIPE },
{ "queue", TOK_QUEUE },
{ "divert", TOK_DIVERT },
@@ -1231,7 +1232,12 @@
case O_SKIPTO:
PRINT_UINT_ARG("skipto ", cmd->arg1);
break;
-
+ case O_PPS:
+ {
+ ipfw_insn_pps *pps=(ipfw_insn_pps *)cmd;
+ printf("pps %d %d",cmd->arg1,pps->duration);
+ break;
+ }
case O_PIPE:
PRINT_UINT_ARG("pipe ", cmd->arg1);
break;
@@ -2985,7 +2991,23 @@
case TOK_COUNT:
action->opcode = O_COUNT;
break;
-
+
+ case TOK_PPS:
+ action->opcode = O_PPS;
+ ipfw_insn_pps *p = (ipfw_insn_pps *)action;
+ action->len = F_INSN_SIZE(ipfw_insn_pps);
+ if (isdigit(**av)) {
+ action->arg1 = strtoul(*av, NULL, 10);
+ av++;
+ }else
+ errx(EX_USAGE, "illegal argument pps `limit` %s", *av);
+ if (isdigit(**av)) {
+ p->duration = strtoul(*av, NULL, 10);
+ av++;
+ }else
+ errx(EX_USAGE,"illegal arugment pps `duration` %s", *av);
+ break;
+
case TOK_NAT:
action->opcode = O_NAT;
action->len = F_INSN_SIZE(ipfw_insn_nat);
Index: sbin/ipfw/ipfw2.h
===================================================================
--- sbin/ipfw/ipfw2.h (revision 265916)
+++ sbin/ipfw/ipfw2.h (working copy)
@@ -92,6 +92,7 @@
TOK_NGTEE,
TOK_FORWARD,
TOK_SKIPTO,
+ TOK_PPS,
TOK_DENY,
TOK_REJECT,
TOK_RESET,
Index: sys/netinet/ip_fw.h
===================================================================
--- sys/netinet/ip_fw.h (revision 265916)
+++ sys/netinet/ip_fw.h (working copy)
@@ -165,6 +165,7 @@
O_REJECT, /* arg1=icmp arg (same as deny) */
O_COUNT, /* none */
O_SKIPTO, /* arg1=next rule number */
+ O_PPS, /* arg1=limit, pps->duration */
O_PIPE, /* arg1=pipe number */
O_QUEUE, /* arg1=queue number */
O_DIVERT, /* arg1=port number */
@@ -378,6 +379,15 @@
} ipfw_insn_log;
/*
+ * This is used for PPS
+ */
+typedef struct _ipfw_insn_pps{
+ ipfw_insn o;
+ uint32_t start_time;
+ uint16_t count;
+ uint16_t duration;
+} ipfw_insn_pps;
+/*
* Data structures required by both ipfw(8) and ipfw(4) but not part of the
* management API are protected by IPFW_INTERNAL.
*/
Index: sys/netpfil/ipfw/ip_fw2.c
===================================================================
--- sys/netpfil/ipfw/ip_fw2.c (revision 265916)
+++ sys/netpfil/ipfw/ip_fw2.c (working copy)
@@ -2179,7 +2179,24 @@
skip_or = 0;
continue;
break; /* not reached */
-
+ case O_PPS:{
+ ipfw_insn_pps *pps = (ipfw_insn_pps *)cmd;
+ if(pps->start_time+pps->duration >= ticks){
+ if(pps->count < cmd->arg1){
+ retval = IP_FW_PASS;
+ }else{
+ retval = IP_FW_DENY;
+ }
+ pps->count++;
+ }else{
+ pps->start_time=ticks;
+ pps->count=1;
+ retval = IP_FW_PASS;
+ }
+ l = 0;
+ done = 1;
+ break;
+ }
case O_CALLRETURN: {
/*
* Implementation of `subroutine' call/return,
Index: sys/netpfil/ipfw/ip_fw_sockopt.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_sockopt.c (revision 265916)
+++ sys/netpfil/ipfw/ip_fw_sockopt.c (working copy)
@@ -702,6 +702,12 @@
if (cmdlen != F_INSN_SIZE(ipfw_insn_altq))
goto bad_size;
break;
+
+ case O_PPS:
+ have_action=1;
+ if (cmdlen != F_INSN_SIZE(ipfw_insn_pps))
+ goto bad_size;
+ break;
case O_PIPE:
case O_QUEUE:
@@ -769,6 +775,7 @@
return EINVAL;
}
break;
+
#ifdef INET6
case O_IP6_SRC:
case O_IP6_DST:
@@ -776,7 +783,6 @@
F_INSN_SIZE(ipfw_insn))
goto bad_size;
break;
-
case O_FLOW6ID:
if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) +
((ipfw_insn_u32 *)cmd)->o.arg1)
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list