diff options
author | green <green@FreeBSD.org> | 2004-10-03 00:17:46 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2004-10-03 00:17:46 +0000 |
commit | a1ab5f0c7dae91ac2b8d9c2be9463083757f5fe6 (patch) | |
tree | e40a46b2deb9dd73b5b7b3f96b1f19d44079a888 /sys | |
parent | c4db706631d6435563c38ac0b9ba4acbbfddccb6 (diff) | |
download | FreeBSD-src-a1ab5f0c7dae91ac2b8d9c2be9463083757f5fe6.zip FreeBSD-src-a1ab5f0c7dae91ac2b8d9c2be9463083757f5fe6.tar.gz |
Add to IPFW the ability to do ALTQ classification/tagging.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_fw.h | 10 | ||||
-rw-r--r-- | sys/netinet/ip_fw2.c | 44 |
2 files changed, 54 insertions, 0 deletions
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index ac903f5..943b505 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -134,6 +134,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */ O_IP_DST_LOOKUP, /* arg1=table number, u32=value */ O_ANTISPOOF, /* none */ O_JAIL, /* u32 = id */ + O_ALTQ, /* u32 = altq classif. qid */ O_LAST_OPCODE /* not an opcode! */ }; @@ -251,6 +252,14 @@ typedef struct _ipfw_insn_pipe { } ipfw_insn_pipe; /* + * This is used for storing an altq queue id number. + */ +typedef struct _ipfw_insn_altq { + ipfw_insn o; + u_int32_t qid; +} ipfw_insn_altq; + +/* * This is used for limit rules. */ typedef struct _ipfw_insn_limit { @@ -293,6 +302,7 @@ typedef struct _ipfw_insn_log { * first instruction (at r->cmd) MUST BE an O_PROBE_STATE * + if a rule has a "log" option, then the first action * (at ACTION_PTR(r)) MUST be O_LOG + * + if a rule has an "altq" option, it comes after "log" * * NOTE: we use a simple linked list of rules because we never need * to delete a rule without scanning the list. We do not use diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 2d8197f..9108d7b 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -77,6 +77,7 @@ #include <netinet/tcpip.h> #include <netinet/udp.h> #include <netinet/udp_var.h> +#include <altq/if_altq.h> #ifdef IPSEC #include <netinet6/ipsec.h> @@ -553,6 +554,13 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ether_header *eh, if (l->log_left == 0) limit_reached = l->max_log; cmd += F_LEN(cmd); /* point to first action */ + if (cmd->opcode == O_ALTQ) { + ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd; + + snprintf(SNPARGS(action2, 0), "Altq %d", + altq->qid); + cmd += F_LEN(cmd); + } if (cmd->opcode == O_PROB) cmd += F_LEN(cmd); @@ -1324,6 +1332,8 @@ lookup_next_rule(struct ip_fw *me) cmd = ACTION_PTR(me); if (cmd->opcode == O_LOG) cmd += F_LEN(cmd); + if (cmd->opcode == O_ALTQ) + cmd += F_LEN(cmd); if ( cmd->opcode == O_SKIPTO ) for (rule = me->next; rule ; rule = rule->next) if (rule->rulenum >= cmd->arg1) @@ -2212,6 +2222,32 @@ check_body: (TH_RST | TH_ACK | TH_SYN)) != TH_SYN); break; + case O_ALTQ: { + struct altq_tag *at; + ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd; + + match = 1; + mtag = m_tag_get(PACKET_TAG_PF_QID, + sizeof(struct altq_tag), + M_NOWAIT); + if (mtag == NULL) { + /* + * Let the packet fall back to the + * default ALTQ. + */ + break; + } + at = (struct altq_tag *)(mtag+1); + at->qid = altq->qid; + if (hlen != 0) + at->af = AF_INET; + else + at->af = AF_LINK; + at->hdr = ip; + m_tag_prepend(m, mtag); + break; + } + case O_LOG: if (fw_verbose) ipfw_log(f, hlen, args->eh, m, oif); @@ -2275,6 +2311,9 @@ check_body: * or to the SKIPTO target ('goto again' after * having set f, cmd and l), respectively. * + * O_LOG and O_ALTQ action parameters: + * perform some action and set match = 1; + * * O_LIMIT and O_KEEP_STATE: these opcodes are * not real 'actions', and are stored right * before the 'action' part of the rule. @@ -2974,6 +3013,11 @@ check_ipfw_struct(struct ip_fw *rule, int size) goto bad_size; break; + case O_ALTQ: + if (cmdlen != F_INSN_SIZE(ipfw_insn_altq)) + goto bad_size; + break; + case O_PIPE: case O_QUEUE: if (cmdlen != F_INSN_SIZE(ipfw_insn_pipe)) |