| 2037 | #endif |
| 2038 | |
| 2039 | int |
| 2040 | tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp) |
| 2041 | { |
| 2042 | int error, opt, optval; |
| 2043 | u_int ui; |
| 2044 | struct tcp_info ti; |
| 2045 | #ifdef KERN_TLS |
| 2046 | struct tls_enable tls; |
| 2047 | #endif |
| 2048 | struct cc_algo *algo; |
| 2049 | char *pbuf, buf[TCP_LOG_ID_LEN]; |
| 2050 | #ifdef STATS |
| 2051 | struct statsblob *sbp; |
| 2052 | #endif |
| 2053 | size_t len; |
| 2054 | |
| 2055 | /* |
| 2056 | * For TCP_CCALGOOPT forward the control to CC module, for both |
| 2057 | * SOPT_SET and SOPT_GET. |
| 2058 | */ |
| 2059 | switch (sopt->sopt_name) { |
| 2060 | case TCP_CCALGOOPT: |
| 2061 | INP_WUNLOCK(inp); |
| 2062 | if (sopt->sopt_valsize > CC_ALGOOPT_LIMIT) |
| 2063 | return (EINVAL); |
| 2064 | pbuf = malloc(sopt->sopt_valsize, M_TEMP, M_WAITOK | M_ZERO); |
| 2065 | error = sooptcopyin(sopt, pbuf, sopt->sopt_valsize, |
| 2066 | sopt->sopt_valsize); |
| 2067 | if (error) { |
| 2068 | free(pbuf, M_TEMP); |
| 2069 | return (error); |
| 2070 | } |
| 2071 | INP_WLOCK_RECHECK_CLEANUP(inp, free(pbuf, M_TEMP)); |
| 2072 | if (CC_ALGO(tp)->ctl_output != NULL) |
| 2073 | error = CC_ALGO(tp)->ctl_output(tp->ccv, sopt, pbuf); |
| 2074 | else |
| 2075 | error = ENOENT; |
| 2076 | INP_WUNLOCK(inp); |
| 2077 | if (error == 0 && sopt->sopt_dir == SOPT_GET) |
| 2078 | error = sooptcopyout(sopt, pbuf, sopt->sopt_valsize); |
| 2079 | free(pbuf, M_TEMP); |
| 2080 | return (error); |
| 2081 | } |
| 2082 | |
| 2083 | switch (sopt->sopt_dir) { |
| 2084 | case SOPT_SET: |
| 2085 | switch (sopt->sopt_name) { |
| 2086 | #if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) |
| 2087 | case TCP_MD5SIG: |
| 2088 | if (!TCPMD5_ENABLED()) { |
| 2089 | INP_WUNLOCK(inp); |
| 2090 | return (ENOPROTOOPT); |
| 2091 | } |
| 2092 | error = TCPMD5_PCBCTL(inp, sopt); |
| 2093 | if (error) |
| 2094 | return (error); |
| 2095 | goto unlock_and_done; |
| 2096 | #endif /* IPSEC */ |
no test coverage detected