Changeset View
Changeset View
Standalone View
Standalone View
netinet/tcp_usrreq.c
Context not available. | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/refcount.h> | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
Context not available. | |||||
goto out; | goto out; | ||||
#endif | #endif | ||||
tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); | tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
out: | out: | ||||
TCPDEBUG2(PRU_CONNECT); | TCPDEBUG2(PRU_CONNECT); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
Context not available. | |||||
(error = tcp_offload_connect(so, nam)) == 0) | (error = tcp_offload_connect(so, nam)) == 0) | ||||
goto out; | goto out; | ||||
#endif | #endif | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
goto out; | goto out; | ||||
} | } | ||||
#endif | #endif | ||||
Context not available. | |||||
goto out; | goto out; | ||||
#endif | #endif | ||||
tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); | tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
out: | out: | ||||
TCPDEBUG2(PRU_CONNECT); | TCPDEBUG2(PRU_CONNECT); | ||||
Context not available. | |||||
socantsendmore(so); | socantsendmore(so); | ||||
tcp_usrclosed(tp); | tcp_usrclosed(tp); | ||||
if (!(inp->inp_flags & INP_DROPPED)) | if (!(inp->inp_flags & INP_DROPPED)) | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
out: | out: | ||||
TCPDEBUG2(PRU_SHUTDOWN); | TCPDEBUG2(PRU_SHUTDOWN); | ||||
Context not available. | |||||
tcp_offload_rcvd(tp); | tcp_offload_rcvd(tp); | ||||
else | else | ||||
#endif | #endif | ||||
tcp_output(tp); | tp->t_fb->tcp_output(tp); | ||||
out: | out: | ||||
TCPDEBUG2(PRU_RCVD); | TCPDEBUG2(PRU_RCVD); | ||||
Context not available. | |||||
!(flags & PRUS_NOTREADY)) { | !(flags & PRUS_NOTREADY)) { | ||||
if (flags & PRUS_MORETOCOME) | if (flags & PRUS_MORETOCOME) | ||||
tp->t_flags |= TF_MORETOCOME; | tp->t_flags |= TF_MORETOCOME; | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
if (flags & PRUS_MORETOCOME) | if (flags & PRUS_MORETOCOME) | ||||
tp->t_flags &= ~TF_MORETOCOME; | tp->t_flags &= ~TF_MORETOCOME; | ||||
} | } | ||||
Context not available. | |||||
tp->snd_up = tp->snd_una + sbavail(&so->so_snd); | tp->snd_up = tp->snd_una + sbavail(&so->so_snd); | ||||
if (!(flags & PRUS_NOTREADY)) { | if (!(flags & PRUS_NOTREADY)) { | ||||
tp->t_flags |= TF_FORCEDATA; | tp->t_flags |= TF_FORCEDATA; | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
tp->t_flags &= ~TF_FORCEDATA; | tp->t_flags &= ~TF_FORCEDATA; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
error = sbready(&so->so_snd, m, count); | error = sbready(&so->so_snd, m, count); | ||||
SOCKBUF_UNLOCK(&so->so_snd); | SOCKBUF_UNLOCK(&so->so_snd); | ||||
if (error == 0) | if (error == 0) | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
return (error); | return (error); | ||||
Context not available. | |||||
int | int | ||||
tcp_ctloutput(struct socket *so, struct sockopt *sopt) | tcp_ctloutput(struct socket *so, struct sockopt *sopt) | ||||
{ | { | ||||
int error, opt, optval; | int error; | ||||
u_int ui; | |||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct tcpcb *tp; | struct tcpcb *tp; | ||||
struct tcp_info ti; | struct tcp_function_block *blk; | ||||
char buf[TCP_CA_NAME_MAX]; | struct tcp_function_set fsn; | ||||
struct cc_algo *algo; | |||||
error = 0; | error = 0; | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
Context not available. | |||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
return (ECONNRESET); | return (ECONNRESET); | ||||
} | } | ||||
tp = intotcpcb(inp); | |||||
/* | |||||
* Protect the TCP option TCP_FUNCTION_BLK so | |||||
* that a sub-function can *never* overwrite this. | |||||
*/ | |||||
if ((sopt->sopt_dir == SOPT_SET) && | |||||
(sopt->sopt_name == TCP_FUNCTION_BLK)) { | |||||
INP_WUNLOCK(inp); | |||||
error = sooptcopyin(sopt, &fsn, sizeof fsn, | |||||
sizeof fsn); | |||||
if (error) | |||||
return (error); | |||||
INP_WLOCK_RECHECK(inp); | |||||
if (tp->t_state != TCPS_CLOSED) { | |||||
/* | |||||
* The user has advanced the state | |||||
* past the initial point, we can't | |||||
* switch since we are down the road | |||||
* and a new set of functions may | |||||
* not be compatibile. | |||||
*/ | |||||
INP_WUNLOCK(inp); | |||||
return(EINVAL); | |||||
} | |||||
blk = find_and_ref_tcp_functions(&fsn); | |||||
if (blk == NULL) { | |||||
INP_WUNLOCK(inp); | |||||
return (ENOENT); | |||||
} | |||||
if (tp->t_fb != blk) { | |||||
if (blk->flags & TCP_FUNC_BEING_REMOVED) { | |||||
refcount_release(&blk->refcnt); | |||||
INP_WUNLOCK(inp); | |||||
return (ENOENT); | |||||
} | |||||
/* | |||||
* Release the old refcnt, the | |||||
* lookup acquires a ref on the | |||||
* new one. | |||||
*/ | |||||
if (tp->t_fb->tcp_fb_fini) | |||||
(*tp->t_fb->tcp_fb_fini)(tp); | |||||
refcount_release(&tp->t_fb->refcnt); | |||||
tp->t_fb = blk; | |||||
if (tp->t_fb->tcp_fb_init) { | |||||
(*tp->t_fb->tcp_fb_init)(tp); | |||||
} | |||||
} | |||||
#ifdef TCP_OFFLOAD | |||||
if (tp->t_flags & TF_TOE) { | |||||
tcp_offload_ctloutput(tp, sopt->sopt_dir, | |||||
sopt->sopt_name); | |||||
} | |||||
#endif | |||||
INP_WUNLOCK(inp); | |||||
return (error); | |||||
} else if ((sopt->sopt_dir == SOPT_GET) && | |||||
(sopt->sopt_name == TCP_FUNCTION_BLK)) { | |||||
strcpy(fsn.function_set_name, tp->t_fb->tcp_block_name); | |||||
fsn.pcbcnt = tp->t_fb->refcnt; | |||||
INP_WUNLOCK(inp); | |||||
error = sooptcopyout(sopt, &fsn, sizeof fsn); | |||||
return (error); | |||||
} | |||||
/* Pass in the INP locked, called must unlock it */ | |||||
return (tp->t_fb->tcp_ctloutput(so, sopt, inp, tp)); | |||||
} | |||||
int | |||||
tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp) | |||||
{ | |||||
int error, opt, optval; | |||||
u_int ui; | |||||
struct tcp_info ti; | |||||
struct cc_algo *algo; | |||||
char buf[TCP_CA_NAME_MAX]; | |||||
switch (sopt->sopt_dir) { | switch (sopt->sopt_dir) { | ||||
case SOPT_SET: | case SOPT_SET: | ||||
switch (sopt->sopt_name) { | switch (sopt->sopt_name) { | ||||
Context not available. | |||||
else if (tp->t_flags & TF_NOPUSH) { | else if (tp->t_flags & TF_NOPUSH) { | ||||
tp->t_flags &= ~TF_NOPUSH; | tp->t_flags &= ~TF_NOPUSH; | ||||
if (TCPS_HAVEESTABLISHED(tp->t_state)) | if (TCPS_HAVEESTABLISHED(tp->t_state)) | ||||
error = tcp_output(tp); | error = tp->t_fb->tcp_output(tp); | ||||
} | } | ||||
goto unlock_and_done; | goto unlock_and_done; | ||||
Context not available. | |||||
sbflush(&so->so_rcv); | sbflush(&so->so_rcv); | ||||
tcp_usrclosed(tp); | tcp_usrclosed(tp); | ||||
if (!(inp->inp_flags & INP_DROPPED)) | if (!(inp->inp_flags & INP_DROPPED)) | ||||
tcp_output(tp); | tp->t_fb->tcp_output(tp); | ||||
} | } | ||||
} | } | ||||
Context not available. |