Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_subr.c
Show First 20 Lines • Show All 2,785 Lines • ▼ Show 20 Lines | |||||
SYSCTL_PROC(_net_inet6_tcp6, OID_AUTO, getcred, | SYSCTL_PROC(_net_inet6_tcp6, OID_AUTO, getcred, | ||||
CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_NEEDGIANT, | CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_NEEDGIANT, | ||||
0, 0, tcp6_getcred, "S,xucred", | 0, 0, tcp6_getcred, "S,xucred", | ||||
"Get the xucred of a TCP6 connection"); | "Get the xucred of a TCP6 connection"); | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#ifdef INET | #ifdef INET | ||||
/* Path MTU to try next when a fragmentation-needed message is received. */ | |||||
static inline int | |||||
tcp_next_pmtu(const struct icmp *icp, const struct ip *ip) | |||||
{ | |||||
int mtu = ntohs(icp->icmp_nextmtu); | |||||
/* If no alternative MTU was proposed, try the next smaller one. */ | |||||
if (!mtu) | |||||
mtu = ip_next_mtu(ntohs(ip->ip_len), 1); | |||||
if (mtu < V_tcp_minmss + sizeof(struct tcpiphdr)) | |||||
mtu = V_tcp_minmss + sizeof(struct tcpiphdr); | |||||
return (mtu); | |||||
} | |||||
static void | static void | ||||
tcp_ctlinput_with_port(int cmd, struct sockaddr *sa, void *vip, uint16_t port) | tcp_ctlinput_with_port(int cmd, struct sockaddr *sa, void *vip, uint16_t port) | ||||
{ | { | ||||
struct ip *ip = vip; | struct ip *ip = vip; | ||||
struct tcphdr *th; | struct tcphdr *th; | ||||
struct in_addr faddr; | struct in_addr faddr; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct tcpcb *tp; | struct tcpcb *tp; | ||||
Show All 39 Lines | if (inp != NULL && PRC_IS_REDIRECT(cmd)) { | ||||
goto out; | goto out; | ||||
} | } | ||||
icmp_tcp_seq = th->th_seq; | icmp_tcp_seq = th->th_seq; | ||||
if (inp != NULL) { | if (inp != NULL) { | ||||
if (!(inp->inp_flags & INP_TIMEWAIT) && | if (!(inp->inp_flags & INP_TIMEWAIT) && | ||||
!(inp->inp_flags & INP_DROPPED) && | !(inp->inp_flags & INP_DROPPED) && | ||||
!(inp->inp_socket == NULL)) { | !(inp->inp_socket == NULL)) { | ||||
tp = intotcpcb(inp); | tp = intotcpcb(inp); | ||||
#ifdef TCP_OFFLOAD | |||||
if (tp->t_flags & TF_TOE && cmd == PRC_MSGSIZE) { | |||||
/* | |||||
* MTU discovery for offloaded connections. Let | |||||
* the TOE driver verify seq# and process it. | |||||
*/ | |||||
mtu = tcp_next_pmtu(icp, ip); | |||||
tcp_offload_pmtu_update(tp, icmp_tcp_seq, mtu); | |||||
goto out; | |||||
} | |||||
#endif | |||||
if (tp->t_port != port) { | if (tp->t_port != port) { | ||||
goto out; | goto out; | ||||
} | } | ||||
if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) && | if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) && | ||||
SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) { | SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) { | ||||
if (cmd == PRC_MSGSIZE) { | if (cmd == PRC_MSGSIZE) { | ||||
/* | /* | ||||
* MTU discovery: | * MTU discovery: we got a needfrag and | ||||
* If we got a needfrag set the MTU | * will potentially try a lower MTU. | ||||
* in the route to the suggested new | |||||
* value (if given) and then notify. | |||||
*/ | */ | ||||
mtu = ntohs(icp->icmp_nextmtu); | mtu = tcp_next_pmtu(icp, ip); | ||||
/* | /* | ||||
* If no alternative MTU was | |||||
* proposed, try the next smaller | |||||
* one. | |||||
*/ | |||||
if (!mtu) | |||||
mtu = ip_next_mtu( | |||||
ntohs(ip->ip_len), 1); | |||||
if (mtu < V_tcp_minmss + | |||||
sizeof(struct tcpiphdr)) | |||||
mtu = V_tcp_minmss + | |||||
sizeof(struct tcpiphdr); | |||||
/* | |||||
* Only process the offered MTU if it | * Only process the offered MTU if it | ||||
* is smaller than the current one. | * is smaller than the current one. | ||||
*/ | */ | ||||
if (mtu < tp->t_maxseg + | if (mtu < tp->t_maxseg + | ||||
sizeof(struct tcpiphdr)) { | sizeof(struct tcpiphdr)) { | ||||
bzero(&inc, sizeof(inc)); | bzero(&inc, sizeof(inc)); | ||||
inc.inc_faddr = faddr; | inc.inc_faddr = faddr; | ||||
inc.inc_fibnum = | inc.inc_fibnum = | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | tcp_ctlinput_viaudp(int cmd, struct sockaddr *sa, void *vip, void *unused) | ||||
o_len -= sizeof(struct udphdr); | o_len -= sizeof(struct udphdr); | ||||
outer_ip->ip_len = htons(o_len); | outer_ip->ip_len = htons(o_len); | ||||
/* Now call in to the normal handling code */ | /* Now call in to the normal handling code */ | ||||
tcp_ctlinput_with_port(cmd, sa, vip, port); | tcp_ctlinput_with_port(cmd, sa, vip, port); | ||||
} | } | ||||
#endif /* INET */ | #endif /* INET */ | ||||
#ifdef INET6 | #ifdef INET6 | ||||
static inline int | |||||
tcp6_next_pmtu(const struct icmp6_hdr *icmp6) | |||||
{ | |||||
int mtu = ntohl(icmp6->icmp6_mtu); | |||||
/* | |||||
* If no alternative MTU was proposed, or the proposed MTU was too | |||||
* small, set to the min. | |||||
*/ | |||||
if (mtu < IPV6_MMTU) | |||||
mtu = IPV6_MMTU - 8; /* XXXNP: what is the adjustment for? */ | |||||
return (mtu); | |||||
} | |||||
static void | static void | ||||
tcp6_ctlinput_with_port(int cmd, struct sockaddr *sa, void *d, uint16_t port) | tcp6_ctlinput_with_port(int cmd, struct sockaddr *sa, void *d, uint16_t port) | ||||
{ | { | ||||
struct in6_addr *dst; | struct in6_addr *dst; | ||||
struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify; | struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | if (m->m_pkthdr.len < (int32_t) (off + sizeof(tcp_seq))) { | ||||
goto out; | goto out; | ||||
} | } | ||||
m_copydata(m, off, sizeof(tcp_seq), (caddr_t)&icmp_tcp_seq); | m_copydata(m, off, sizeof(tcp_seq), (caddr_t)&icmp_tcp_seq); | ||||
if (inp != NULL) { | if (inp != NULL) { | ||||
if (!(inp->inp_flags & INP_TIMEWAIT) && | if (!(inp->inp_flags & INP_TIMEWAIT) && | ||||
!(inp->inp_flags & INP_DROPPED) && | !(inp->inp_flags & INP_DROPPED) && | ||||
!(inp->inp_socket == NULL)) { | !(inp->inp_socket == NULL)) { | ||||
tp = intotcpcb(inp); | tp = intotcpcb(inp); | ||||
#ifdef TCP_OFFLOAD | |||||
if (tp->t_flags & TF_TOE && cmd == PRC_MSGSIZE) { | |||||
/* MTU discovery for offloaded connections. */ | |||||
mtu = tcp6_next_pmtu(icmp6); | |||||
tcp_offload_pmtu_update(tp, icmp_tcp_seq, mtu); | |||||
goto out; | |||||
} | |||||
#endif | |||||
if (tp->t_port != port) { | if (tp->t_port != port) { | ||||
goto out; | goto out; | ||||
} | } | ||||
if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) && | if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) && | ||||
SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) { | SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) { | ||||
if (cmd == PRC_MSGSIZE) { | if (cmd == PRC_MSGSIZE) { | ||||
/* | /* | ||||
* MTU discovery: | * MTU discovery: | ||||
* If we got a needfrag set the MTU | * If we got a needfrag set the MTU | ||||
* in the route to the suggested new | * in the route to the suggested new | ||||
* value (if given) and then notify. | * value (if given) and then notify. | ||||
*/ | */ | ||||
mtu = ntohl(icmp6->icmp6_mtu); | mtu = tcp6_next_pmtu(icmp6); | ||||
/* | |||||
* If no alternative MTU was | |||||
* proposed, or the proposed | |||||
* MTU was too small, set to | |||||
* the min. | |||||
*/ | |||||
if (mtu < IPV6_MMTU) | |||||
mtu = IPV6_MMTU - 8; | |||||
bzero(&inc, sizeof(inc)); | bzero(&inc, sizeof(inc)); | ||||
inc.inc_fibnum = M_GETFIB(m); | inc.inc_fibnum = M_GETFIB(m); | ||||
inc.inc_flags |= INC_ISIPV6; | inc.inc_flags |= INC_ISIPV6; | ||||
inc.inc6_faddr = *dst; | inc.inc6_faddr = *dst; | ||||
if (in6_setscope(&inc.inc6_faddr, | if (in6_setscope(&inc.inc6_faddr, | ||||
m->m_pkthdr.rcvif, NULL)) | m->m_pkthdr.rcvif, NULL)) | ||||
goto out; | goto out; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 876 Lines • Show Last 20 Lines |