diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h index e7c47e85bb7b..6dc7403aae28 100644 --- a/sys/netinet/tcp.h +++ b/sys/netinet/tcp.h @@ -210,6 +210,7 @@ struct tcphdr { #define TCP_PCAP_OUT 2048 /* number of output packets to keep */ #define TCP_PCAP_IN 4096 /* number of input packets to keep */ #define TCP_FUNCTION_BLK 8192 /* Set the tcp function pointers to the specified stack */ +#define TCP_FUNCTION_ALIAS 8193 /* Get the current tcp function pointer name alias */ /* Options for Rack and BBR */ #define TCP_REUSPORT_LB_NUMA 1026 /* set listen socket numa domain */ #define TCP_RACK_MBUF_QUEUE 1050 /* Do we allow mbuf queuing if supported */ diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 9d66086a383b..2752773a95fc 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -473,6 +473,37 @@ find_and_ref_tcp_fb(struct tcp_function_block *blk) return(rblk); } +/* Find a matching alias for the given tcp_function_block. */ +int +find_tcp_function_alias(struct tcp_function_block *blk, + struct tcp_function_set *fs) +{ + struct tcp_function *f; + int found; + + found = 0; + rw_rlock(&tcp_function_lock); + TAILQ_FOREACH(f, &t_functions, tf_next) { + if ((f->tf_fb == blk) && + (strncmp(f->tf_name, blk->tfb_tcp_block_name, + TCP_FUNCTION_NAME_LEN_MAX) != 0)) { + /* Matching function block with different name. */ + strncpy(fs->function_set_name, f->tf_name, + TCP_FUNCTION_NAME_LEN_MAX); + found = 1; + break; + } + } + /* Null terminate the string appropriately. */ + if (found) { + fs->function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0'; + } else { + fs->function_set_name[0] = '\0'; + } + rw_runlock(&tcp_function_lock); + return (found); +} + static struct tcp_function_block * find_and_ref_tcp_default_fb(void) { diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index e9f7fa541461..f004d54b4657 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1894,10 +1894,17 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt) INP_WUNLOCK(inp); return (error); } else if ((sopt->sopt_dir == SOPT_GET) && - (sopt->sopt_name == TCP_FUNCTION_BLK)) { - strncpy(fsn.function_set_name, tp->t_fb->tfb_tcp_block_name, - TCP_FUNCTION_NAME_LEN_MAX); - fsn.function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0'; + ((sopt->sopt_name == TCP_FUNCTION_BLK) || + (sopt->sopt_name == TCP_FUNCTION_ALIAS))) { + if (sopt->sopt_name == TCP_FUNCTION_ALIAS) { + memset(&fsn, 0, sizeof(fsn)); + find_tcp_function_alias(tp->t_fb, &fsn); + } else { + strncpy(fsn.function_set_name, + tp->t_fb->tfb_tcp_block_name, + TCP_FUNCTION_NAME_LEN_MAX); + fsn.function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0'; + } fsn.pcbcnt = tp->t_fb->tfb_refcnt; INP_WUNLOCK(inp); error = sooptcopyout(sopt, &fsn, sizeof fsn); diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index d5b2963ef4dc..2775fb392a1a 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1020,6 +1020,7 @@ int register_tcp_functions_as_name(struct tcp_function_block *blk, int deregister_tcp_functions(struct tcp_function_block *blk, bool quiesce, bool force); struct tcp_function_block *find_and_ref_tcp_functions(struct tcp_function_set *fs); +int find_tcp_function_alias(struct tcp_function_block *blk, struct tcp_function_set *fs); void tcp_switch_back_to_default(struct tcpcb *tp); struct tcp_function_block * find_and_ref_tcp_fb(struct tcp_function_block *fs);