summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2004-02-13 19:14:16 +0000
committermlaier <mlaier@FreeBSD.org>2004-02-13 19:14:16 +0000
commitda4d773b129fb1339d7b5fc23b93388b18952d3b (patch)
tree75fdee3c73dd1369e60e6348343749bdf159313a /sys/netinet/ip_input.c
parent09ad0862e6acad72dd0217846a1c16d5bea5c454 (diff)
downloadFreeBSD-src-da4d773b129fb1339d7b5fc23b93388b18952d3b.zip
FreeBSD-src-da4d773b129fb1339d7b5fc23b93388b18952d3b.tar.gz
This set of changes eliminates the use of MT_TAG "pseudo mbufs", replacing
them mostly with packet tags (one case is handled by using an mbuf flag since the linkage between "caller" and "callee" is direct and there's no need to incur the overhead of a packet tag). This is (mostly) work from: sam Silence from: -arch Approved by: bms(mentor), sam, rwatson
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c174
1 files changed, 56 insertions, 118 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 0900202..3156b85 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -78,6 +78,7 @@
#include <sys/socketvar.h>
#include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
#ifdef IPSEC
@@ -239,8 +240,7 @@ static int ip_dooptions(struct mbuf *m, int,
static void ip_forward(struct mbuf *m, int srcrt,
struct sockaddr_in *next_hop);
static void ip_freef(struct ipqhead *, struct ipq *);
-static struct mbuf *ip_reass(struct mbuf *, struct ipqhead *,
- struct ipq *, u_int32_t *, u_int16_t *);
+static struct mbuf *ip_reass(struct mbuf *, struct ipqhead *, struct ipq *);
/*
* IP initialization: fill in IP protocol switch table.
@@ -300,17 +300,18 @@ ip_input(struct mbuf *m)
struct in_ifaddr *ia = NULL;
struct ifaddr *ifa;
int i, checkif, hlen = 0;
- int ours = 0;
u_short sum;
struct in_addr pkt_dst;
- u_int32_t divert_info = 0; /* packet divert/tee info */
+ struct m_tag *mtag;
+#ifdef IPDIVERT
+ u_int32_t divert_info; /* packet divert/tee info */
+#endif
struct ip_fw_args args;
int dchg = 0; /* dest changed after fw */
#ifdef PFIL_HOOKS
struct in_addr odst; /* original dst address */
#endif
#ifdef FAST_IPSEC
- struct m_tag *mtag;
struct tdb_ident *tdbi;
struct secpolicy *sp;
int s, error;
@@ -318,57 +319,16 @@ ip_input(struct mbuf *m)
args.eh = NULL;
args.oif = NULL;
- args.rule = NULL;
- args.divert_rule = 0; /* divert cookie */
- args.next_hop = NULL;
-
- /*
- * Grab info from MT_TAG mbufs prepended to the chain.
- *
- * XXX: This is ugly. These pseudo mbuf prepend tags should really
- * be real m_tags. Before these have always been allocated on the
- * callers stack, so we didn't have to free them. Now with
- * ip_fastforward they are true mbufs and we have to free them
- * otherwise we have a leak. Must rewrite ipfw to use m_tags.
- */
- for (; m && m->m_type == MT_TAG;) {
- struct mbuf *m0;
-
- switch(m->_m_tag_id) {
- default:
- printf("ip_input: unrecognised MT_TAG tag %d\n",
- m->_m_tag_id);
- break;
-
- case PACKET_TAG_DUMMYNET:
- args.rule = ((struct dn_pkt *)m)->rule;
- break;
-
- case PACKET_TAG_DIVERT:
- args.divert_rule = (intptr_t)m->m_hdr.mh_data & 0xffff;
- break;
-
- case PACKET_TAG_IPFORWARD:
- args.next_hop = (struct sockaddr_in *)m->m_hdr.mh_data;
- break;
-
- case PACKET_TAG_IPFASTFWD_OURS:
- ours = 1;
- break;
- }
-
- m0 = m;
- m = m->m_next;
- /* XXX: This is set by ip_fastforward */
- if (m0->m_nextpkt == (struct mbuf *)1)
- m_free(m0);
- }
+ args.next_hop = ip_claim_next_hop(m);
+ args.rule = ip_dn_find_rule(m);
M_ASSERTPKTHDR(m);
- if (ours) /* ip_fastforward firewall changed dest to local */
+ if (m->m_flags & M_FASTFWD_OURS) {
+ /* ip_fastforward firewall changed dest to local */
+ m->m_flags &= ~M_FASTFWD_OURS; /* just in case... */
goto ours;
-
+ }
if (args.rule) { /* dummynet already filtered us */
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
@@ -531,7 +491,6 @@ iphack:
#ifdef IPDIVERT
if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
/* Divert or tee packet */
- divert_info = i;
goto ours;
}
#endif
@@ -839,13 +798,11 @@ found:
/*
* Attempt reassembly; if it succeeds, proceed.
- * ip_reass() will return a different mbuf, and update
- * the divert info in divert_info and args.divert_rule.
+ * ip_reass() will return a different mbuf.
*/
ipstat.ips_fragments++;
m->m_pkthdr.header = ip;
- m = ip_reass(m,
- &ipq[sum], fp, &divert_info, &args.divert_rule);
+ m = ip_reass(m, &ipq[sum], fp);
IPQ_UNLOCK();
if (m == 0)
return;
@@ -855,7 +812,7 @@ found:
hlen = ip->ip_hl << 2;
#ifdef IPDIVERT
/* Restore original checksum before diverting packet */
- if (divert_info != 0) {
+ if (divert_find_info(m) != 0) {
ip->ip_len += hlen;
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
@@ -876,12 +833,15 @@ found:
/*
* Divert or tee packet to the divert protocol if required.
*/
+ divert_info = divert_find_info(m);
if (divert_info != 0) {
- struct mbuf *clone = NULL;
+ struct mbuf *clone;
/* Clone packet if we're doing a 'tee' */
if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0)
- clone = m_dup(m, M_DONTWAIT);
+ clone = divert_clone(m);
+ else
+ clone = NULL;
/* Restore packet header fields to original values */
ip->ip_len += hlen;
@@ -889,7 +849,7 @@ found:
ip->ip_off = htons(ip->ip_off);
/* Deliver packet to divert input routine */
- divert_packet(m, 1, divert_info & 0xffff, args.divert_rule);
+ divert_packet(m, 1);
ipstat.ips_delivered++;
/* If 'tee', continue with original packet */
@@ -900,12 +860,11 @@ found:
ip->ip_len += hlen;
/*
* Jump backwards to complete processing of the
- * packet. But first clear divert_info to avoid
- * entering this block again.
- * We do not need to clear args.divert_rule
- * or args.next_hop as they will not be used.
+ * packet. We do not need to clear args.next_hop
+ * as that will not be used again and the cloned packet
+ * doesn't contain a divert packet tag so we won't
+ * re-entry this block.
*/
- divert_info = 0;
goto pass;
}
#endif
@@ -968,19 +927,18 @@ DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
ipstat.ips_delivered++;
NET_PICKUP_GIANT();
if (args.next_hop && ip->ip_p == IPPROTO_TCP) {
- /* TCP needs IPFORWARD info if available */
- struct m_hdr tag;
-
- tag.mh_type = MT_TAG;
- tag.mh_flags = PACKET_TAG_IPFORWARD;
- tag.mh_data = (caddr_t)args.next_hop;
- tag.mh_next = m;
- tag.mh_nextpkt = NULL;
-
- (*inetsw[ip_protox[ip->ip_p]].pr_input)(
- (struct mbuf *)&tag, hlen);
- } else
- (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
+ /* attach next hop info for TCP */
+ mtag = m_tag_get(PACKET_TAG_IPFORWARD,
+ sizeof(struct sockaddr_in *), M_NOWAIT);
+ if (mtag == NULL) {
+ /* XXX statistic */
+ NET_DROP_GIANT();
+ goto bad;
+ }
+ *(struct sockaddr_in **)(mtag+1) = args.next_hop;
+ m_tag_prepend(m, mtag);
+ }
+ (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
NET_DROP_GIANT();
return;
bad:
@@ -999,8 +957,7 @@ bad:
*/
static struct mbuf *
-ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
- u_int32_t *divinfo, u_int16_t *divert_rule)
+ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp)
{
struct ip *ip = mtod(m, struct ip *);
register struct mbuf *p, *q, *nq;
@@ -1042,10 +999,6 @@ ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
fp->ipq_dst = ip->ip_dst;
fp->ipq_frags = m;
m->m_nextpkt = NULL;
-#ifdef IPDIVERT
- fp->ipq_div_info = 0;
- fp->ipq_div_cookie = 0;
-#endif
goto inserted;
} else {
fp->ipq_nfrags++;
@@ -1129,16 +1082,15 @@ ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
inserted:
#ifdef IPDIVERT
- /*
- * Transfer firewall instructions to the fragment structure.
- * Only trust info in the fragment at offset 0.
- */
- if (ip->ip_off == 0) {
- fp->ipq_div_info = *divinfo;
- fp->ipq_div_cookie = *divert_rule;
+ if (ip->ip_off != 0) {
+ /*
+ * Strip any divert information; only the info
+ * on the first fragment is used/kept.
+ */
+ struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
+ if (mtag)
+ m_tag_delete(m, mtag);
}
- *divinfo = 0;
- *divert_rule = 0;
#endif
/*
@@ -1204,14 +1156,6 @@ inserted:
mac_destroy_ipq(fp);
#endif
-#ifdef IPDIVERT
- /*
- * Extract firewall instructions from the fragment structure.
- */
- *divinfo = fp->ipq_div_info;
- *divert_rule = fp->ipq_div_cookie;
-#endif
-
/*
* Create header for new ip packet by
* modifying header of first packet;
@@ -1232,10 +1176,6 @@ inserted:
return (m);
dropfrag:
-#ifdef IPDIVERT
- *divinfo = 0;
- *divert_rule = 0;
-#endif
ipstat.ips_fragdropped++;
if (fp != NULL)
fp->ipq_nfrags--;
@@ -1781,6 +1721,7 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
struct in_ifaddr *ia;
int error, type = 0, code = 0;
struct mbuf *mcopy;
+ struct m_tag *mtag;
n_long dest;
struct in_addr pkt_dst;
struct ifnet *destifp;
@@ -1913,21 +1854,18 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop)
RTFREE(rt);
}
- {
- struct m_hdr tag;
-
if (next_hop) {
- /* Pass IPFORWARD info if available */
-
- tag.mh_type = MT_TAG;
- tag.mh_flags = PACKET_TAG_IPFORWARD;
- tag.mh_data = (caddr_t)next_hop;
- tag.mh_next = m;
- tag.mh_nextpkt = NULL;
- m = (struct mbuf *)&tag;
+ mtag = m_tag_get(PACKET_TAG_IPFORWARD,
+ sizeof(struct sockaddr_in *), M_NOWAIT);
+ if (mtag == NULL) {
+ /* XXX statistic */
+ m_freem(m);
+ return;
+ }
+ *(struct sockaddr_in **)(mtag+1) = next_hop;
+ m_tag_prepend(m, mtag);
}
error = ip_output(m, (struct mbuf *)0, NULL, IP_FORWARDING, 0, NULL);
- }
if (error)
ipstat.ips_cantforward++;
else {
OpenPOWER on IntegriCloud