summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r--sys/netinet/ip_output.c113
1 files changed, 53 insertions, 60 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 4ab1528..368d3c5 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -90,7 +90,6 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
#endif /*FAST_IPSEC*/
#include <netinet/ip_fw.h>
-#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
@@ -131,11 +130,12 @@ extern struct protosw inetsw[];
* inserted, so must have a NULL opt pointer.
*/
int
-ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
+ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
int flags, struct ip_moptions *imo, struct inpcb *inp)
{
struct ip *ip;
struct ifnet *ifp = NULL; /* keep compiler happy */
+ struct mbuf *m;
int hlen = sizeof (struct ip);
int len, off, error = 0;
struct sockaddr_in *dst = NULL; /* keep compiler happy */
@@ -143,13 +143,11 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
int isbroadcast, sw_csum;
struct in_addr pkt_dst;
struct route iproute;
- struct m_tag *dummytag; /* dummynet packet tag */
- struct m_tag *mtag;
- struct mbuf *m0; /* XXX */
#ifdef IPSEC
struct secpolicy *sp = NULL;
#endif
#ifdef FAST_IPSEC
+ struct m_tag *mtag;
struct secpolicy *sp = NULL;
struct tdb_ident *tdbi;
int s;
@@ -159,7 +157,42 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
args.eh = NULL;
args.rule = NULL;
- args.next_hop = ip_claim_next_hop(m);
+ args.next_hop = NULL;
+ args.divert_rule = 0; /* divert cookie */
+
+ /* Grab info from MT_TAG mbufs prepended to the chain. */
+ for (; m0 && m0->m_type == MT_TAG; m0 = m0->m_next) {
+ switch(m0->_m_tag_id) {
+ default:
+ printf("ip_output: unrecognised MT_TAG tag %d\n",
+ m0->_m_tag_id);
+ break;
+
+ case PACKET_TAG_DUMMYNET:
+ /*
+ * the packet was already tagged, so part of the
+ * processing was already done, and we need to go down.
+ * Get parameters from the header.
+ */
+ args.rule = ((struct dn_pkt *)m0)->rule;
+ opt = NULL ;
+ ro = & ( ((struct dn_pkt *)m0)->ro ) ;
+ imo = NULL ;
+ dst = ((struct dn_pkt *)m0)->dn_dst ;
+ ifp = ((struct dn_pkt *)m0)->ifp ;
+ flags = ((struct dn_pkt *)m0)->flags ;
+ break;
+
+ case PACKET_TAG_DIVERT:
+ args.divert_rule = (intptr_t)m0->m_data & 0xffff;
+ break;
+
+ case PACKET_TAG_IPFORWARD:
+ args.next_hop = (struct sockaddr_in *)m0->m_data;
+ break;
+ }
+ }
+ m = m0;
M_ASSERTPKTHDR(m);
@@ -171,34 +204,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
if (inp != NULL)
INP_LOCK_ASSERT(inp);
- /*
- * When packet comes from dummynet restore state from
- * previous processing instead of the header. Yech!
- *
- * XXX add conditional compilation?
- */
- dummytag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
- if (dummytag != NULL) {
- struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
-
- /*
- * NB: the route in the tag is known to have a
- * reference that must be free'd, but doing this
- * before the storage is reclaimed is painful due
- * to some of the contorted code in this routine.
- * So instead unlink the tag from the mbuf so it
- * doesn't get reclaimed and do the cleanup explicitly
- * below. We should be able to do this automatically
- * using a uma dtor method when m_tag's can be
- * allocated from zones.
- */
- m_tag_unlink(m, dummytag);
-
- args.rule = dt->rule;
- ro = &dt->ro;
- dst = dt->dn_dst;
- ifp = dt->ifp;
-
+ if (args.rule != NULL) { /* dummynet already saw us */
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2 ;
if (ro->ro_rt)
@@ -551,7 +557,7 @@ sendit:
dst = (struct sockaddr_in *)state.dst;
if (error) {
/* mbuf is already reclaimed in ipsec4_output. */
- m = NULL;
+ m0 = NULL;
switch (error) {
case EHOSTUNREACH:
case ENETUNREACH:
@@ -791,13 +797,11 @@ spd_done:
}
#ifdef IPDIVERT
if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
- struct mbuf *clone;
+ struct mbuf *clone = NULL;
/* Clone packet if we're doing a 'tee' */
if ((off & IP_FW_PORT_TEE_FLAG) != 0)
- clone = divert_clone(m);
- else
- clone = NULL;
+ clone = m_dup(m, M_DONTWAIT);
/*
* XXX
@@ -814,7 +818,7 @@ spd_done:
ip->ip_off = htons(ip->ip_off);
/* Deliver packet to divert input routine */
- divert_packet(m, 0);
+ divert_packet(m, 0, off & 0xffff, args.divert_rule);
/* If 'tee', continue with original packet */
if (clone != NULL) {
@@ -892,31 +896,26 @@ spd_done:
break;
}
if (ia) { /* tell ip_input "dont filter" */
- mtag = m_tag_get(PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in *),
- M_NOWAIT);
- if (mtag == NULL) {
- /* XXX statistic */
- error = ENOBUFS; /* XXX */
- goto bad;
- }
- *(struct sockaddr_in **)(mtag+1) =
- args.next_hop;
- m_tag_prepend(m, mtag);
+ 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;
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = ifunit("lo0");
if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
m->m_pkthdr.csum_flags |=
CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m->m_pkthdr.csum_data = 0xffff;
+ m0->m_pkthdr.csum_data = 0xffff;
}
m->m_pkthdr.csum_flags |=
CSUM_IP_CHECKED | CSUM_IP_VALID;
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
- /* XXX netisr_queue(NETISR_IP, m); */
- ip_input(m);
+ ip_input((struct mbuf *)&tag);
goto done;
}
/*
@@ -1073,12 +1072,6 @@ done:
RTFREE(ro->ro_rt);
ro->ro_rt = NULL;
}
- if (dummytag) {
- struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
- if (dt->ro.ro_rt)
- RTFREE(dt->ro.ro_rt);
- m_tag_free(dummytag);
- }
#ifdef IPSEC
if (sp != NULL) {
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
OpenPOWER on IntegriCloud