Implement an ipfw action to reassemble ip packets: reass.

This commit is contained in:
Paolo Pisati 2009-04-01 20:23:47 +00:00
parent 8b61c10e48
commit eb2e411915
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=190633
7 changed files with 80 additions and 2 deletions

View File

@ -866,6 +866,13 @@ in any subsequent forwarding decisions.
Initially this is limited to the values 0 through 15, see
.Xr setfib 8 .
Processing continues at the next rule.
.It Cm reass
Queue and reassemble ip fragments.
If the packet is not fragmented, counters are updated and processing continues with the next rule.
If the packet is the last logical fragment, the packet is reassembled and, if
.Va net.inet.ip.fw.one_pass
is set to 0, processing continues with the next rule, else packet is allowed to pass and search terminates.
If the packet is a fragment in the middle, it is consumed and processing stops immediately.
.El
.Ss RULE BODY
The body of a rule contains zero or more patterns (such as

View File

@ -211,6 +211,7 @@ static struct _s_x rule_actions[] = {
{ "check-state", TOK_CHECKSTATE },
{ "//", TOK_COMMENT },
{ "nat", TOK_NAT },
{ "reass", TOK_REASS },
{ "setfib", TOK_SETFIB },
{ NULL, 0 } /* terminator */
};
@ -1089,6 +1090,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
case O_SETFIB:
PRINT_UINT_ARG("setfib ", cmd->arg1);
break;
case O_REASS:
printf("reass");
break;
default:
printf("** unrecognized action %d len %d ",
@ -2781,6 +2786,10 @@ ipfw_add(int ac, char *av[])
ac--; av++;
break;
}
case TOK_REASS:
action->opcode = O_REASS;
break;
default:
errx(EX_DATAERR, "invalid action %s\n", av[-1]);

View File

@ -95,6 +95,7 @@ enum tokens {
TOK_UNREACH,
TOK_CHECKSTATE,
TOK_NAT,
TOK_REASS,
TOK_ALTQ,
TOK_LOG,

View File

@ -54,7 +54,7 @@ help(void)
"RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
"ACTION: check-state | allow | count | deny | unreach{,6} CODE |\n"
" skipto N | {divert|tee} PORT | forward ADDR |\n"
" pipe N | queue N | nat N | setfib FIB\n"
" pipe N | queue N | nat N | setfib FIB | reass\n"
"PARAMS: [log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
"ADDR: [ MAC dst src ether_type ] \n"
" [ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"

View File

@ -139,7 +139,8 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_FORWARD_IP, /* fwd sockaddr */
O_FORWARD_MAC, /* fwd mac */
O_NAT, /* nope */
O_REASS, /* none */
/*
* More opcodes.
*/
@ -574,6 +575,7 @@ enum {
IP_FW_NETGRAPH,
IP_FW_NGTEE,
IP_FW_NAT,
IP_FW_REASS,
};
/* flags for divert mtag */

View File

@ -898,6 +898,9 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
case O_NAT:
action = "Nat";
break;
case O_REASS:
action = "Reass";
break;
default:
action = "UNKNOWN";
break;
@ -3375,6 +3378,55 @@ do { \
goto done;
}
case O_REASS: {
int ip_off;
f->pcnt++;
f->bcnt += pktlen;
ip_off = (args->eh != NULL) ? ntohs(ip->ip_off) : ip->ip_off;
if (ip_off & (IP_MF | IP_OFFMASK)) {
/*
* ip_reass() expects len & off in host
* byte order: fix them in case we come
* from layer2.
*/
if (args->eh != NULL) {
ip->ip_len = ntohs(ip->ip_len);
ip->ip_off = ntohs(ip->ip_off);
}
m = ip_reass(m);
args->m = m;
/*
* IP header checksum fixup after
* reassembly and leave header
* in network byte order.
*/
if (m != NULL) {
int hlen;
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
/* revert len & off for layer2 pkts */
if (args->eh != NULL)
ip->ip_len = htons(ip->ip_len);
ip->ip_sum = 0;
if (hlen == sizeof(struct ip))
ip->ip_sum = in_cksum_hdr(ip);
else
ip->ip_sum = in_cksum(m, hlen);
retval = IP_FW_REASS;
args->rule = f;
goto done;
} else {
retval = IP_FW_DENY;
goto done;
}
}
goto next_rule;
}
default:
panic("-- unknown opcode %d\n", cmd->opcode);
} /* end of switch() on opcodes */
@ -4024,6 +4076,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_UNREACH6:
#endif
case O_SKIPTO:
case O_REASS:
check_size:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size;

View File

@ -200,6 +200,9 @@ ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
case IP_FW_NAT:
goto again; /* continue with packet */
case IP_FW_REASS:
goto again;
default:
KASSERT(0, ("%s: unknown retval", __func__));
}
@ -329,6 +332,9 @@ ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
case IP_FW_NAT:
goto again; /* continue with packet */
case IP_FW_REASS:
goto again;
default:
KASSERT(0, ("%s: unknown retval", __func__));
}