The first customer of the SO_USER_COOKIE option:

the "sockarg" ipfw option matches packets associated to
a local socket and with a non-zero so_user_cookie value.
The value is made available as tablearg, so it can be used
as a skipto target or pipe number in ipfw/dummynet rules.

Code by Paul Joe, manpage by me.

Submitted by:	Paul Joe
MFC after:	1 week
This commit is contained in:
Luigi Rizzo 2010-11-12 13:05:17 +00:00
parent 5c9d0a9ad3
commit ae99fd0e07
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215179
6 changed files with 56 additions and 0 deletions

View File

@ -1510,6 +1510,17 @@ interface.
Matches TCP packets that have the SYN bit set but no ACK bit. Matches TCP packets that have the SYN bit set but no ACK bit.
This is the short form of This is the short form of
.Dq Li tcpflags\ syn,!ack . .Dq Li tcpflags\ syn,!ack .
.It Cm sockarg
Matches packets that are associated to a local socket and
for which the SO_USER_COOKIE socket option has been set
to a non-zero value. As a side effect, the value of the
option is made available as
.Cm tablearg
value, which in turn can be used as
.Cm skipto
or
.Cm pipe
number.
.It Cm src-ip Ar ip-address .It Cm src-ip Ar ip-address
Matches IPv4 packets whose source IP is one of the address(es) Matches IPv4 packets whose source IP is one of the address(es)
specified as an argument. specified as an argument.

View File

@ -266,6 +266,7 @@ static struct _s_x rule_options[] = {
{ "estab", TOK_ESTAB }, { "estab", TOK_ESTAB },
{ "established", TOK_ESTAB }, { "established", TOK_ESTAB },
{ "setup", TOK_SETUP }, { "setup", TOK_SETUP },
{ "sockarg", TOK_SOCKARG },
{ "tcpdatalen", TOK_TCPDATALEN }, { "tcpdatalen", TOK_TCPDATALEN },
{ "tcpflags", TOK_TCPFLAGS }, { "tcpflags", TOK_TCPFLAGS },
{ "tcpflgs", TOK_TCPFLAGS }, { "tcpflgs", TOK_TCPFLAGS },
@ -1338,6 +1339,9 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
case O_FIB: case O_FIB:
printf(" fib %u", cmd->arg1 ); printf(" fib %u", cmd->arg1 );
break; break;
case O_SOCKARG:
printf(" sockarg");
break;
case O_IN: case O_IN:
printf(cmd->len & F_NOT ? " out" : " in"); printf(cmd->len & F_NOT ? " out" : " in");
@ -3531,6 +3535,9 @@ ipfw_add(char *av[])
fill_cmd(cmd, O_FIB, 0, strtoul(*av, NULL, 0)); fill_cmd(cmd, O_FIB, 0, strtoul(*av, NULL, 0));
av++; av++;
break; break;
case TOK_SOCKARG:
fill_cmd(cmd, O_SOCKARG, 0, 0);
break;
case TOK_LOOKUP: { case TOK_LOOKUP: {
ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd; ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd;

View File

@ -199,6 +199,7 @@ enum tokens {
TOK_FIB, TOK_FIB,
TOK_SETFIB, TOK_SETFIB,
TOK_LOOKUP, TOK_LOOKUP,
TOK_SOCKARG,
}; };
/* /*
* the following macro returns an error message if we run out of * the following macro returns an error message if we run out of

View File

@ -192,10 +192,13 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_SETFIB, /* arg1=FIB number */ O_SETFIB, /* arg1=FIB number */
O_FIB, /* arg1=FIB desired fib number */ O_FIB, /* arg1=FIB desired fib number */
O_SOCKARG, /* socket argument */
O_LAST_OPCODE /* not an opcode! */ O_LAST_OPCODE /* not an opcode! */
}; };
/* /*
* The extension header are filtered only for presence using a bit * The extension header are filtered only for presence using a bit
* vector with a flag for each header. * vector with a flag for each header.

View File

@ -1801,6 +1801,39 @@ do { \
match = 1; match = 1;
break; break;
case O_SOCKARG: {
struct inpcb *inp = args->inp;
struct inpcbinfo *pi;
if (is_ipv6) /* XXX can we remove this ? */
break;
if (proto == IPPROTO_TCP)
pi = &V_tcbinfo;
else if (proto == IPPROTO_UDP)
pi = &V_udbinfo;
else
break;
/* For incomming packet, lookup up the
inpcb using the src/dest ip/port tuple */
if (inp == NULL) {
INP_INFO_RLOCK(pi);
inp = in_pcblookup_hash(pi,
src_ip, htons(src_port),
dst_ip, htons(dst_port),
0, NULL);
INP_INFO_RUNLOCK(pi);
}
if (inp && inp->inp_socket) {
tablearg = inp->inp_socket->so_user_cookie;
if (tablearg)
match = 1;
}
break;
}
case O_TAGGED: { case O_TAGGED: {
struct m_tag *mtag; struct m_tag *mtag;
uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ? uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ?

View File

@ -572,6 +572,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_IPTOS: case O_IPTOS:
case O_IPPRECEDENCE: case O_IPPRECEDENCE:
case O_IPVER: case O_IPVER:
case O_SOCKARG:
case O_TCPWIN: case O_TCPWIN:
case O_TCPFLAGS: case O_TCPFLAGS:
case O_TCPOPTS: case O_TCPOPTS: