int match = 0;
struct sk_buff *skb = ((struct mbuf *)inp)->m_skb;
- printf("%s opcode %d arg %d oif %p src 0x%x:%d dst 0x%x:%d\n", __FUNCTION__,
- insn->o.opcode, insn->d[0], oif,
- ntohl(src_ip.s_addr), ntohs(src_port),
- ntohl(dst_ip.s_addr), ntohs(dst_port)
- );
- if (insn->o.opcode == O_JAIL) {
-#ifdef IPFW_PLANETLAB
- match = (skb->skb_tag == insn->d[0]);
- printf("JAIL compiled for planetlab state %d xid %d want %d result %d\n",
- skb->skb_tag, insn->d[0], match);
-
-#endif
- return match;
- }
-
if (*ugid_lookupp == 0) { /* actively lookup and copy in cache */
/* returns null if any element of the chain up to file is null.
if (insn->o.opcode == O_UID)
match = (ugp->fw_uid == (uid_t)insn->d[0]);
+ else if (insn->o.opcode == O_JAIL)
+ match = (ugp->fw_groups[1] == (uid_t)insn->d[0]);
+ else if (insn->o.opcode == O_GID)
+ match = (ugp->fw_groups[0] == (uid_t)insn->d[0]);
+
return match;
#else /* FreeBSD */
/* end of ipv6 variables */
int is_ipv4 = 0;
+ int done = 0; /* flag for actions match */
+
if (m->m_flags & M_SKIP_FIREWALL)
return (IP_FW_PASS); /* accept */
uint32_t tablearg = 0;
int l, cmdlen, skip_or; /* skip rest of OR block */
-again:
+/* again: */
if (set_disable & (1 << f->set) )
continue;
* the target rule.
*/
-check_body:
+/* check_body: */
cmdlen = F_LEN(cmd);
/*
* An OR block (insn_1 || .. || insn_n) has the
* Exceptions:
* O_COUNT and O_SKIPTO actions:
* instead of terminating, we jump to the next rule
- * ('goto next_rule', equivalent to a 'break 2'),
- * or to the SKIPTO target ('goto again' after
+ * ('break' after setting match and l)
+ * or to the SKIPTO target ('break' after
* having set f, cmd and l), respectively.
*
* O_TAG, O_LOG and O_ALTQ action parameters:
* O_PROBE_STATE and O_CHECK_STATE: these opcodes
* cause a lookup of the state table, and a jump
* to the 'action' part of the parent rule
- * ('goto check_body') if an entry is found, or
+ * if an entry is found, or
* (CHECK_STATE only) a jump to the next rule if
* the entry is not found ('goto next_rule').
* The result of the lookup is cached to make
* further instances of these opcodes are
* effectively NOPs.
+ * The jump to the next rule is done by a break
+ * after zeroing the cmdlen value and setting
+ * match.
*/
case O_LIMIT:
case O_KEEP_STATE:
if (install_state(f,
(ipfw_insn_limit *)cmd, args, tablearg)) {
retval = IP_FW_DENY;
- goto done; /* error/limit violation */
+ /* was goto done; */ /* error/limit violation */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
}
match = 1;
break;
cmd = ACTION_PTR(f);
l = f->cmd_len - f->act_ofs;
IPFW_DYN_UNLOCK();
- goto check_body;
+ /* previously was goto check_body; */
+ cmdlen = 0; /* make null for() changes */
+ match = 1; /* do not break to the external loop */
+ break;
}
/*
* Dynamic entry not found. If CHECK_STATE,
* ignore and continue with next opcode.
*/
if (cmd->opcode == O_CHECK_STATE)
- goto next_rule;
+ l = 0; /* was goto next_rule; */
match = 1;
break;
case O_ACCEPT:
retval = 0; /* accept */
- goto done;
+ /* was goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
case O_PIPE:
case O_QUEUE:
else
args->cookie = cmd->arg1;
retval = IP_FW_DUMMYNET;
- goto done;
+ /* was goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
#if 0
case O_DIVERT:
m_tag_prepend(m, mtag);
retval = (cmd->opcode == O_DIVERT) ?
IP_FW_DIVERT : IP_FW_TEE;
- goto done;
+ /* was goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
}
#endif
f->pcnt++; /* update stats */
f->bcnt += pktlen;
f->timestamp = time_uptime;
- if (cmd->opcode == O_COUNT)
- goto next_rule;
+ if (cmd->opcode == O_COUNT) {
+ /* was goto next_rule; */
+ l = 0; /* exit the inner loop */
+ match = 1; /* do not break the loop */
+ break;
+ }
/* handle skipto */
if (cmd->arg1 == IP_FW_TABLEARG) {
f = lookup_next_rule(f, tablearg);
lookup_next_rule(f, 0);
f = f->next_rule;
}
- goto again;
+ /* previously was "goto again;"
+ * We emulate by re-entering the inner loop
+ * with the correct f, l and cmd.
+ * First, skip over disabled rules.
+ * Should at least match the default rule,
+ * but try to be robust.
+ */
+ while (f && (set_disable & (1 << f->set)))
+ f = f->next;
+ /* prepare to re-enter the inner loop. */
+ if (f) { /* better safe than sorry */
+ l = f->cmd_len;
+ cmd = f->cmd;
+ } else {
+ l = 0; /* this will break the inner loop */
+ }
+ cmdlen = 0; /* reset loop condition */
+ skip_or = 0;
+ match = 1; /* do not break the loop */
+ break;
case O_REJECT:
/*
#endif
case O_DENY:
retval = IP_FW_DENY;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
case O_FORWARD_IP: {
struct sockaddr_in *sa;
}
}
retval = IP_FW_PASS;
- }
- goto done;
+ }
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
case O_NETGRAPH:
case O_NGTEE:
args->cookie = cmd->arg1;
retval = (cmd->opcode == O_NETGRAPH) ?
IP_FW_NETGRAPH : IP_FW_NGTEE;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
#if 0
case O_SETFIB:
f->timestamp = time_uptime;
M_SETFIB(m, cmd->arg1);
args->f_id.fib = cmd->arg1;
- goto next_rule;
+ /* was goto next_rule; */
+ l = 0;
+ match = 1;
+ break;
case O_NAT: {
struct cfg_nat *t;
LOOKUP_NAT(layer3_chain, nat_id, t);
if (t == NULL) {
retval = IP_FW_DENY;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
}
if (cmd->arg1 != IP_FW_TABLEARG)
((ipfw_insn_nat *)cmd)->nat = t;
retval = ipfw_nat_ptr(args, t, m);
} else
retval = IP_FW_DENY;
- goto done;
+ /* goto done; */
+ l = 0; /* break the inner loop */
+ done = 1; /* break the external loop */
+ break;
}
#endif
} /* end of inner for, scan opcodes */
-next_rule:; /* try next rule */
+ if (done)
+ break;
+/* next_rule:; */ /* try next rule */
} /* end of outer for, scan rules */
+
+ if (done) {
+ /* Update statistics */
+ f->pcnt++;
+ f->bcnt += pktlen;
+ f->timestamp = time_uptime;
+ IPFW_RUNLOCK(chain);
+ return (retval);
+ }
+
printf("ipfw: ouch!, skip past end of rules, denying packet\n");
IPFW_RUNLOCK(chain);
return (IP_FW_DENY);
-done:
- /* Update statistics */
- f->pcnt++;
- f->bcnt += pktlen;
- f->timestamp = time_uptime;
- IPFW_RUNLOCK(chain);
- return (retval);
-
pullup_failed:
if (fw_verbose)
printf("ipfw: pullup failed\n");
}
/*
- * Copy the static and dynamic rules to the supplied buffer
+ * Copy the static rules to the supplied buffer
* and return the amount of space actually used.
*/
static size_t
int i;
time_t boot_seconds;
- boot_seconds = boottime.tv_sec;
+ boot_seconds = boottime.tv_sec;
+
/* XXX this can take a long time and locking will block packet flow */
IPFW_RLOCK(chain);
for (rule = chain->rules; rule ; rule = rule->next) {
}
}
IPFW_RUNLOCK(chain);
+
+ return (bp - (char *)buf);
+}
+
+/*
+ * Copy the dynamic rules to the supplied buffer
+ * and return the amount of space actually used.
+ * XXX marta if we allocate X and rules grows
+ * we check for size limit while copying rules into the buffer
+ */
+static size_t
+ipfw_getdynrules(struct ip_fw_chain *chain, void *buf, size_t space)
+{
+ char *bp = buf;
+ char *ep = bp + space;
+ int i;
+ time_t boot_seconds;
+
+ printf("dynrules requested\n");
+ boot_seconds = boottime.tv_sec;
+
if (ipfw_dyn_v) {
ipfw_dyn_rule *p, *last = NULL;
TIME_LEQ(dst->expire, time_uptime) ?
0 : dst->expire - time_uptime ;
bp += sizeof(ipfw_dyn_rule);
+ } else {
+ p = NULL; /* break the loop */
+ i = curr_dyn_buckets;
}
}
IPFW_DYN_UNLOCK();
if (last != NULL) /* mark last dynamic rule */
bzero(&last->next, sizeof(last));
}
+
return (bp - (char *)buf);
}
switch (sopt->sopt_name) {
case IP_FW_GET:
/*
- * pass up a copy of the current rules. Static rules
- * come first (the last of which has number IPFW_DEFAULT_RULE),
- * followed by a possibly empty list of dynamic rule.
- * The last dynamic rule has NULL in the "next" field.
+ * pass up a copy of the current static rules.
+ * The last static rule has number IPFW_DEFAULT_RULE.
*
* Note that the calculated size is used to bound the
* amount of data returned to the user. The rule set may
* data in which case we'll just return what fits.
*/
size = static_len; /* size of static rules */
- if (ipfw_dyn_v) /* add size of dyn.rules */
- size += (dyn_count * sizeof(ipfw_dyn_rule));
/*
* XXX todo: if the user passes a short length just to know
free(buf, M_TEMP);
break;
+ case IP_FW_DYN_GET:
+ /*
+ * pass up a copy of the current dynamic rules.
+ * The last dynamic rule has NULL in the "next" field.
+ */
+ /* if (!ipfw_dyn_v) XXX check for empty set ? */
+ size = (dyn_count * sizeof(ipfw_dyn_rule)); /* size of dyn. rules */
+
+ buf = malloc(size, M_TEMP, M_WAITOK);
+ error = sooptcopyout(sopt, buf,
+ ipfw_getdynrules(&layer3_chain, buf, size));
+ free(buf, M_TEMP);
+ break;
+
case IP_FW_FLUSH:
/*
* Normally we cannot release the lock on each iteration.