Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115645102
D48661.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D48661.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D48661: inpcb: Add a flags parameter to in_pcbbind()
Attached
Detach File
Event Timeline
Log In to Comment