Change handling to support strong alignment architectures such as alpha and
sparc64. PR: alpha/50658 Submitted by: rizzo Tested on: alpha
This commit is contained in:
parent
0b95513444
commit
330462a315
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=115793
@ -348,6 +348,14 @@ struct _s_x rule_options[] = {
|
|||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static __inline u_int64_t
|
||||||
|
align_uint64(u_int64_t *pll) {
|
||||||
|
u_int64_t ret;
|
||||||
|
|
||||||
|
bcopy (pll, &ret, sizeof(ret));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* match_token takes a table and a string, returns the value associated
|
* match_token takes a table and a string, returns the value associated
|
||||||
* with the string (0 meaning an error in most cases)
|
* with the string (0 meaning an error in most cases)
|
||||||
@ -813,8 +821,9 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
|||||||
int flags = 0; /* prerequisites */
|
int flags = 0; /* prerequisites */
|
||||||
ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */
|
ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */
|
||||||
int or_block = 0; /* we are in an or block */
|
int or_block = 0; /* we are in an or block */
|
||||||
|
u_int32_t set_disable;
|
||||||
|
|
||||||
u_int32_t set_disable = rule->set_disable;
|
bcopy(&rule->next_rule, &set_disable, sizeof(set_disable));
|
||||||
|
|
||||||
if (set_disable & (1 << rule->set)) { /* disabled */
|
if (set_disable & (1 << rule->set)) { /* disabled */
|
||||||
if (!show_sets)
|
if (!show_sets)
|
||||||
@ -825,8 +834,8 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
|||||||
printf("%05u ", rule->rulenum);
|
printf("%05u ", rule->rulenum);
|
||||||
|
|
||||||
if (do_acct)
|
if (do_acct)
|
||||||
printf("%*llu %*llu ", pcwidth, rule->pcnt, bcwidth,
|
printf("%*llu %*llu ", pcwidth, align_uint64(&rule->pcnt),
|
||||||
rule->bcnt);
|
bcwidth, align_uint64(&rule->bcnt));
|
||||||
|
|
||||||
if (do_time) {
|
if (do_time) {
|
||||||
char timestr[30];
|
char timestr[30];
|
||||||
@ -1213,14 +1222,18 @@ show_dyn_ipfw(ipfw_dyn_rule *d, int pcwidth, int bcwidth)
|
|||||||
{
|
{
|
||||||
struct protoent *pe;
|
struct protoent *pe;
|
||||||
struct in_addr a;
|
struct in_addr a;
|
||||||
|
uint16_t rulenum;
|
||||||
|
|
||||||
if (!do_expired) {
|
if (!do_expired) {
|
||||||
if (!d->expire && !(d->dyn_type == O_LIMIT_PARENT))
|
if (!d->expire && !(d->dyn_type == O_LIMIT_PARENT))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%05d %*llu %*llu (%ds)", d->rulenum, pcwidth, d->pcnt, bcwidth,
|
bcopy(&d->rule, &rulenum, sizeof(rulenum));
|
||||||
d->bcnt, d->expire);
|
|
||||||
|
printf("%05d %*llu %*llu (%ds)", rulenum, pcwidth,
|
||||||
|
align_uint64(&d->pcnt), bcwidth,
|
||||||
|
align_uint64(&d->bcnt), d->expire);
|
||||||
switch (d->dyn_type) {
|
switch (d->dyn_type) {
|
||||||
case O_LIMIT_PARENT:
|
case O_LIMIT_PARENT:
|
||||||
printf(" PARENT %d", d->count);
|
printf(" PARENT %d", d->count);
|
||||||
@ -1454,7 +1467,9 @@ sets_handler(int ac, char *av[])
|
|||||||
err(EX_OSERR, "malloc");
|
err(EX_OSERR, "malloc");
|
||||||
if (getsockopt(s, IPPROTO_IP, IP_FW_GET, data, &nbytes) < 0)
|
if (getsockopt(s, IPPROTO_IP, IP_FW_GET, data, &nbytes) < 0)
|
||||||
err(EX_OSERR, "getsockopt(IP_FW_GET)");
|
err(EX_OSERR, "getsockopt(IP_FW_GET)");
|
||||||
set_disable = ((struct ip_fw *)data)->set_disable;
|
bcopy(&((struct ip_fw *)data)->next_rule,
|
||||||
|
&set_disable, sizeof(set_disable));
|
||||||
|
|
||||||
|
|
||||||
for (i = 0, msg = "disable" ; i < 31; i++)
|
for (i = 0, msg = "disable" ; i < 31; i++)
|
||||||
if ( (set_disable & (1<<i))) {
|
if ( (set_disable & (1<<i))) {
|
||||||
@ -1620,23 +1635,27 @@ list(int ac, char *av[])
|
|||||||
for (n = 0, r = data; n < nstat;
|
for (n = 0, r = data; n < nstat;
|
||||||
n++, r = (void *)r + RULESIZE(r)) {
|
n++, r = (void *)r + RULESIZE(r)) {
|
||||||
/* packet counter */
|
/* packet counter */
|
||||||
width = snprintf(NULL, 0, "%llu", r->pcnt);
|
width = snprintf(NULL, 0, "%llu",
|
||||||
|
align_uint64(&r->pcnt));
|
||||||
if (width > pcwidth)
|
if (width > pcwidth)
|
||||||
pcwidth = width;
|
pcwidth = width;
|
||||||
|
|
||||||
/* byte counter */
|
/* byte counter */
|
||||||
width = snprintf(NULL, 0, "%llu", r->bcnt);
|
width = snprintf(NULL, 0, "%llu",
|
||||||
|
align_uint64(&r->bcnt));
|
||||||
if (width > bcwidth)
|
if (width > bcwidth)
|
||||||
bcwidth = width;
|
bcwidth = width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (do_dynamic && ndyn) {
|
if (do_dynamic && ndyn) {
|
||||||
for (n = 0, d = dynrules; n < ndyn; n++, d++) {
|
for (n = 0, d = dynrules; n < ndyn; n++, d++) {
|
||||||
width = snprintf(NULL, 0, "%llu", d->pcnt);
|
width = snprintf(NULL, 0, "%llu",
|
||||||
|
align_uint64(&d->pcnt));
|
||||||
if (width > pcwidth)
|
if (width > pcwidth)
|
||||||
pcwidth = width;
|
pcwidth = width;
|
||||||
|
|
||||||
width = snprintf(NULL, 0, "%llu", d->bcnt);
|
width = snprintf(NULL, 0, "%llu",
|
||||||
|
align_uint64(&d->bcnt));
|
||||||
if (width > bcwidth)
|
if (width > bcwidth)
|
||||||
bcwidth = width;
|
bcwidth = width;
|
||||||
}
|
}
|
||||||
@ -1690,9 +1709,12 @@ list(int ac, char *av[])
|
|||||||
/* already warned */
|
/* already warned */
|
||||||
continue;
|
continue;
|
||||||
for (n = 0, d = dynrules; n < ndyn; n++, d++) {
|
for (n = 0, d = dynrules; n < ndyn; n++, d++) {
|
||||||
if (d->rulenum > rnum)
|
uint16_t rulenum;
|
||||||
|
|
||||||
|
bcopy(&d->rule, &rulenum, sizeof(rulenum));
|
||||||
|
if (rulenum > rnum)
|
||||||
break;
|
break;
|
||||||
if (d->rulenum == rnum)
|
if (rulenum == rnum)
|
||||||
show_dyn_ipfw(d, pcwidth, bcwidth);
|
show_dyn_ipfw(d, pcwidth, bcwidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1027,7 +1027,11 @@ locate_flowset(int pipe_nr, struct ip_fw *rule)
|
|||||||
|
|
||||||
if (cmd->opcode == O_LOG)
|
if (cmd->opcode == O_LOG)
|
||||||
cmd += F_LEN(cmd);
|
cmd += F_LEN(cmd);
|
||||||
|
#ifdef __i386__
|
||||||
fs = ((ipfw_insn_pipe *)cmd)->pipe_ptr;
|
fs = ((ipfw_insn_pipe *)cmd)->pipe_ptr;
|
||||||
|
#else
|
||||||
|
bcopy(& ((ipfw_insn_pipe *)cmd)->pipe_ptr, &fs, sizeof(fs));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (fs != NULL)
|
if (fs != NULL)
|
||||||
return fs;
|
return fs;
|
||||||
@ -1049,7 +1053,11 @@ locate_flowset(int pipe_nr, struct ip_fw *rule)
|
|||||||
}
|
}
|
||||||
/* record for the future */
|
/* record for the future */
|
||||||
#if IPFW2
|
#if IPFW2
|
||||||
|
#ifdef __i386__
|
||||||
((ipfw_insn_pipe *)cmd)->pipe_ptr = fs;
|
((ipfw_insn_pipe *)cmd)->pipe_ptr = fs;
|
||||||
|
#else
|
||||||
|
bcopy(&fs, & ((ipfw_insn_pipe *)cmd)->pipe_ptr, sizeof(fs));
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
if (fs != NULL)
|
if (fs != NULL)
|
||||||
rule->pipe_ptr = fs;
|
rule->pipe_ptr = fs;
|
||||||
|
@ -32,11 +32,16 @@
|
|||||||
* The kernel representation of ipfw rules is made of a list of
|
* The kernel representation of ipfw rules is made of a list of
|
||||||
* 'instructions' (for all practical purposes equivalent to BPF
|
* 'instructions' (for all practical purposes equivalent to BPF
|
||||||
* instructions), which specify which fields of the packet
|
* instructions), which specify which fields of the packet
|
||||||
* (or its metatada) should be analysed.
|
* (or its metadata) should be analysed.
|
||||||
*
|
*
|
||||||
* Each instruction is stored in a structure which begins with
|
* Each instruction is stored in a structure which begins with
|
||||||
* "ipfw_insn", and can contain extra fields depending on the
|
* "ipfw_insn", and can contain extra fields depending on the
|
||||||
* instruction type (listed below).
|
* instruction type (listed below).
|
||||||
|
* Note that the code is written so that individual instructions
|
||||||
|
* have a size which is a multiple of 32 bits. This means that, if
|
||||||
|
* such structures contain pointers or other 64-bit entities,
|
||||||
|
* (there is just one instance now) they may end up unaligned on
|
||||||
|
* 64-bit architectures, so the must be handled with care.
|
||||||
*
|
*
|
||||||
* "enum ipfw_opcodes" are the opcodes supported. We can have up
|
* "enum ipfw_opcodes" are the opcodes supported. We can have up
|
||||||
* to 256 different opcodes.
|
* to 256 different opcodes.
|
||||||
@ -211,7 +216,7 @@ typedef struct _ipfw_insn_if {
|
|||||||
ipfw_insn o;
|
ipfw_insn o;
|
||||||
union {
|
union {
|
||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
int unit;
|
int32_t unit;
|
||||||
} p;
|
} p;
|
||||||
char name[IFNAMSIZ];
|
char name[IFNAMSIZ];
|
||||||
} ipfw_insn_if;
|
} ipfw_insn_if;
|
||||||
@ -220,10 +225,13 @@ typedef struct _ipfw_insn_if {
|
|||||||
* This is used for pipe and queue actions, which need to store
|
* This is used for pipe and queue actions, which need to store
|
||||||
* a single pointer (which can have different size on different
|
* a single pointer (which can have different size on different
|
||||||
* architectures.
|
* architectures.
|
||||||
|
* Note that, because of previous instructions, pipe_ptr might
|
||||||
|
* be unaligned in the overall structure, so it needs to be
|
||||||
|
* manipulated with care.
|
||||||
*/
|
*/
|
||||||
typedef struct _ipfw_insn_pipe {
|
typedef struct _ipfw_insn_pipe {
|
||||||
ipfw_insn o;
|
ipfw_insn o;
|
||||||
void *pipe_ptr;
|
void *pipe_ptr; /* XXX */
|
||||||
} ipfw_insn_pipe;
|
} ipfw_insn_pipe;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -278,7 +286,9 @@ typedef struct _ipfw_insn_log {
|
|||||||
struct ip_fw {
|
struct ip_fw {
|
||||||
struct ip_fw *next; /* linked list of rules */
|
struct ip_fw *next; /* linked list of rules */
|
||||||
struct ip_fw *next_rule; /* ptr to next [skipto] rule */
|
struct ip_fw *next_rule; /* ptr to next [skipto] rule */
|
||||||
|
#if 0 /* passed up using 'next_rule' */
|
||||||
u_int32_t set_disable; /* disabled sets (for userland) */
|
u_int32_t set_disable; /* disabled sets (for userland) */
|
||||||
|
#endif
|
||||||
u_int16_t act_ofs; /* offset of action in 32-bit units */
|
u_int16_t act_ofs; /* offset of action in 32-bit units */
|
||||||
u_int16_t cmd_len; /* # of 32-bit words in cmd */
|
u_int16_t cmd_len; /* # of 32-bit words in cmd */
|
||||||
u_int16_t rulenum; /* rule number */
|
u_int16_t rulenum; /* rule number */
|
||||||
@ -319,12 +329,12 @@ typedef struct _ipfw_dyn_rule ipfw_dyn_rule;
|
|||||||
|
|
||||||
struct _ipfw_dyn_rule {
|
struct _ipfw_dyn_rule {
|
||||||
ipfw_dyn_rule *next; /* linked list of rules. */
|
ipfw_dyn_rule *next; /* linked list of rules. */
|
||||||
struct ipfw_flow_id id; /* (masked) flow id */
|
|
||||||
struct ip_fw *rule; /* pointer to rule */
|
struct ip_fw *rule; /* pointer to rule */
|
||||||
ipfw_dyn_rule *parent; /* pointer to parent rule */
|
ipfw_dyn_rule *parent; /* pointer to parent rule */
|
||||||
u_int32_t expire; /* expire time */
|
|
||||||
u_int64_t pcnt; /* packet match counter */
|
u_int64_t pcnt; /* packet match counter */
|
||||||
u_int64_t bcnt; /* byte match counter */
|
u_int64_t bcnt; /* byte match counter */
|
||||||
|
struct ipfw_flow_id id; /* (masked) flow id */
|
||||||
|
u_int32_t expire; /* expire time */
|
||||||
u_int32_t bucket; /* which bucket in hash table */
|
u_int32_t bucket; /* which bucket in hash table */
|
||||||
u_int32_t state; /* state of this rule (typically a
|
u_int32_t state; /* state of this rule (typically a
|
||||||
* combination of TCP flags)
|
* combination of TCP flags)
|
||||||
@ -334,7 +344,9 @@ struct _ipfw_dyn_rule {
|
|||||||
/* to generate keepalives) */
|
/* to generate keepalives) */
|
||||||
u_int16_t dyn_type; /* rule type */
|
u_int16_t dyn_type; /* rule type */
|
||||||
u_int16_t count; /* refcount */
|
u_int16_t count; /* refcount */
|
||||||
|
#if 0 /* passed up with 'rule' */
|
||||||
u_int16_t rulenum; /* rule number (for userland) */
|
u_int16_t rulenum; /* rule number (for userland) */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2020,8 +2020,15 @@ flush_pipe_ptrs(struct dn_flow_set *match)
|
|||||||
|
|
||||||
if (cmd->o.opcode != O_PIPE && cmd->o.opcode != O_QUEUE)
|
if (cmd->o.opcode != O_PIPE && cmd->o.opcode != O_QUEUE)
|
||||||
continue;
|
continue;
|
||||||
if (match == NULL || cmd->pipe_ptr == match)
|
/*
|
||||||
cmd->pipe_ptr = NULL;
|
* XXX Use bcmp/bzero to handle pipe_ptr to overcome
|
||||||
|
* possible alignment problems on 64-bit architectures.
|
||||||
|
* This code is seldom used so we do not worry too
|
||||||
|
* much about efficiency.
|
||||||
|
*/
|
||||||
|
if (match == NULL ||
|
||||||
|
!bcmp(&cmd->pipe_ptr, &match, sizeof(match)) )
|
||||||
|
bzero(&cmd->pipe_ptr, sizeof(cmd->pipe_ptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2562,7 +2569,8 @@ ipfw_ctl(struct sockopt *sopt)
|
|||||||
for (rule = layer3_chain; rule ; rule = rule->next) {
|
for (rule = layer3_chain; rule ; rule = rule->next) {
|
||||||
int i = RULESIZE(rule);
|
int i = RULESIZE(rule);
|
||||||
bcopy(rule, bp, i);
|
bcopy(rule, bp, i);
|
||||||
((struct ip_fw *)bp)->set_disable = set_disable;
|
bcopy(&set_disable, &(bp->next_rule),
|
||||||
|
sizeof(set_disable));
|
||||||
bp = (struct ip_fw *)((char *)bp + i);
|
bp = (struct ip_fw *)((char *)bp + i);
|
||||||
}
|
}
|
||||||
if (ipfw_dyn_v) {
|
if (ipfw_dyn_v) {
|
||||||
@ -2574,21 +2582,22 @@ ipfw_ctl(struct sockopt *sopt)
|
|||||||
for ( p = ipfw_dyn_v[i] ; p != NULL ;
|
for ( p = ipfw_dyn_v[i] ; p != NULL ;
|
||||||
p = p->next, dst++ ) {
|
p = p->next, dst++ ) {
|
||||||
bcopy(p, dst, sizeof *p);
|
bcopy(p, dst, sizeof *p);
|
||||||
dst->rulenum = p->rule->rulenum;
|
bcopy(&(p->rule->rulenum), &(dst->rule),
|
||||||
|
sizeof(p->rule->rulenum));
|
||||||
/*
|
/*
|
||||||
* store a non-null value in "next".
|
* store a non-null value in "next".
|
||||||
* The userland code will interpret a
|
* The userland code will interpret a
|
||||||
* NULL here as a marker
|
* NULL here as a marker
|
||||||
* for the last dynamic rule.
|
* for the last dynamic rule.
|
||||||
*/
|
*/
|
||||||
dst->next = dst ;
|
bcopy(&dst, &dst->next, sizeof(dst));
|
||||||
last = dst ;
|
last = dst ;
|
||||||
dst->expire =
|
dst->expire =
|
||||||
TIME_LEQ(dst->expire, time_second) ?
|
TIME_LEQ(dst->expire, time_second) ?
|
||||||
0 : dst->expire - time_second ;
|
0 : dst->expire - time_second ;
|
||||||
}
|
}
|
||||||
if (last != NULL) /* mark last dynamic rule */
|
if (last != NULL) /* mark last dynamic rule */
|
||||||
last->next = NULL;
|
bzero(&last->next, sizeof(last));
|
||||||
}
|
}
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user