summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2004-10-03 00:17:46 +0000
committergreen <green@FreeBSD.org>2004-10-03 00:17:46 +0000
commita1ab5f0c7dae91ac2b8d9c2be9463083757f5fe6 (patch)
treee40a46b2deb9dd73b5b7b3f96b1f19d44079a888 /sys/netinet
parentc4db706631d6435563c38ac0b9ba4acbbfddccb6 (diff)
downloadFreeBSD-src-a1ab5f0c7dae91ac2b8d9c2be9463083757f5fe6.zip
FreeBSD-src-a1ab5f0c7dae91ac2b8d9c2be9463083757f5fe6.tar.gz
Add to IPFW the ability to do ALTQ classification/tagging.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_fw.h10
-rw-r--r--sys/netinet/ip_fw2.c44
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))
OpenPOWER on IntegriCloud