Removal of deprecated implied connect for TCP
Andre Oppermann
andre at freebsd.org
Sun Aug 29 15:22:15 UTC 2010
When T/TCP RFC1644 support was introduced in r6283 by wollman 15 years
ago the semantics of sendto(2) with regard to TCP sockets were changed.
It became possible directly do a sendto(2) call with the target address in
the *to argument instead of doing a connect(2) first and subsequent write(2)
or send(2) calls as the standard TCP API specifies. Optionally MSG_EOR
could be specified to close the connection again right again after the
data has been sent out.
This is totally non-portable and no other OS (Linux, NetBSD, OpenBSD,
Solaris, HP-UX) ever supported this functionality for TCP sockets.
FreeBSD was the only OS to ever ship this.
T/TCP was ill-defined and had major security issues and never gained
any support. It has been defunct in FreeBSD and most code has been
removed about 6 years ago. The sendto(2) extended functionality is one
of the last parts that persisted and remained around living a zombie life.
I want to remove it now because it is totally non-portable, has no
known users and complicates the TCP send path. The patch is attached.
If you have any objections speak up now.
--
Andre
-------------- next part --------------
Index: netinet/tcp_usrreq.c
===================================================================
--- netinet/tcp_usrreq.c (revision 211874)
+++ netinet/tcp_usrreq.c (working copy)
@@ -740,86 +740,34 @@
int error = 0;
struct inpcb *inp;
struct tcpcb *tp = NULL;
- int headlocked = 0;
-#ifdef INET6
- int isipv6;
-#endif
+
TCPDEBUG0;
- /*
- * We require the pcbinfo lock in two cases:
- *
- * (1) An implied connect is taking place, which can result in
- * binding IPs and ports and hence modification of the pcb hash
- * chains.
- *
- * (2) PRUS_EOF is set, resulting in explicit close on the send.
- */
- if ((nam != NULL) || (flags & PRUS_EOF)) {
- INP_INFO_WLOCK(&V_tcbinfo);
- headlocked = 1;
+ /* TCP doesn't do control messages (rights, creds, etc.) */
+ if (control != NULL && control->m_len) {
+ error = EINVAL;
+ goto out;
}
+
inp = sotoinpcb(so);
- KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL"));
+ KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
INP_WLOCK(inp);
- if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
- if (control)
- m_freem(control);
- if (m)
- m_freem(m);
+ if (inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT)) {
error = ECONNRESET;
- goto out;
+ goto done;
}
-#ifdef INET6
- isipv6 = nam && nam->sa_family == AF_INET6;
-#endif /* INET6 */
tp = intotcpcb(inp);
+
TCPDEBUG1();
- if (control) {
- /* TCP doesn't do control messages (rights, creds, etc) */
- if (control->m_len) {
- m_freem(control);
- if (m)
- m_freem(m);
- error = EINVAL;
- goto out;
- }
- m_freem(control); /* empty control, just free it */
- }
+
+ /*
+ * Append the new data to the send socket buffer and
+ * try to send it (may be limited by CWND).
+ */
if (!(flags & PRUS_OOB)) {
sbappendstream(&so->so_snd, m);
- if (nam && tp->t_state < TCPS_SYN_SENT) {
- /*
- * Do implied connect if not yet connected,
- * initialize window to default value, and
- * initialize maxseg/maxopd using peer's cached
- * MSS.
- */
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
-#ifdef INET6
- if (isipv6)
- error = tcp6_connect(tp, nam, td);
- else
-#endif /* INET6 */
- error = tcp_connect(tp, nam, td);
- if (error)
- goto out;
- tp->snd_wnd = TTCP_CLIENT_SND_WND;
- tcp_mss(tp, -1);
- }
- if (flags & PRUS_EOF) {
- /*
- * Close the send side of the connection after
- * the data is sent.
- */
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
- socantsendmore(so);
- tcp_usrclosed(tp);
- }
- if (headlocked) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
- headlocked = 0;
- }
+ m = NULL;
+
if (!(inp->inp_flags & INP_DROPPED)) {
if (flags & PRUS_MORETOCOME)
tp->t_flags |= TF_MORETOCOME;
@@ -828,15 +776,11 @@
tp->t_flags &= ~TF_MORETOCOME;
}
} else {
- /*
- * XXXRW: PRUS_EOF not implemented with PRUS_OOB?
- */
SOCKBUF_LOCK(&so->so_snd);
if (sbspace(&so->so_snd) < -512) {
SOCKBUF_UNLOCK(&so->so_snd);
- m_freem(m);
error = ENOBUFS;
- goto out;
+ goto done;
}
/*
* According to RFC961 (Assigned Protocols),
@@ -847,42 +791,24 @@
* Otherwise, snd_up should be one lower.
*/
sbappendstream_locked(&so->so_snd, m);
+ m = NULL;
SOCKBUF_UNLOCK(&so->so_snd);
- if (nam && tp->t_state < TCPS_SYN_SENT) {
- /*
- * Do implied connect if not yet connected,
- * initialize window to default value, and
- * initialize maxseg/maxopd using peer's cached
- * MSS.
- */
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
-#ifdef INET6
- if (isipv6)
- error = tcp6_connect(tp, nam, td);
- else
-#endif /* INET6 */
- error = tcp_connect(tp, nam, td);
- if (error)
- goto out;
- tp->snd_wnd = TTCP_CLIENT_SND_WND;
- tcp_mss(tp, -1);
- INP_INFO_WUNLOCK(&V_tcbinfo);
- headlocked = 0;
- } else if (nam) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
- headlocked = 0;
- }
+
tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
tp->t_flags |= TF_FORCEDATA;
error = tcp_output_send(tp);
tp->t_flags &= ~TF_FORCEDATA;
}
-out:
- TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB :
- ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
+ TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB : PRU_SEND);
+done:
INP_WUNLOCK(inp);
- if (headlocked)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+out:
+ /* Free mbufs in error cases. */
+ if (m != NULL)
+ m_freem(m);
+ if (control != NULL)
+ m_freem(control);
+
return (error);
}
Index: netinet/in_proto.c
===================================================================
--- netinet/in_proto.c (revision 211874)
+++ netinet/in_proto.c (working copy)
@@ -134,7 +134,7 @@
.pr_type = SOCK_STREAM,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_TCP,
- .pr_flags = PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD,
+ .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD,
.pr_input = tcp_input,
.pr_ctlinput = tcp_ctlinput,
.pr_ctloutput = tcp_ctloutput,
More information about the freebsd-net
mailing list