summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/contrib/pf/net/pf.c8
-rw-r--r--sys/netinet/in_pcb.c39
-rw-r--r--sys/netinet/in_pcb.h6
-rw-r--r--sys/netinet/tcp_input.c14
-rw-r--r--sys/netinet/tcp_syncache.c8
-rw-r--r--sys/netinet/udp_usrreq.c4
-rw-r--r--sys/netinet6/in6_pcb.c29
-rw-r--r--sys/netinet6/in6_pcb.h6
-rw-r--r--sys/netinet6/udp6_usrreq.c4
9 files changed, 96 insertions, 22 deletions
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 2ce254f..135d734 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -3034,6 +3034,10 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
#ifdef INET
case AF_INET:
#ifdef __FreeBSD__
+ /*
+ * XXXRW: would be nice if we had an mbuf here so that we
+ * could use in_pcblookup_mbuf().
+ */
inp = in_pcblookup(pi, saddr->v4, sport, daddr->v4,
dport, INPLOOKUP_RLOCKPCB, NULL);
if (inp == NULL) {
@@ -3056,6 +3060,10 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
#ifdef INET6
case AF_INET6:
#ifdef __FreeBSD__
+ /*
+ * XXXRW: would be nice if we had an mbuf here so that we
+ * could use in6_pcblookup_mbuf().
+ */
inp = in6_pcblookup(pi, &saddr->v6, sport,
&daddr->v6, dport, INPLOOKUP_RLOCKPCB, NULL);
if (inp == NULL) {
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 4357b66..4aa998f 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -621,7 +621,8 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
* then pick one.
*/
int
-in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
+in_pcbconnect_mbuf(struct inpcb *inp, struct sockaddr *nam,
+ struct ucred *cred, struct mbuf *m)
{
u_short lport, fport;
in_addr_t laddr, faddr;
@@ -654,13 +655,20 @@ in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
inp->inp_laddr.s_addr = laddr;
inp->inp_faddr.s_addr = faddr;
inp->inp_fport = fport;
- in_pcbrehash(inp);
+ in_pcbrehash_mbuf(inp, m);
if (anonport)
inp->inp_flags |= INP_ANONPORT;
return (0);
}
+int
+in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
+{
+
+ return (in_pcbconnect_mbuf(inp, nam, cred, NULL));
+}
+
/*
* Do proper source address selection on an unbound socket in case
* of connect. Take jails into account as well.
@@ -1626,7 +1634,8 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
}
/*
- * Public inpcb lookup routines, accepting a 4-tuple.
+ * Public inpcb lookup routines, accepting a 4-tuple, and optionally, an mbuf
+ * from which a pre-calculated hash value may be extracted.
*/
struct inpcb *
in_pcblookup(struct inpcbinfo *pcbinfo, struct in_addr faddr, u_int fport,
@@ -1641,6 +1650,21 @@ in_pcblookup(struct inpcbinfo *pcbinfo, struct in_addr faddr, u_int fport,
return (in_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport,
lookupflags, ifp));
}
+
+struct inpcb *
+in_pcblookup_mbuf(struct inpcbinfo *pcbinfo, struct in_addr faddr,
+ u_int fport, struct in_addr laddr, u_int lport, int lookupflags,
+ struct ifnet *ifp, struct mbuf *m)
+{
+
+ KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
+ ("%s: invalid lookup flags %d", __func__, lookupflags));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
+ ("%s: LOCKPCB not set", __func__));
+
+ return (in_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport,
+ lookupflags, ifp));
+}
#endif /* INET */
/*
@@ -1707,7 +1731,7 @@ in_pcbinshash(struct inpcb *inp)
* not change after in_pcbinshash() has been called.
*/
void
-in_pcbrehash(struct inpcb *inp)
+in_pcbrehash_mbuf(struct inpcb *inp, struct mbuf *m)
{
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
struct inpcbhead *head;
@@ -1733,6 +1757,13 @@ in_pcbrehash(struct inpcb *inp)
LIST_INSERT_HEAD(head, inp, inp_hash);
}
+void
+in_pcbrehash(struct inpcb *inp)
+{
+
+ in_pcbrehash_mbuf(inp, NULL);
+}
+
/*
* Remove PCB from various lists.
*/
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index bde9e8d..809bc05 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -541,6 +541,8 @@ int in_pcb_lport(struct inpcb *, struct in_addr *, u_short *,
int in_pcbbind_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
u_short *, struct ucred *);
int in_pcbconnect(struct inpcb *, struct sockaddr *, struct ucred *);
+int in_pcbconnect_mbuf(struct inpcb *, struct sockaddr *, struct ucred *,
+ struct mbuf *);
int in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
u_short *, in_addr_t *, u_short *, struct inpcb **,
struct ucred *);
@@ -555,10 +557,14 @@ struct inpcb *
struct inpcb *
in_pcblookup(struct inpcbinfo *, struct in_addr, u_int,
struct in_addr, u_int, int, struct ifnet *);
+struct inpcb *
+ in_pcblookup_mbuf(struct inpcbinfo *, struct in_addr, u_int,
+ struct in_addr, u_int, int, struct ifnet *, struct mbuf *);
void in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr,
int, struct inpcb *(*)(struct inpcb *, int));
void in_pcbref(struct inpcb *);
void in_pcbrehash(struct inpcb *);
+void in_pcbrehash_mbuf(struct inpcb *, struct mbuf *);
int in_pcbrele(struct inpcb *);
int in_pcbrele_rlocked(struct inpcb *);
int in_pcbrele_wlocked(struct inpcb *);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 080b4da..e3e9aa6 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -791,12 +791,14 @@ findpcb:
* Transparently forwarded. Pretend to be the destination.
* already got one like this?
*/
- inp = in_pcblookup(&V_tcbinfo, ip->ip_src, th->th_sport,
+ inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, th->th_sport,
ip->ip_dst, th->th_dport, INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif);
+ m->m_pkthdr.rcvif, m);
if (!inp) {
/*
* It's new. Try to find the ambushing socket.
+ * Because we've rewritten the destination address,
+ * any hardware-generated hash is ignored.
*/
inp = in_pcblookup(&V_tcbinfo, ip->ip_src,
th->th_sport, next_hop->sin_addr,
@@ -812,19 +814,19 @@ findpcb:
{
#ifdef INET6
if (isipv6)
- inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src,
+ inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
th->th_sport, &ip6->ip6_dst, th->th_dport,
INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif);
+ m->m_pkthdr.rcvif, m);
#endif
#if defined(INET) && defined(INET6)
else
#endif
#ifdef INET
- inp = in_pcblookup(&V_tcbinfo, ip->ip_src,
+ inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
th->th_sport, ip->ip_dst, th->th_dport,
INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif);
+ m->m_pkthdr.rcvif, m);
#endif
}
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 533de4b..5125134 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -730,8 +730,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
laddr6 = inp->in6p_laddr;
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
inp->in6p_laddr = sc->sc_inc.inc6_laddr;
- if ((error = in6_pcbconnect(inp, (struct sockaddr *)&sin6,
- thread0.td_ucred)) != 0) {
+ if ((error = in6_pcbconnect_mbuf(inp, (struct sockaddr *)&sin6,
+ thread0.td_ucred, m)) != 0) {
inp->in6p_laddr = laddr6;
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: in6_pcbconnect failed "
@@ -770,8 +770,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
laddr = inp->inp_laddr;
if (inp->inp_laddr.s_addr == INADDR_ANY)
inp->inp_laddr = sc->sc_inc.inc_laddr;
- if ((error = in_pcbconnect(inp, (struct sockaddr *)&sin,
- thread0.td_ucred)) != 0) {
+ if ((error = in_pcbconnect_mbuf(inp, (struct sockaddr *)&sin,
+ thread0.td_ucred, m)) != 0) {
inp->inp_laddr = laddr;
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: in_pcbconnect failed "
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 5f2d7c3..fd864c0 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -567,9 +567,9 @@ udp_input(struct mbuf *m, int off)
/*
* Locate pcb for datagram.
*/
- inp = in_pcblookup(&V_udbinfo, ip->ip_src, uh->uh_sport,
+ inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
- ifp);
+ ifp, m);
if (inp == NULL) {
if (udp_log_in_vain) {
char buf[4*sizeof "123"];
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 17fb953..da73f21 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -364,8 +364,8 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
* then pick one.
*/
int
-in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
- struct ucred *cred)
+in6_pcbconnect_mbuf(register struct inpcb *inp, struct sockaddr *nam,
+ struct ucred *cred, struct mbuf *m)
{
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
@@ -405,11 +405,18 @@ in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
- in_pcbrehash(inp);
+ in_pcbrehash_mbuf(inp, m);
return (0);
}
+int
+in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
+{
+
+ return (in6_pcbconnect_mbuf(inp, nam, cred, NULL));
+}
+
void
in6_pcbdisconnect(struct inpcb *inp)
{
@@ -974,13 +981,27 @@ in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
}
/*
- * Public inpcb lookup routines, accepting a 4-tuple.
+ * Public inpcb lookup routines, accepting a 4-tuple, and optionally, an mbuf
+ * from which a pre-calculated hash value may be extracted.
*/
struct inpcb *
in6_pcblookup(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, u_int fport,
struct in6_addr *laddr, u_int lport, int lookupflags, struct ifnet *ifp)
{
+ KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
+ ("%s: invalid lookup flags %d", __func__, lookupflags));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
+ ("%s: LOCKPCB not set", __func__));
+ return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport,
+ lookupflags, ifp));
+}
+
+struct inpcb *
+in6_pcblookup_mbuf(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
+ u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags,
+ struct ifnet *ifp, struct mbuf *m)
+{
KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h
index bce5ee3..cf24704 100644
--- a/sys/netinet6/in6_pcb.h
+++ b/sys/netinet6/in6_pcb.h
@@ -73,6 +73,8 @@ void in6_pcbpurgeif0 __P((struct inpcbinfo *, struct ifnet *));
void in6_losing __P((struct inpcb *));
int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct ucred *));
int in6_pcbconnect __P((struct inpcb *, struct sockaddr *, struct ucred *));
+int in6_pcbconnect_mbuf __P((struct inpcb *, struct sockaddr *,
+ struct ucred *, struct mbuf *));
void in6_pcbdisconnect __P((struct inpcb *));
int in6_pcbladdr(struct inpcb *, struct sockaddr *, struct in6_addr *);
struct inpcb *
@@ -87,6 +89,10 @@ struct inpcb *
in6_pcblookup_hash_locked __P((struct inpcbinfo *, struct in6_addr *,
u_int, struct in6_addr *, u_int, int,
struct ifnet *));
+struct inpcb *
+ in6_pcblookup_mbuf __P((struct inpcbinfo *, struct in6_addr *,
+ u_int, struct in6_addr *, u_int, int,
+ struct ifnet *ifp, struct mbuf *));
void in6_pcbnotify __P((struct inpcbinfo *, struct sockaddr *,
u_int, const struct sockaddr *, u_int, int, void *,
struct inpcb *(*)(struct inpcb *, int)));
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 75145d7..6723007 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -377,9 +377,9 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
/*
* Locate pcb for datagram.
*/
- inp = in6_pcblookup(&V_udbinfo, &ip6->ip6_src, uh->uh_sport,
+ inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src, uh->uh_sport,
&ip6->ip6_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
- INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif);
+ INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
if (inp == NULL) {
if (udp_log_in_vain) {
char ip6bufs[INET6_ADDRSTRLEN];
OpenPOWER on IntegriCloud