Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148454581
D8877.id23174.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D8877.id23174.diff
View Options
Index: sys/netinet/ip_output.c
===================================================================
--- sys/netinet/ip_output.c
+++ sys/netinet/ip_output.c
@@ -108,7 +108,6 @@
ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp,
struct sockaddr_in *dst, int *fibnum, int *error)
{
- struct m_tag *fwd_tag = NULL;
struct mbuf *m;
struct in_addr odst;
struct ip *ip;
@@ -182,13 +181,9 @@
return 1; /* Finished */
}
/* Or forward to some other address? */
- if ((m->m_flags & M_IP_NEXTHOP) &&
- ((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) {
- bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
+ if (IP_HAS_NEXTHOP(m) && !ip_get_fwdtag(m, dst, NULL)) {
m->m_flags |= M_SKIP_FIREWALL;
- m->m_flags &= ~M_IP_NEXTHOP;
- m_tag_delete(m, fwd_tag);
-
+ ip_flush_fwdtag(m);
return -1; /* Reloop for CHANGE of dst */
}
@@ -1415,3 +1410,82 @@
if_simloop(ifp, copym, AF_INET, 0);
}
}
+
+int
+ip_set_fwdtag(struct mbuf *m, struct sockaddr_in *dst, u_short ifidx)
+{
+ struct sockaddr_in *sa;
+ struct m_tag *fwd_tag;
+
+ (void)ifidx; /* XXX: store after dst, or make struct? */
+
+ KASSERT(dst != NULL, ("%s: !dst", __func__));
+ KASSERT(dst->sa_family == AF_INET, ("%s: !AF_INET", __func__));
+
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag != NULL) {
+ KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family ==
+ AF_INET, ("%s: !AF_INET", __func__));
+
+ m_tag_unlink(m, fwd_tag);
+ } else {
+ fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, sizeof(*dst),
+ M_NOWAIT);
+ if (fwd_tag == NULL) {
+ return (ENOBUFS);
+ }
+ }
+
+ sa = (struct sockaddr_in *)(fwd_tag+1);
+
+ bcopy(dst, sa, sizeof(*dst));
+ m->m_flags |= M_IP_NEXTHOP;
+
+ if (in_localip(sa->sin_addr))
+ m->m_flags |= M_FASTFWD_OURS;
+ else
+ m->m_flags &= ~M_FASTFWD_OURS;
+
+ m_tag_prepend(m, fwd_tag);
+
+ return (0);
+}
+
+int
+ip_get_fwdtag(struct mbuf *m, struct sockaddr_in *dst, u_short *ifidx)
+{
+ struct m_tag *fwd_tag;
+
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag == NULL) {
+ return (ENOENT);
+ }
+
+ KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family == AF_INET,
+ ("%s: !AF_INET", __func__));
+
+ if (dst != NULL) {
+ bcopy((fwd_tag+1), dst, sizeof(*dst));
+ }
+
+ if (ifidx != NULL) {
+ /* XXX ifidx is not yet defined */
+ }
+
+ return (0);
+}
+
+void
+ip_flush_fwdtag(struct mbuf *m)
+{
+ struct m_tag *fwd_tag;
+
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag != NULL) {
+ KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family ==
+ AF_INET, ("%s: !AF_INET", __func__));
+
+ m->m_flags &= ~(M_IP_NEXTHOP | M_FASTFWD_OURS);
+ m_tag_delete(m, fwd_tag);
+ }
+}
Index: sys/netinet/ip_var.h
===================================================================
--- sys/netinet/ip_var.h
+++ sys/netinet/ip_var.h
@@ -236,6 +236,11 @@
extern void (*ip_rsvp_force_done)(struct socket *);
extern int (*rsvp_input_p)(struct mbuf **, int *, int);
+#define IP_HAS_NEXTHOP(m) ((m)->m_flags & M_IP_NEXTHOP)
+int ip_set_fwdtag(struct mbuf *, struct sockaddr_in *, u_short);
+int ip_get_fwdtag(struct mbuf *, struct sockaddr_in *, u_short *);
+void ip_flush_fwdtag(struct mbuf *);
+
VNET_DECLARE(struct pfil_head, inet_pfil_hook); /* packet filter hooks */
#define V_inet_pfil_hook VNET(inet_pfil_hook)
Index: sys/netinet/tcp_input.c
===================================================================
--- sys/netinet/tcp_input.c
+++ sys/netinet/tcp_input.c
@@ -605,6 +605,7 @@
int off0;
int optlen = 0;
#ifdef INET
+ struct sockaddr_in next_hop;
int len;
#endif
int tlen = 0, off;
@@ -615,8 +616,8 @@
uint8_t sig_checked = 0;
#endif
uint8_t iptos;
- struct m_tag *fwd_tag = NULL;
#ifdef INET6
+ struct sockaddr_in6 next_hop6;
struct ip6_hdr *ip6 = NULL;
int isipv6;
#else
@@ -810,22 +811,6 @@
} else
ti_locked = TI_UNLOCKED;
- /*
- * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
- */
- if (
-#ifdef INET6
- (isipv6 && (m->m_flags & M_IP6_NEXTHOP))
-#ifdef INET
- || (!isipv6 && (m->m_flags & M_IP_NEXTHOP))
-#endif
-#endif
-#if defined(INET) && !defined(INET6)
- (m->m_flags & M_IP_NEXTHOP)
-#endif
- )
- fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
-
findpcb:
#ifdef INVARIANTS
if (ti_locked == TI_RLOCKED) {
@@ -835,10 +820,11 @@
}
#endif
#ifdef INET6
- if (isipv6 && fwd_tag != NULL) {
- struct sockaddr_in6 *next_hop6;
-
- next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
+ /*
+ * Grab info from IP forward tag prepended to the chain.
+ */
+ if (isipv6 && IP6_HAS_NEXTHOP(m) &&
+ !ip6_get_fwdtag(m, &next_hop6, NULL)) {
/*
* Transparently forwarded. Pretend to be the destination.
* Already got one like this?
@@ -853,11 +839,13 @@
* any hardware-generated hash is ignored.
*/
inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src,
- th->th_sport, &next_hop6->sin6_addr,
- next_hop6->sin6_port ? ntohs(next_hop6->sin6_port) :
+ th->th_sport, &next_hop6.sin6_addr,
+ next_hop6.sin6_port ? ntohs(next_hop6.sin6_port) :
th->th_dport, INPLOOKUP_WILDCARD |
INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif);
}
+ /* Remove the tag from the packet. We don't need it anymore. */
+ ip6_flush_fwdtag(m);
} else if (isipv6) {
inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
th->th_sport, &ip6->ip6_dst, th->th_dport,
@@ -869,10 +857,10 @@
else
#endif
#ifdef INET
- if (fwd_tag != NULL) {
- struct sockaddr_in *next_hop;
-
- next_hop = (struct sockaddr_in *)(fwd_tag+1);
+ /*
+ * Grab info from IP forward tag prepended to the chain.
+ */
+ if (IP_HAS_NEXTHOP(m) && !ip_get_fwdtag(m, &next_hop, NULL)) {
/*
* Transparently forwarded. Pretend to be the destination.
* already got one like this?
@@ -887,11 +875,13 @@
* any hardware-generated hash is ignored.
*/
inp = in_pcblookup(&V_tcbinfo, ip->ip_src,
- th->th_sport, next_hop->sin_addr,
- next_hop->sin_port ? ntohs(next_hop->sin_port) :
+ th->th_sport, next_hop.sin_addr,
+ next_hop.sin_port ? ntohs(next_hop.sin_port) :
th->th_dport, INPLOOKUP_WILDCARD |
INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif);
}
+ /* Remove the tag from the packet. We don't need it anymore. */
+ ip_flush_fwdtag(m);
} else
inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
th->th_sport, ip->ip_dst, th->th_dport,
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -407,7 +407,7 @@
struct ip save_ip;
struct sockaddr_in udp_in;
struct mbuf *m;
- struct m_tag *fwd_tag;
+ struct sockaddr_in next_hop;
int cscov_partial, iphlen;
m = *mp;
@@ -647,14 +647,9 @@
*/
/*
- * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
+ * Grab info from IP forward tag prepended to the chain.
*/
- if ((m->m_flags & M_IP_NEXTHOP) &&
- (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
- struct sockaddr_in *next_hop;
-
- next_hop = (struct sockaddr_in *)(fwd_tag + 1);
-
+ if (IP_HAS_NEXTHOP(m) && !ip_get_fwdtag(m, &next_hop, NULL)) {
/*
* Transparently forwarded. Pretend to be the destination.
* Already got one like this?
@@ -668,14 +663,13 @@
* any hardware-generated hash is ignored.
*/
inp = in_pcblookup(pcbinfo, ip->ip_src,
- uh->uh_sport, next_hop->sin_addr,
- next_hop->sin_port ? htons(next_hop->sin_port) :
+ uh->uh_sport, next_hop.sin_addr,
+ next_hop.sin_port ? htons(next_hop.sin_port) :
uh->uh_dport, INPLOOKUP_WILDCARD |
INPLOOKUP_RLOCKPCB, ifp);
}
/* Remove the tag from the packet. We don't need it anymore. */
- m_tag_delete(m, fwd_tag);
- m->m_flags &= ~M_IP_NEXTHOP;
+ ip_flush_fwdtag(m);
} else
inp = in_pcblookup_mbuf(pcbinfo, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -322,8 +322,8 @@
int hdrsplit = 0;
int sw_csum, tso;
int needfiblookup;
+ int has_fwd_tag = 0;
uint32_t fibnum;
- struct m_tag *fwd_tag = NULL;
uint32_t id;
if (inp != NULL) {
@@ -547,7 +547,7 @@
ro->ro_dst.sin6_family = AF_INET6;
RT_VALIDATE((struct route *)ro, &inp->inp_rt_cookie, fibnum);
}
- if (ro->ro_rt && fwd_tag == NULL && (ro->ro_rt->rt_flags & RTF_UP) &&
+ if (ro->ro_rt && !has_fwd_tag && (ro->ro_rt->rt_flags & RTF_UP) &&
ro->ro_dst.sin6_family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)) {
rt = ro->ro_rt;
@@ -556,7 +556,7 @@
if (ro->ro_lle)
LLE_FREE(ro->ro_lle); /* zeros ro_lle */
ro->ro_lle = NULL;
- if (fwd_tag == NULL) {
+ if (!has_fwd_tag) {
bzero(&dst_sa, sizeof(dst_sa));
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
@@ -860,13 +860,11 @@
goto done;
}
/* Or forward to some other address? */
- if ((m->m_flags & M_IP6_NEXTHOP) &&
- (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
+ if (IP6_HAS_NEXTHOP(m) && !ip6_get_fwdtag(m, &dst_sa, NULL)) {
dst = (struct sockaddr_in6 *)&ro->ro_dst;
- bcopy((fwd_tag+1), &dst_sa, sizeof(struct sockaddr_in6));
m->m_flags |= M_SKIP_FIREWALL;
- m->m_flags &= ~M_IP6_NEXTHOP;
- m_tag_delete(m, fwd_tag);
+ ip6_flush_fwdtag(m);
+ has_fwd_tag = 1;
goto again;
}
@@ -3096,3 +3094,95 @@
return len;
#undef elen
}
+
+int
+ip6_set_fwdtag(struct mbuf *m, struct sockaddr_in6 *dst, u_short ifidx)
+{
+ struct sockaddr_in6 *sa6;
+ struct m_tag *fwd_tag;
+ int error;
+
+ (void)ifidx; /* XXX: store after dst, or make struct? */
+
+ KASSERT(dst != NULL, ("%s: !dst", __func__));
+ KASSERT(dst->sa_family == AF_INET6, ("%s: !AF_INET6", __func__));
+
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag != NULL) {
+ KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family ==
+ AF_INET6, ("%s: !AF_INET6", __func__));
+
+ m_tag_unlink(m, fwd_tag);
+ } else {
+ fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, sizeof(*dst),
+ M_NOWAIT);
+ if (fwd_tag == NULL) {
+ return (ENOBUFS);
+ }
+ }
+
+ sa6 = (struct sockaddr_in6 *)(fwd_tag+1);
+
+ bcopy(dst, sa6, sizeof(*dst));
+
+ /*
+ * If nh6 address is link-local we should convert
+ * it to kernel internal form before doing any
+ * comparisons.
+ */
+ error = sa6_embedscope(sa6, V_ip6_use_defzone);
+ if (error != 0) {
+ m_tag_free(fwd_tag);
+ return (error);
+ }
+
+ if (in6_localip(&sa6->sin6_addr))
+ m->m_flags |= M_FASTFWD_OURS;
+ else
+ m->m_flags &= ~M_FASTFWD_OURS;
+
+ m->m_flags |= M_IP6_NEXTHOP;
+
+ m_tag_prepend(m, fwd_tag);
+
+ return (0);
+}
+
+int
+ip6_get_fwdtag(struct mbuf *m, struct sockaddr_in6 *dst, u_short *ifidx)
+{
+ struct m_tag *fwd_tag;
+
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag == NULL) {
+ return (ENOENT);
+ }
+
+ KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family == AF_INET6,
+ ("%s: !AF_INET6", __func__));
+
+ if (dst != NULL) {
+ bcopy((fwd_tag+1), dst, sizeof(*dst));
+ }
+
+ if (ifidx != NULL) {
+ /* XXX ifidx is not yet defined */
+ }
+
+ return (0);
+}
+
+void
+ip6_flush_fwdtag(struct mbuf *m)
+{
+ struct m_tag *fwd_tag;
+
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag != NULL) {
+ KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family ==
+ AF_INET6, ("%s: !AF_INET6", __func__));
+
+ m->m_flags &= ~(M_IP6_NEXTHOP | M_FASTFWD_OURS);
+ m_tag_delete(m, fwd_tag);
+ }
+}
Index: sys/netinet6/ip6_var.h
===================================================================
--- sys/netinet6/ip6_var.h
+++ sys/netinet6/ip6_var.h
@@ -397,6 +397,11 @@
int ip6_fragment(struct ifnet *, struct mbuf *, int, u_char, int,
uint32_t);
+#define IP6_HAS_NEXTHOP(m) ((m)->m_flags & M_IP6_NEXTHOP)
+int ip6_set_fwdtag(struct mbuf *, struct sockaddr_in6 *, u_short);
+int ip6_get_fwdtag(struct mbuf *, struct sockaddr_in6 *, u_short *);
+void ip6_flush_fwdtag(struct mbuf *);
+
int route6_input(struct mbuf **, int *, int);
void frag6_init(void);
Index: sys/netinet6/udp6_usrreq.c
===================================================================
--- sys/netinet6/udp6_usrreq.c
+++ sys/netinet6/udp6_usrreq.c
@@ -204,7 +204,7 @@
int cscov_partial;
int plen, ulen;
struct sockaddr_in6 fromsa;
- struct m_tag *fwd_tag;
+ struct sockaddr_in6 next_hop6;
uint16_t uh_sum;
uint8_t nxt;
@@ -413,14 +413,9 @@
*/
/*
- * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
+ * Grab info from IP forward tag prepended to the chain.
*/
- if ((m->m_flags & M_IP6_NEXTHOP) &&
- (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
- struct sockaddr_in6 *next_hop6;
-
- next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
-
+ if (IP6_HAS_NEXTHOP(m) && !ip6_get_fwdtag(m, &next_hop6, NULL)) {
/*
* Transparently forwarded. Pretend to be the destination.
* Already got one like this?
@@ -435,14 +430,13 @@
* any hardware-generated hash is ignored.
*/
inp = in6_pcblookup(pcbinfo, &ip6->ip6_src,
- uh->uh_sport, &next_hop6->sin6_addr,
- next_hop6->sin6_port ? htons(next_hop6->sin6_port) :
+ uh->uh_sport, &next_hop6.sin6_addr,
+ next_hop6.sin6_port ? htons(next_hop6.sin6_port) :
uh->uh_dport, INPLOOKUP_WILDCARD |
INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif);
}
/* Remove the tag from the packet. We don't need it anymore. */
- m_tag_delete(m, fwd_tag);
- m->m_flags &= ~M_IP6_NEXTHOP;
+ ip6_flush_fwdtag(m);
} else
inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src,
uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
Index: sys/netpfil/ipfw/ip_fw_pfil.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_pfil.c
+++ sys/netpfil/ipfw/ip_fw_pfil.c
@@ -165,66 +165,25 @@
ret = EACCES;
#else
{
- struct m_tag *fwd_tag;
- size_t len;
-
KASSERT(args.next_hop == NULL || args.next_hop6 == NULL,
("%s: both next_hop=%p and next_hop6=%p not NULL", __func__,
args.next_hop, args.next_hop6));
#ifdef INET6
- if (args.next_hop6 != NULL)
- len = sizeof(struct sockaddr_in6);
-#endif
-#ifdef INET
- if (args.next_hop != NULL)
- len = sizeof(struct sockaddr_in);
-#endif
-
- /* Incoming packets should not be tagged so we do not
- * m_tag_find. Outgoing packets may be tagged, so we
- * reuse the tag if present.
- */
- fwd_tag = (dir == DIR_IN) ? NULL :
- m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL);
- if (fwd_tag != NULL) {
- m_tag_unlink(*m0, fwd_tag);
- } else {
- fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, len,
- M_NOWAIT);
- if (fwd_tag == NULL) {
- ret = EACCES;
- break; /* i.e. drop */
- }
- }
-#ifdef INET6
if (args.next_hop6 != NULL) {
- struct sockaddr_in6 *sa6;
-
- sa6 = (struct sockaddr_in6 *)(fwd_tag + 1);
- bcopy(args.next_hop6, sa6, len);
- /*
- * If nh6 address is link-local we should convert
- * it to kernel internal form before doing any
- * comparisons.
- */
- if (sa6_embedscope(sa6, V_ip6_use_defzone) != 0) {
+ if (ip6_set_fwdtag(*m0, args.next_hop6, 0)) {
ret = EACCES;
break;
}
- if (in6_localip(&sa6->sin6_addr))
- (*m0)->m_flags |= M_FASTFWD_OURS;
- (*m0)->m_flags |= M_IP6_NEXTHOP;
}
#endif
#ifdef INET
if (args.next_hop != NULL) {
- bcopy(args.next_hop, (fwd_tag+1), len);
- if (in_localip(args.next_hop->sin_addr))
- (*m0)->m_flags |= M_FASTFWD_OURS;
- (*m0)->m_flags |= M_IP_NEXTHOP;
+ if (ip_set_fwdtag(*m0, args.next_hop, 0)) {
+ ret = EACCES;
+ break;
+ }
}
#endif
- m_tag_prepend(*m0, fwd_tag);
}
#endif /* INET || INET6 */
break;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 19, 12:16 AM (9 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29862933
Default Alt Text
D8877.id23174.diff (15 KB)
Attached To
Mode
D8877: pf|ipfw|netinet6?: shared IP forwarding
Attached
Detach File
Event Timeline
Log In to Comment