Page MenuHomeFreeBSD

D34138.id102524.diff
No OneTemporary

D34138.id102524.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
@@ -368,6 +368,15 @@
so_gen_t xig_sogen; /* socket generation count this time */
uint64_t _xig_spare64[4];
} __aligned(8);
+
+struct sockopt_parameters {
+ struct in_conninfo sop_inc;
+ uint64_t sop_id;
+ int sop_level;
+ int sop_optname;
+ char sop_optval[];
+};
+
#ifdef _KERNEL
void in_pcbtoxinpcb(const struct inpcb *, struct xinpcb *);
#endif
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -41,6 +41,7 @@
#include "opt_tcpdebug.h"
#include <sys/param.h>
+#include <sys/hash.h>
#include <sys/systm.h>
#include <sys/arb.h>
#include <sys/callout.h>
@@ -85,6 +86,7 @@
#include <netinet/in_fib.h>
#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
+#include <netinet/in_pcb_var.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
@@ -3834,6 +3836,85 @@
CTLFLAG_NEEDGIANT, NULL, 0, sysctl_drop, "",
"Drop TCP connection");
+static int
+sysctl_setsockopt(SYSCTL_HANDLER_ARGS)
+{
+ struct sockopt sopt;
+ struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_tcbinfo,
+ INPLOOKUP_WLOCKPCB);
+ struct inpcb *inp;
+ struct sockopt_parameters *params;
+ struct socket *so;
+ int error;
+ char buf[1024];
+
+ if (req->oldptr != NULL || req->oldlen != 0)
+ return (EINVAL);
+ if (req->newptr == NULL)
+ return (EPERM);
+ if (req->newlen > sizeof(buf))
+ return (ENOMEM);
+ error = SYSCTL_IN(req, buf, req->newlen);
+ if (error != 0)
+ return (error);
+ if (req->newlen < sizeof(struct sockopt_parameters))
+ return (EINVAL);
+ params = (struct sockopt_parameters *)buf;
+ sopt.sopt_level = params->sop_level;
+ sopt.sopt_name = params->sop_optname;
+ sopt.sopt_dir = SOPT_SET;
+ sopt.sopt_val = params->sop_optval;
+ sopt.sopt_valsize = req->newlen - sizeof(struct sockopt_parameters);
+ sopt.sopt_td = NULL;
+ if (params->sop_inc.inc_flags & INC_ISIPV6) {
+ if (IN6_IS_SCOPE_LINKLOCAL(&params->sop_inc.inc6_laddr))
+ params->sop_inc.inc6_laddr.s6_addr16[1] =
+ htons(params->sop_inc.inc6_zoneid & 0xffff);
+ if (IN6_IS_SCOPE_LINKLOCAL(&params->sop_inc.inc6_faddr))
+ params->sop_inc.inc6_faddr.s6_addr16[1] =
+ htons(params->sop_inc.inc6_zoneid & 0xffff);
+ }
+ if (params->sop_inc.inc_lport != htons(0)) {
+ if (params->sop_inc.inc_fport == htons(0))
+ inpi.hash = INP_PCBHASH_WILD(params->sop_inc.inc_lport,
+ V_tcbinfo.ipi_hashmask);
+ else
+ if (params->sop_inc.inc_flags & INC_ISIPV6)
+ inpi.hash = INP6_PCBHASH(
+ &params->sop_inc.inc6_faddr,
+ params->sop_inc.inc_lport,
+ params->sop_inc.inc_fport,
+ V_tcbinfo.ipi_hashmask);
+ else
+ inpi.hash = INP_PCBHASH(
+ &params->sop_inc.inc_faddr,
+ params->sop_inc.inc_lport,
+ params->sop_inc.inc_fport,
+ V_tcbinfo.ipi_hashmask);
+ }
+ while ((inp = inp_next(&inpi)) != NULL)
+ if (inp->inp_gencnt == params->sop_id) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+ INP_WUNLOCK(inp);
+ return (ECONNRESET);
+ }
+ so = inp->inp_socket;
+ KASSERT(so != NULL, ("inp_socket == NULL"));
+ soref(so);
+ error = tcp_ctloutput_set(inp, &sopt);
+ sorele(so);
+ break;
+ }
+ if (inp == NULL)
+ error = ESRCH;
+ return (error);
+}
+
+SYSCTL_PROC(_net_inet_tcp, OID_AUTO, setsockopt,
+ CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_WR | CTLFLAG_SKIP |
+ CTLFLAG_MPSAFE, NULL, 0, sysctl_setsockopt, "",
+ "Set socket option for TCP endpoint");
+
#ifdef KERN_TLS
static int
sysctl_switch_tls(SYSCTL_HANDLER_ARGS)

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 21, 6:50 PM (2 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27119408
Default Alt Text
D34138.id102524.diff (3 KB)

Event Timeline