Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115287530
D48666.id150078.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D48666.id150078.diff
View Options
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -3699,6 +3699,19 @@
}
+int
+sosetfib(struct socket *so, int fibnum)
+{
+ if (fibnum < 0 || fibnum >= rt_numfibs)
+ return (EINVAL);
+
+ SOCK_LOCK(so);
+ so->so_fibnum = fibnum;
+ SOCK_UNLOCK(so);
+
+ return (0);
+}
+
#ifdef SOCKET_HHOOK
/*
* Wrapper for Socket established helper hook.
@@ -3847,21 +3860,7 @@
break;
case SO_SETFIB:
- error = sooptcopyin(sopt, &optval, sizeof optval,
- sizeof optval);
- if (error)
- goto bad;
-
- if (optval < 0 || optval >= rt_numfibs) {
- error = EINVAL;
- goto bad;
- }
- if (((so->so_proto->pr_domain->dom_family == PF_INET) ||
- (so->so_proto->pr_domain->dom_family == PF_INET6) ||
- (so->so_proto->pr_domain->dom_family == PF_ROUTE)))
- so->so_fibnum = optval;
- else
- so->so_fibnum = 0;
+ error = so->so_proto->pr_ctloutput(so, sopt);
break;
case SO_USER_COOKIE:
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -423,6 +423,30 @@
return (0);
}
+static int
+rts_ctloutput(struct socket *so, struct sockopt *sopt)
+{
+ int error, optval;
+
+ error = ENOPROTOOPT;
+ if (sopt->sopt_dir == SOPT_SET) {
+ switch (sopt->sopt_level) {
+ case SOL_SOCKET:
+ switch (sopt->sopt_name) {
+ case SO_SETFIB:
+ error = sooptcopyin(sopt, &optval,
+ sizeof(optval), sizeof(optval));
+ if (error != 0)
+ break;
+ error = sosetfib(so, optval);
+ break;
+ }
+ break;
+ }
+ }
+ return (error);
+}
+
static void
rts_detach(struct socket *so)
{
@@ -2702,6 +2726,7 @@
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_abort = rts_close,
.pr_attach = rts_attach,
+ .pr_ctloutput = rts_ctloutput,
.pr_detach = rts_detach,
.pr_send = rts_send,
.pr_shutdown = rts_shutdown,
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1088,10 +1088,22 @@
sopt->sopt_dir == SOPT_SET) {
switch (sopt->sopt_name) {
case SO_SETFIB:
+ error = sooptcopyin(sopt, &optval,
+ sizeof(optval), sizeof(optval));
+ if (error != 0)
+ break;
+
INP_WLOCK(inp);
- inp->inp_inc.inc_fibnum = so->so_fibnum;
+ if ((inp->inp_flags & INP_BOUNDFIB) != 0 &&
+ optval != so->so_fibnum) {
+ INP_WUNLOCK(inp);
+ error = EISCONN;
+ break;
+ }
+ error = sosetfib(inp->inp_socket, optval);
+ if (error == 0)
+ inp->inp_inc.inc_fibnum = optval;
INP_WUNLOCK(inp);
- error = 0;
break;
case SO_MAX_PACING_RATE:
#ifdef RATELIMIT
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -633,13 +633,10 @@
int error, optval;
if (sopt->sopt_level != IPPROTO_IP) {
- if ((sopt->sopt_level == SOL_SOCKET) &&
- (sopt->sopt_name == SO_SETFIB)) {
- INP_WLOCK(inp);
- inp->inp_inc.inc_fibnum = so->so_fibnum;
- INP_WUNLOCK(inp);
- return (0);
- }
+ if (sopt->sopt_dir == SOPT_SET &&
+ sopt->sopt_level == SOL_SOCKET &&
+ sopt->sopt_name == SO_SETFIB)
+ return (ip_ctloutput(so, sopt));
return (EINVAL);
}
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1648,10 +1648,22 @@
sopt->sopt_dir == SOPT_SET) {
switch (sopt->sopt_name) {
case SO_SETFIB:
+ error = sooptcopyin(sopt, &optval,
+ sizeof(optval), sizeof(optval));
+ if (error != 0)
+ break;
+
INP_WLOCK(inp);
- inp->inp_inc.inc_fibnum = so->so_fibnum;
+ if ((inp->inp_flags & INP_BOUNDFIB) != 0 &&
+ optval != so->so_fibnum) {
+ INP_WUNLOCK(inp);
+ error = EISCONN;
+ break;
+ }
+ error = sosetfib(inp->inp_socket, optval);
+ if (error == 0)
+ inp->inp_inc.inc_fibnum = optval;
INP_WUNLOCK(inp);
- error = 0;
break;
case SO_MAX_PACING_RATE:
#ifdef RATELIMIT
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -576,13 +576,10 @@
*/
return (icmp6_ctloutput(so, sopt));
else if (sopt->sopt_level != IPPROTO_IPV6) {
- if (sopt->sopt_level == SOL_SOCKET &&
- sopt->sopt_name == SO_SETFIB) {
- INP_WLOCK(inp);
- inp->inp_inc.inc_fibnum = so->so_fibnum;
- INP_WUNLOCK(inp);
- return (0);
- }
+ if (sopt->sopt_dir == SOPT_SET &&
+ sopt->sopt_level == SOL_SOCKET &&
+ sopt->sopt_name == SO_SETFIB)
+ return (ip6_ctloutput(so, sopt));
return (EINVAL);
}
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -555,6 +555,7 @@
int sosend_generic(struct socket *so, struct sockaddr *addr,
struct uio *uio, struct mbuf *top, struct mbuf *control,
int flags, struct thread *td);
+int sosetfib(struct socket *so, int fibnum);
int soshutdown(struct socket *so, enum shutdown_how);
void soupcall_clear(struct socket *, sb_which);
void soupcall_set(struct socket *, sb_which, so_upcall_t, void *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 23, 6:44 AM (15 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17682440
Default Alt Text
D48666.id150078.diff (4 KB)
Attached To
Mode
D48666: socket: Move SO_SETFIB handling to protocol layers
Attached
Detach File
Event Timeline
Log In to Comment