Page MenuHomeFreeBSD

D48661.diff
No OneTemporary

D48661.diff

diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -437,7 +437,7 @@
uint16_t il_lport; /* (c) */
u_char il_vflag; /* (c) */
uint8_t il_numa_domain;
- uint32_t il_pad2;
+ int il_fibnum;
union in_dependaddr il_dependladdr; /* (c) */
#define il_laddr il_dependladdr.id46_addr.ia46_addr4
#define il6_laddr il_dependladdr.id6_addr
@@ -575,7 +575,7 @@
#define INP_DROPPED 0x04000000 /* protocol drop flag */
#define INP_SOCKREF 0x08000000 /* strong socket reference */
#define INP_RESERVED_0 0x10000000 /* reserved field */
-#define INP_RESERVED_1 0x20000000 /* reserved field */
+#define INP_BOUNDFIB 0x20000000 /* Bound to a specific FIB. */
#define IN6P_RFC2292 0x40000000 /* used RFC2292 API on the socket */
#define IN6P_MTU 0x80000000 /* receive path MTU */
@@ -662,9 +662,10 @@
void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *);
int in_pcballoc(struct socket *, struct inpcbinfo *);
-int in_pcbbind(struct inpcb *, struct sockaddr_in *, struct ucred *);
+#define INPBIND_FIB 0x0001 /* bind to the PCB's FIB only */
+int in_pcbbind(struct inpcb *, struct sockaddr_in *, int, struct ucred *);
int in_pcbbind_setup(struct inpcb *, struct sockaddr_in *, in_addr_t *,
- u_short *, struct ucred *);
+ u_short *, int, struct ucred *);
int in_pcbconnect(struct inpcb *, struct sockaddr_in *, struct ucred *);
int in_pcbconnect_setup(struct inpcb *, struct sockaddr_in *, in_addr_t *,
u_short *, in_addr_t *, u_short *, struct ucred *);
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -254,7 +254,7 @@
static struct inpcblbgroup *
in_pcblbgroup_alloc(struct ucred *cred, u_char vflag, uint16_t port,
- const union in_dependaddr *addr, int size, uint8_t numa_domain)
+ const union in_dependaddr *addr, int size, uint8_t numa_domain, int fib)
{
struct inpcblbgroup *grp;
size_t bytes;
@@ -268,6 +268,7 @@
grp->il_vflag = vflag;
grp->il_lport = port;
grp->il_numa_domain = numa_domain;
+ grp->il_fibnum = fib;
grp->il_dependladdr = *addr;
grp->il_inpsiz = size;
return (grp);
@@ -360,7 +361,7 @@
grp = in_pcblbgroup_alloc(old_grp->il_cred, old_grp->il_vflag,
old_grp->il_lport, &old_grp->il_dependladdr, size,
- old_grp->il_numa_domain);
+ old_grp->il_numa_domain, old_grp->il_fibnum);
if (grp == NULL)
return (NULL);
@@ -390,12 +391,16 @@
struct inpcblbgrouphead *hdr;
struct inpcblbgroup *grp;
uint32_t idx;
+ int fib;
pcbinfo = inp->inp_pcbinfo;
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(pcbinfo);
+ fib = (inp->inp_flags & INP_BOUNDFIB) != 0 ?
+ inp->inp_inc.inc_fibnum : RT_ALL_FIBS;
+
#ifdef INET6
/*
* Don't allow IPv4 mapped INET6 wild socket.
@@ -414,6 +419,7 @@
grp->il_vflag == inp->inp_vflag &&
grp->il_lport == inp->inp_lport &&
grp->il_numa_domain == numa_domain &&
+ grp->il_fibnum == fib &&
memcmp(&grp->il_dependladdr,
&inp->inp_inc.inc_ie.ie_dependladdr,
sizeof(grp->il_dependladdr)) == 0) {
@@ -424,7 +430,7 @@
/* Create new load balance group. */
grp = in_pcblbgroup_alloc(inp->inp_cred, inp->inp_vflag,
inp->inp_lport, &inp->inp_inc.inc_ie.ie_dependladdr,
- INPCBLBGROUP_SIZMIN, numa_domain);
+ INPCBLBGROUP_SIZMIN, numa_domain, fib);
if (grp == NULL)
return (ENOBUFS);
in_pcblbgroup_insert(grp, inp);
@@ -709,7 +715,8 @@
#ifdef INET
int
-in_pcbbind(struct inpcb *inp, struct sockaddr_in *sin, struct ucred *cred)
+in_pcbbind(struct inpcb *inp, struct sockaddr_in *sin, int flags,
+ struct ucred *cred)
{
int anonport, error;
@@ -724,12 +731,13 @@
return (EINVAL);
anonport = sin == NULL || sin->sin_port == 0;
error = in_pcbbind_setup(inp, sin, &inp->inp_laddr.s_addr,
- &inp->inp_lport, cred);
+ &inp->inp_lport, flags, cred);
if (error)
return (error);
if (in_pcbinshash(inp) != 0) {
inp->inp_laddr.s_addr = INADDR_ANY;
inp->inp_lport = 0;
+ inp->inp_flags &= ~INP_BOUNDFIB;
return (EAGAIN);
}
if (anonport)
@@ -903,7 +911,8 @@
*/
static int
in_pcbbind_avail(struct inpcb *inp, const struct in_addr laddr,
- const u_short lport, int sooptions, int lookupflags, struct ucred *cred)
+ const u_short lport, const int fib, int sooptions, int lookupflags,
+ struct ucred *cred)
{
int reuseport, reuseport_lb;
@@ -974,8 +983,8 @@
(inp->inp_cred->cr_uid != t->inp_cred->cr_uid))
return (EADDRINUSE);
}
- t = in_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
- RT_ALL_FIBS, lookupflags, cred);
+ t = in_pcblookup_local(inp->inp_pcbinfo, laddr, lport, fib,
+ lookupflags, cred);
if (t != NULL && ((reuseport | reuseport_lb) &
t->inp_socket->so_options) == 0) {
#ifdef INET6
@@ -1001,13 +1010,12 @@
*/
int
in_pcbbind_setup(struct inpcb *inp, struct sockaddr_in *sin, in_addr_t *laddrp,
- u_short *lportp, struct ucred *cred)
+ u_short *lportp, int flags, struct ucred *cred)
{
struct socket *so = inp->inp_socket;
struct in_addr laddr;
u_short lport = 0;
- int lookupflags, sooptions;
- int error;
+ int error, fib, lookupflags, sooptions;
/*
* No state changes, so read locks are sufficient here.
@@ -1043,8 +1051,11 @@
}
laddr = sin->sin_addr;
+ fib = (flags & INPBIND_FIB) != 0 ? inp->inp_inc.inc_fibnum :
+ RT_ALL_FIBS;
+
/* See if this address/port combo is available. */
- error = in_pcbbind_avail(inp, laddr, lport, sooptions,
+ error = in_pcbbind_avail(inp, laddr, lport, fib, sooptions,
lookupflags, cred);
if (error != 0)
return (error);
@@ -1058,6 +1069,8 @@
}
*laddrp = laddr.s_addr;
*lportp = lport;
+ if ((flags & INPBIND_FIB) != 0)
+ inp->inp_flags |= INP_BOUNDFIB;
return (0);
}
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -262,7 +262,7 @@
goto out;
}
INP_HASH_WLOCK(&V_tcbinfo);
- error = in_pcbbind(inp, sinp, td->td_ucred);
+ error = in_pcbbind(inp, sinp, 0, td->td_ucred);
INP_HASH_WUNLOCK(&V_tcbinfo);
out:
tcp_bblog_pru(tp, PRU_BIND, error);
@@ -330,13 +330,13 @@
}
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
- error = in_pcbbind(inp, &sin, td->td_ucred);
+ error = in_pcbbind(inp, &sin, 0, td->td_ucred);
INP_HASH_WUNLOCK(&V_tcbinfo);
goto out;
}
}
#endif
- error = in6_pcbbind(inp, sin6, td->td_ucred);
+ error = in6_pcbbind(inp, sin6, 0, td->td_ucred);
INP_HASH_WUNLOCK(&V_tcbinfo);
out:
if (error != 0)
@@ -378,7 +378,7 @@
}
if (inp->inp_lport == 0) {
INP_HASH_WLOCK(&V_tcbinfo);
- error = in_pcbbind(inp, NULL, td->td_ucred);
+ error = in_pcbbind(inp, NULL, 0, td->td_ucred);
INP_HASH_WUNLOCK(&V_tcbinfo);
}
if (error == 0) {
@@ -441,7 +441,7 @@
inp->inp_vflag &= ~INP_IPV4;
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
inp->inp_vflag |= INP_IPV4;
- error = in6_pcbbind(inp, NULL, td->td_ucred);
+ error = in6_pcbbind(inp, NULL, 0, td->td_ucred);
}
INP_HASH_WUNLOCK(&V_tcbinfo);
if (error == 0) {
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1242,7 +1242,7 @@
inp->inp_vflag &= ~INP_IPV6;
}
INP_HASH_WLOCK(pcbinfo);
- error = in_pcbbind_setup(inp, &src, &laddr.s_addr, &lport,
+ error = in_pcbbind_setup(inp, &src, &laddr.s_addr, &lport, 0,
td->td_ucred);
INP_HASH_WUNLOCK(pcbinfo);
if ((flags & PRUS_IPV6) != 0)
@@ -1592,7 +1592,7 @@
INP_WLOCK(inp);
INP_HASH_WLOCK(pcbinfo);
- error = in_pcbbind(inp, sinp, td->td_ucred);
+ error = in_pcbbind(inp, sinp, 0, td->td_ucred);
INP_HASH_WUNLOCK(pcbinfo);
INP_WUNLOCK(inp);
return (error);
diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h
--- a/sys/netinet6/in6_pcb.h
+++ b/sys/netinet6/in6_pcb.h
@@ -70,7 +70,7 @@
void in6_pcbpurgeif0(struct inpcbinfo *, struct ifnet *);
void in6_losing(struct inpcb *);
-int in6_pcbbind(struct inpcb *, struct sockaddr_in6 *, struct ucred *);
+int in6_pcbbind(struct inpcb *, struct sockaddr_in6 *, int, struct ucred *);
int in6_pcbconnect(struct inpcb *, struct sockaddr_in6 *, struct ucred *,
bool);
void in6_pcbdisconnect(struct inpcb *);
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -164,7 +164,7 @@
* Determine whether the inpcb can be bound to the specified address/port tuple.
*/
static int
-in6_pcbbind_avail(struct inpcb *inp, const struct sockaddr_in6 *sin6,
+in6_pcbbind_avail(struct inpcb *inp, const struct sockaddr_in6 *sin6, int fib,
int sooptions, int lookupflags, struct ucred *cred)
{
const struct in6_addr *laddr;
@@ -275,7 +275,7 @@
#endif
}
t = in6_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
- RT_ALL_FIBS, lookupflags, cred);
+ fib, lookupflags, cred);
if (t != NULL && ((reuseport | reuseport_lb) &
t->inp_socket->so_options) == 0)
return (EADDRINUSE);
@@ -300,11 +300,12 @@
}
int
-in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred)
+in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, int flags,
+ struct ucred *cred)
{
struct socket *so = inp->inp_socket;
u_short lport = 0;
- int error, lookupflags, sooptions;
+ int error, fib, lookupflags, sooptions;
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
@@ -333,8 +334,11 @@
((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
return (error);
+ fib = (flags & INPBIND_FIB) != 0 ? inp->inp_inc.inc_fibnum :
+ RT_ALL_FIBS;
+
/* See if this address/port combo is available. */
- error = in6_pcbbind_avail(inp, sin6, sooptions, lookupflags,
+ error = in6_pcbbind_avail(inp, sin6, fib, sooptions, lookupflags,
cred);
if (error != 0)
return (error);
@@ -342,15 +346,19 @@
lport = sin6->sin6_port;
inp->in6p_laddr = sin6->sin6_addr;
}
+ if ((flags & INPBIND_FIB) != 0)
+ inp->inp_flags |= INP_BOUNDFIB;
if (lport == 0) {
if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) {
/* Undo an address bind that may have occurred. */
+ inp->inp_flags &= ~INP_BOUNDFIB;
inp->in6p_laddr = in6addr_any;
return (error);
}
} else {
inp->inp_lport = lport;
if (in_pcbinshash(inp) != 0) {
+ inp->inp_flags &= ~INP_BOUNDFIB;
inp->in6p_laddr = in6addr_any;
inp->inp_lport = 0;
return (EAGAIN);
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -1058,13 +1058,13 @@
in6_sin6_2_sin(&sin, sin6_p);
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
- error = in_pcbbind(inp, &sin, td->td_ucred);
+ error = in_pcbbind(inp, &sin, 0, td->td_ucred);
goto out;
}
#endif
}
- error = in6_pcbbind(inp, sin6_p, td->td_ucred);
+ error = in6_pcbbind(inp, sin6_p, 0, td->td_ucred);
#ifdef INET
out:
#endif

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 27, 11:54 AM (10 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17817334
Default Alt Text
D48661.diff (10 KB)

Event Timeline