Implement probabilistic rule match in ipfw. Each rule can be associated
with a match probability to achieve non-deterministic behaviour of the firewall. This can be extremely useful for testing purposes such as simulating random packet drop without having to use dummynet (which already does the same thing), and simulating multipath effects and the associated out-of-order delivery (this time in conjunction with dummynet). The overhead on normal rules is just one comparison with 0. Since it would have been trivial to implement this by just adding a field to the ip_fw structure, I decided to do it in a backward-compatible way (i.e. struct ip_fw is unchanged, and as a consequence you don't need to recompile ipfw if you don't want to use this feature), since this was also useful for -STABLE. When, at some point, someone decides to change struct ip_fw, please add a length field and a version number at the beginning, so userland apps can keep working even if they are out of sync with the kernel.
This commit is contained in:
parent
706aa7f870
commit
772759420f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=49630
@ -12,7 +12,7 @@
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*
|
||||
* $Id: ip_fw.c,v 1.115 1999/07/28 22:27:27 green Exp $
|
||||
* $Id: ip_fw.c,v 1.116 1999/08/01 16:57:15 green Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -626,7 +626,7 @@ non_ip: ip = NULL ;
|
||||
/* Check protocol; if wildcard, and no [ug]id, match */
|
||||
if (f->fw_prot == IPPROTO_IP) {
|
||||
if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)))
|
||||
goto got_match;
|
||||
goto rnd_then_got_match;
|
||||
} else
|
||||
/* If different, don't match */
|
||||
if (ip->ip_p != f->fw_prot)
|
||||
@ -812,6 +812,10 @@ non_ip: ip = NULL ;
|
||||
goto dropit;
|
||||
}
|
||||
|
||||
rnd_then_got_match:
|
||||
if ( ((struct ip_fw_ext *)f)->dont_match_prob &&
|
||||
random() < ((struct ip_fw_ext *)f)->dont_match_prob )
|
||||
continue ;
|
||||
got_match:
|
||||
*flow_id = chain ; /* XXX set flow id */
|
||||
/* Update statistics */
|
||||
@ -967,12 +971,14 @@ static int
|
||||
add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
|
||||
{
|
||||
struct ip_fw *ftmp = 0;
|
||||
struct ip_fw_ext *ftmp_ext = 0 ;
|
||||
struct ip_fw_chain *fwc = 0, *fcp, *fcpl = 0;
|
||||
u_short nbr = 0;
|
||||
int s;
|
||||
|
||||
fwc = malloc(sizeof *fwc, M_IPFW, M_DONTWAIT);
|
||||
ftmp = malloc(sizeof *ftmp, M_IPFW, M_DONTWAIT);
|
||||
ftmp_ext = malloc(sizeof *ftmp_ext, M_IPFW, M_DONTWAIT);
|
||||
ftmp = &ftmp_ext->rule ;
|
||||
if (!fwc || !ftmp) {
|
||||
dprintf(("%s malloc said no\n", err_prefix));
|
||||
if (fwc) free(fwc, M_IPFW);
|
||||
@ -980,7 +986,11 @@ add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
|
||||
return (ENOSPC);
|
||||
}
|
||||
|
||||
bcopy(frwl, ftmp, sizeof(struct ip_fw));
|
||||
bzero(ftmp_ext, sizeof(*ftmp_ext)); /* play safe! */
|
||||
bcopy(frwl, ftmp, sizeof(*ftmp));
|
||||
if (ftmp->fw_flg & IP_FW_F_RND_MATCH)
|
||||
ftmp_ext->dont_match_prob = (long)(ftmp->pipe_ptr) ;
|
||||
|
||||
ftmp->fw_in_if.fu_via_if.name[FW_IFNLEN - 1] = '\0';
|
||||
ftmp->fw_pcnt = 0L;
|
||||
ftmp->fw_bcnt = 0L;
|
||||
@ -1293,9 +1303,8 @@ ip_fw_ctl(struct sockopt *sopt)
|
||||
{
|
||||
int error, s;
|
||||
size_t size;
|
||||
char *buf, *bp;
|
||||
struct ip_fw_chain *fcp;
|
||||
struct ip_fw frwl;
|
||||
struct ip_fw frwl, *bp , *buf;
|
||||
|
||||
/*
|
||||
* Disallow sets in really-really secure mode, but still allow
|
||||
@ -1320,7 +1329,9 @@ ip_fw_ctl(struct sockopt *sopt)
|
||||
for (fcp = LIST_FIRST(&ip_fw_chain), bp = buf; fcp;
|
||||
fcp = LIST_NEXT(fcp, chain)) {
|
||||
bcopy(fcp->rule, bp, sizeof *fcp->rule);
|
||||
bp += sizeof *fcp->rule;
|
||||
(long)bp->pipe_ptr =
|
||||
((struct ip_fw_ext *)fcp->rule)->dont_match_prob;
|
||||
bp ++ ;
|
||||
}
|
||||
error = sooptcopyout(sopt, buf, size);
|
||||
FREE(buf, M_TEMP);
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*
|
||||
* $Id: ip_fw.h,v 1.39 1999/07/28 22:22:57 green Exp $
|
||||
* $Id: ip_fw.h,v 1.40 1999/08/01 16:57:16 green Exp $
|
||||
*/
|
||||
|
||||
#ifndef _IP_FW_H
|
||||
@ -89,6 +89,22 @@ struct ip_fw {
|
||||
u_int64_t fw_loghighest; /* highest number packet to log */
|
||||
};
|
||||
|
||||
/*
|
||||
* extended ipfw structure... some fields in the original struct
|
||||
* can be used to pass parameters up/down, namely pointers
|
||||
* void *pipe_ptr
|
||||
* void *next_rule_ptr
|
||||
* some others can be used to pass parameters down, namely counters etc.
|
||||
* u_int64_t fw_pcnt,fw_bcnt;
|
||||
* long timestamp;
|
||||
*/
|
||||
|
||||
struct ip_fw_ext { /* extended structure */
|
||||
struct ip_fw rule; /* must be at offset 0 */
|
||||
long dont_match_prob; /* 0x7fffffff means 1.0, always fail */
|
||||
u_int param1; /* unused at the moment */
|
||||
};
|
||||
|
||||
#define IP_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f)
|
||||
#define IP_FW_SETNSRCP(rule, n) do { \
|
||||
(rule)->fw_nports &= ~0x0f; \
|
||||
@ -154,7 +170,9 @@ struct ip_fw_chain {
|
||||
|
||||
#define IP_FW_F_GID 0x00400000 /* filter by uid */
|
||||
|
||||
#define IP_FW_F_MASK 0x007FFFFF /* All possible flag bits mask */
|
||||
#define IP_FW_F_RND_MATCH 0x00800000 /* probabilistic rule match */
|
||||
|
||||
#define IP_FW_F_MASK 0x00FFFFFF /* All possible flag bits mask */
|
||||
|
||||
/*
|
||||
* For backwards compatibility with rules specifying "via iface" but
|
||||
|
Loading…
Reference in New Issue
Block a user