Deleted Added
full compact
tcp_usrreq.c (289276) tcp_usrreq.c (292309)
1/*-
2 * Copyright (c) 1982, 1986, 1988, 1993
3 * The Regents of the University of California.
4 * Copyright (c) 2006-2007 Robert N. M. Watson
5 * Copyright (c) 2010-2011 Juniper Networks, Inc.
6 * All rights reserved.
7 *
8 * Portions of this software were developed by Robert N. M. Watson under

--- 22 unchanged lines hidden (view full) ---

31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
36 */
37
38#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1982, 1986, 1988, 1993
3 * The Regents of the University of California.
4 * Copyright (c) 2006-2007 Robert N. M. Watson
5 * Copyright (c) 2010-2011 Juniper Networks, Inc.
6 * All rights reserved.
7 *
8 * Portions of this software were developed by Robert N. M. Watson under

--- 22 unchanged lines hidden (view full) ---

31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/sys/netinet/tcp_usrreq.c 289276 2015-10-14 00:35:37Z hiren $");
39__FBSDID("$FreeBSD: head/sys/netinet/tcp_usrreq.c 292309 2015-12-16 00:56:45Z rrs $");
40
41#include "opt_ddb.h"
42#include "opt_inet.h"
43#include "opt_inet6.h"
44#include "opt_tcpdebug.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/limits.h>
49#include <sys/malloc.h>
40
41#include "opt_ddb.h"
42#include "opt_inet.h"
43#include "opt_inet6.h"
44#include "opt_tcpdebug.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/limits.h>
49#include <sys/malloc.h>
50#include <sys/refcount.h>
50#include <sys/kernel.h>
51#include <sys/sysctl.h>
52#include <sys/mbuf.h>
53#ifdef INET6
54#include <sys/domain.h>
55#endif /* INET6 */
56#include <sys/socket.h>
57#include <sys/socketvar.h>

--- 446 unchanged lines hidden (view full) ---

504 goto out;
505#ifdef TCP_OFFLOAD
506 if (registered_toedevs > 0 &&
507 (so->so_options & SO_NO_OFFLOAD) == 0 &&
508 (error = tcp_offload_connect(so, nam)) == 0)
509 goto out;
510#endif
511 tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
51#include <sys/kernel.h>
52#include <sys/sysctl.h>
53#include <sys/mbuf.h>
54#ifdef INET6
55#include <sys/domain.h>
56#endif /* INET6 */
57#include <sys/socket.h>
58#include <sys/socketvar.h>

--- 446 unchanged lines hidden (view full) ---

505 goto out;
506#ifdef TCP_OFFLOAD
507 if (registered_toedevs > 0 &&
508 (so->so_options & SO_NO_OFFLOAD) == 0 &&
509 (error = tcp_offload_connect(so, nam)) == 0)
510 goto out;
511#endif
512 tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
512 error = tcp_output(tp);
513 error = tp->t_fb->tfb_tcp_output(tp);
513out:
514 TCPDEBUG2(PRU_CONNECT);
515 INP_WUNLOCK(inp);
516 return (error);
517}
518#endif /* INET */
519
520#ifdef INET6

--- 53 unchanged lines hidden (view full) ---

574 if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0)
575 goto out;
576#ifdef TCP_OFFLOAD
577 if (registered_toedevs > 0 &&
578 (so->so_options & SO_NO_OFFLOAD) == 0 &&
579 (error = tcp_offload_connect(so, nam)) == 0)
580 goto out;
581#endif
514out:
515 TCPDEBUG2(PRU_CONNECT);
516 INP_WUNLOCK(inp);
517 return (error);
518}
519#endif /* INET */
520
521#ifdef INET6

--- 53 unchanged lines hidden (view full) ---

575 if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0)
576 goto out;
577#ifdef TCP_OFFLOAD
578 if (registered_toedevs > 0 &&
579 (so->so_options & SO_NO_OFFLOAD) == 0 &&
580 (error = tcp_offload_connect(so, nam)) == 0)
581 goto out;
582#endif
582 error = tcp_output(tp);
583 error = tp->t_fb->tfb_tcp_output(tp);
583 goto out;
584 }
585#endif
586 inp->inp_vflag &= ~INP_IPV4;
587 inp->inp_vflag |= INP_IPV6;
588 inp->inp_inc.inc_flags |= INC_ISIPV6;
589 if ((error = prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr)) != 0)
590 goto out;
591 if ((error = tcp6_connect(tp, nam, td)) != 0)
592 goto out;
593#ifdef TCP_OFFLOAD
594 if (registered_toedevs > 0 &&
595 (so->so_options & SO_NO_OFFLOAD) == 0 &&
596 (error = tcp_offload_connect(so, nam)) == 0)
597 goto out;
598#endif
599 tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
584 goto out;
585 }
586#endif
587 inp->inp_vflag &= ~INP_IPV4;
588 inp->inp_vflag |= INP_IPV6;
589 inp->inp_inc.inc_flags |= INC_ISIPV6;
590 if ((error = prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr)) != 0)
591 goto out;
592 if ((error = tcp6_connect(tp, nam, td)) != 0)
593 goto out;
594#ifdef TCP_OFFLOAD
595 if (registered_toedevs > 0 &&
596 (so->so_options & SO_NO_OFFLOAD) == 0 &&
597 (error = tcp_offload_connect(so, nam)) == 0)
598 goto out;
599#endif
600 tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
600 error = tcp_output(tp);
601 error = tp->t_fb->tfb_tcp_output(tp);
601
602out:
603 TCPDEBUG2(PRU_CONNECT);
604 TCP_PROBE2(debug__user, tp, PRU_CONNECT);
605 INP_WUNLOCK(inp);
606 return (error);
607}
608#endif /* INET6 */

--- 159 unchanged lines hidden (view full) ---

768 error = ECONNRESET;
769 goto out;
770 }
771 tp = intotcpcb(inp);
772 TCPDEBUG1();
773 socantsendmore(so);
774 tcp_usrclosed(tp);
775 if (!(inp->inp_flags & INP_DROPPED))
602
603out:
604 TCPDEBUG2(PRU_CONNECT);
605 TCP_PROBE2(debug__user, tp, PRU_CONNECT);
606 INP_WUNLOCK(inp);
607 return (error);
608}
609#endif /* INET6 */

--- 159 unchanged lines hidden (view full) ---

769 error = ECONNRESET;
770 goto out;
771 }
772 tp = intotcpcb(inp);
773 TCPDEBUG1();
774 socantsendmore(so);
775 tcp_usrclosed(tp);
776 if (!(inp->inp_flags & INP_DROPPED))
776 error = tcp_output(tp);
777 error = tp->t_fb->tfb_tcp_output(tp);
777
778out:
779 TCPDEBUG2(PRU_SHUTDOWN);
780 TCP_PROBE2(debug__user, tp, PRU_SHUTDOWN);
781 INP_WUNLOCK(inp);
782 INP_INFO_RUNLOCK(&V_tcbinfo);
783
784 return (error);

--- 19 unchanged lines hidden (view full) ---

804 }
805 tp = intotcpcb(inp);
806 TCPDEBUG1();
807#ifdef TCP_OFFLOAD
808 if (tp->t_flags & TF_TOE)
809 tcp_offload_rcvd(tp);
810 else
811#endif
778
779out:
780 TCPDEBUG2(PRU_SHUTDOWN);
781 TCP_PROBE2(debug__user, tp, PRU_SHUTDOWN);
782 INP_WUNLOCK(inp);
783 INP_INFO_RUNLOCK(&V_tcbinfo);
784
785 return (error);

--- 19 unchanged lines hidden (view full) ---

805 }
806 tp = intotcpcb(inp);
807 TCPDEBUG1();
808#ifdef TCP_OFFLOAD
809 if (tp->t_flags & TF_TOE)
810 tcp_offload_rcvd(tp);
811 else
812#endif
812 tcp_output(tp);
813 tp->t_fb->tfb_tcp_output(tp);
813
814out:
815 TCPDEBUG2(PRU_RCVD);
816 TCP_PROBE2(debug__user, tp, PRU_RCVD);
817 INP_WUNLOCK(inp);
818 return (error);
819}
820

--- 85 unchanged lines hidden (view full) ---

906 INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
907 socantsendmore(so);
908 tcp_usrclosed(tp);
909 }
910 if (!(inp->inp_flags & INP_DROPPED) &&
911 !(flags & PRUS_NOTREADY)) {
912 if (flags & PRUS_MORETOCOME)
913 tp->t_flags |= TF_MORETOCOME;
814
815out:
816 TCPDEBUG2(PRU_RCVD);
817 TCP_PROBE2(debug__user, tp, PRU_RCVD);
818 INP_WUNLOCK(inp);
819 return (error);
820}
821

--- 85 unchanged lines hidden (view full) ---

907 INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
908 socantsendmore(so);
909 tcp_usrclosed(tp);
910 }
911 if (!(inp->inp_flags & INP_DROPPED) &&
912 !(flags & PRUS_NOTREADY)) {
913 if (flags & PRUS_MORETOCOME)
914 tp->t_flags |= TF_MORETOCOME;
914 error = tcp_output(tp);
915 error = tp->t_fb->tfb_tcp_output(tp);
915 if (flags & PRUS_MORETOCOME)
916 tp->t_flags &= ~TF_MORETOCOME;
917 }
918 } else {
919 /*
920 * XXXRW: PRUS_EOF not implemented with PRUS_OOB?
921 */
922 SOCKBUF_LOCK(&so->so_snd);

--- 33 unchanged lines hidden (view full) ---

956 if (error)
957 goto out;
958 tp->snd_wnd = TTCP_CLIENT_SND_WND;
959 tcp_mss(tp, -1);
960 }
961 tp->snd_up = tp->snd_una + sbavail(&so->so_snd);
962 if (!(flags & PRUS_NOTREADY)) {
963 tp->t_flags |= TF_FORCEDATA;
916 if (flags & PRUS_MORETOCOME)
917 tp->t_flags &= ~TF_MORETOCOME;
918 }
919 } else {
920 /*
921 * XXXRW: PRUS_EOF not implemented with PRUS_OOB?
922 */
923 SOCKBUF_LOCK(&so->so_snd);

--- 33 unchanged lines hidden (view full) ---

957 if (error)
958 goto out;
959 tp->snd_wnd = TTCP_CLIENT_SND_WND;
960 tcp_mss(tp, -1);
961 }
962 tp->snd_up = tp->snd_una + sbavail(&so->so_snd);
963 if (!(flags & PRUS_NOTREADY)) {
964 tp->t_flags |= TF_FORCEDATA;
964 error = tcp_output(tp);
965 error = tp->t_fb->tfb_tcp_output(tp);
965 tp->t_flags &= ~TF_FORCEDATA;
966 }
967 }
968out:
969 TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB :
970 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
971 TCP_PROBE2(debug__user, tp, (flags & PRUS_OOB) ? PRU_SENDOOB :
972 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));

--- 19 unchanged lines hidden (view full) ---

992 return (ECONNRESET);
993 }
994 tp = intotcpcb(inp);
995
996 SOCKBUF_LOCK(&so->so_snd);
997 error = sbready(&so->so_snd, m, count);
998 SOCKBUF_UNLOCK(&so->so_snd);
999 if (error == 0)
966 tp->t_flags &= ~TF_FORCEDATA;
967 }
968 }
969out:
970 TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB :
971 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
972 TCP_PROBE2(debug__user, tp, (flags & PRUS_OOB) ? PRU_SENDOOB :
973 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));

--- 19 unchanged lines hidden (view full) ---

993 return (ECONNRESET);
994 }
995 tp = intotcpcb(inp);
996
997 SOCKBUF_LOCK(&so->so_snd);
998 error = sbready(&so->so_snd, m, count);
999 SOCKBUF_UNLOCK(&so->so_snd);
1000 if (error == 0)
1000 error = tcp_output(tp);
1001 error = tp->t_fb->tfb_tcp_output(tp);
1001 INP_WUNLOCK(inp);
1002
1003 return (error);
1004}
1005
1006/*
1007 * Abort the TCP. Drop the connection abruptly.
1008 */

--- 335 unchanged lines hidden (view full) ---

1344 return (ECONNRESET); \
1345 } \
1346 tp = intotcpcb(inp); \
1347} while(0)
1348
1349int
1350tcp_ctloutput(struct socket *so, struct sockopt *sopt)
1351{
1002 INP_WUNLOCK(inp);
1003
1004 return (error);
1005}
1006
1007/*
1008 * Abort the TCP. Drop the connection abruptly.
1009 */

--- 335 unchanged lines hidden (view full) ---

1345 return (ECONNRESET); \
1346 } \
1347 tp = intotcpcb(inp); \
1348} while(0)
1349
1350int
1351tcp_ctloutput(struct socket *so, struct sockopt *sopt)
1352{
1352 int error, opt, optval;
1353 u_int ui;
1353 int error;
1354 struct inpcb *inp;
1355 struct tcpcb *tp;
1354 struct inpcb *inp;
1355 struct tcpcb *tp;
1356 struct tcp_info ti;
1357 char buf[TCP_CA_NAME_MAX];
1358 struct cc_algo *algo;
1356 struct tcp_function_block *blk;
1357 struct tcp_function_set fsn;
1359
1360 error = 0;
1361 inp = sotoinpcb(so);
1362 KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL"));
1363 INP_WLOCK(inp);
1364 if (sopt->sopt_level != IPPROTO_TCP) {
1365#ifdef INET6
1366 if (inp->inp_vflag & INP_IPV6PROTO) {

--- 11 unchanged lines hidden (view full) ---

1378 }
1379#endif
1380 return (error);
1381 }
1382 if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
1383 INP_WUNLOCK(inp);
1384 return (ECONNRESET);
1385 }
1358
1359 error = 0;
1360 inp = sotoinpcb(so);
1361 KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL"));
1362 INP_WLOCK(inp);
1363 if (sopt->sopt_level != IPPROTO_TCP) {
1364#ifdef INET6
1365 if (inp->inp_vflag & INP_IPV6PROTO) {

--- 11 unchanged lines hidden (view full) ---

1377 }
1378#endif
1379 return (error);
1380 }
1381 if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
1382 INP_WUNLOCK(inp);
1383 return (ECONNRESET);
1384 }
1385 tp = intotcpcb(inp);
1386 /*
1387 * Protect the TCP option TCP_FUNCTION_BLK so
1388 * that a sub-function can *never* overwrite this.
1389 */
1390 if ((sopt->sopt_dir == SOPT_SET) &&
1391 (sopt->sopt_name == TCP_FUNCTION_BLK)) {
1392 INP_WUNLOCK(inp);
1393 error = sooptcopyin(sopt, &fsn, sizeof fsn,
1394 sizeof fsn);
1395 if (error)
1396 return (error);
1397 INP_WLOCK_RECHECK(inp);
1398 if (tp->t_state != TCPS_CLOSED) {
1399 /*
1400 * The user has advanced the state
1401 * past the initial point, we can't
1402 * switch since we are down the road
1403 * and a new set of functions may
1404 * not be compatibile.
1405 */
1406 INP_WUNLOCK(inp);
1407 return(EINVAL);
1408 }
1409 blk = find_and_ref_tcp_functions(&fsn);
1410 if (blk == NULL) {
1411 INP_WUNLOCK(inp);
1412 return (ENOENT);
1413 }
1414 if (tp->t_fb != blk) {
1415 if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) {
1416 refcount_release(&blk->tfb_refcnt);
1417 INP_WUNLOCK(inp);
1418 return (ENOENT);
1419 }
1420 /*
1421 * Release the old refcnt, the
1422 * lookup acquires a ref on the
1423 * new one.
1424 */
1425 if (tp->t_fb->tfb_tcp_fb_fini)
1426 (*tp->t_fb->tfb_tcp_fb_fini)(tp);
1427 refcount_release(&tp->t_fb->tfb_refcnt);
1428 tp->t_fb = blk;
1429 if (tp->t_fb->tfb_tcp_fb_init) {
1430 (*tp->t_fb->tfb_tcp_fb_init)(tp);
1431 }
1432 }
1433#ifdef TCP_OFFLOAD
1434 if (tp->t_flags & TF_TOE) {
1435 tcp_offload_ctloutput(tp, sopt->sopt_dir,
1436 sopt->sopt_name);
1437 }
1438#endif
1439 INP_WUNLOCK(inp);
1440 return (error);
1441 } else if ((sopt->sopt_dir == SOPT_GET) &&
1442 (sopt->sopt_name == TCP_FUNCTION_BLK)) {
1443 strcpy(fsn.function_set_name, tp->t_fb->tfb_tcp_block_name);
1444 fsn.pcbcnt = tp->t_fb->tfb_refcnt;
1445 INP_WUNLOCK(inp);
1446 error = sooptcopyout(sopt, &fsn, sizeof fsn);
1447 return (error);
1448 }
1449 /* Pass in the INP locked, called must unlock it */
1450 return (tp->t_fb->tfb_tcp_ctloutput(so, sopt, inp, tp));
1451}
1386
1452
1453int
1454tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp)
1455{
1456 int error, opt, optval;
1457 u_int ui;
1458 struct tcp_info ti;
1459 struct cc_algo *algo;
1460 char buf[TCP_CA_NAME_MAX];
1461
1387 switch (sopt->sopt_dir) {
1388 case SOPT_SET:
1389 switch (sopt->sopt_name) {
1390#ifdef TCP_SIGNATURE
1391 case TCP_MD5SIG:
1392 INP_WUNLOCK(inp);
1393 error = sooptcopyin(sopt, &optval, sizeof optval,
1394 sizeof optval);

--- 51 unchanged lines hidden (view full) ---

1446 return (error);
1447
1448 INP_WLOCK_RECHECK(inp);
1449 if (optval)
1450 tp->t_flags |= TF_NOPUSH;
1451 else if (tp->t_flags & TF_NOPUSH) {
1452 tp->t_flags &= ~TF_NOPUSH;
1453 if (TCPS_HAVEESTABLISHED(tp->t_state))
1462 switch (sopt->sopt_dir) {
1463 case SOPT_SET:
1464 switch (sopt->sopt_name) {
1465#ifdef TCP_SIGNATURE
1466 case TCP_MD5SIG:
1467 INP_WUNLOCK(inp);
1468 error = sooptcopyin(sopt, &optval, sizeof optval,
1469 sizeof optval);

--- 51 unchanged lines hidden (view full) ---

1521 return (error);
1522
1523 INP_WLOCK_RECHECK(inp);
1524 if (optval)
1525 tp->t_flags |= TF_NOPUSH;
1526 else if (tp->t_flags & TF_NOPUSH) {
1527 tp->t_flags &= ~TF_NOPUSH;
1528 if (TCPS_HAVEESTABLISHED(tp->t_state))
1454 error = tcp_output(tp);
1529 error = tp->t_fb->tfb_tcp_output(tp);
1455 }
1456 goto unlock_and_done;
1457
1458 case TCP_MAXSEG:
1459 INP_WUNLOCK(inp);
1460 error = sooptcopyin(sopt, &optval, sizeof optval,
1461 sizeof optval);
1462 if (error)

--- 302 unchanged lines hidden (view full) ---

1765 tp = tcp_drop(tp, 0);
1766 KASSERT(tp != NULL,
1767 ("tcp_disconnect: tcp_drop() returned NULL"));
1768 } else {
1769 soisdisconnecting(so);
1770 sbflush(&so->so_rcv);
1771 tcp_usrclosed(tp);
1772 if (!(inp->inp_flags & INP_DROPPED))
1530 }
1531 goto unlock_and_done;
1532
1533 case TCP_MAXSEG:
1534 INP_WUNLOCK(inp);
1535 error = sooptcopyin(sopt, &optval, sizeof optval,
1536 sizeof optval);
1537 if (error)

--- 302 unchanged lines hidden (view full) ---

1840 tp = tcp_drop(tp, 0);
1841 KASSERT(tp != NULL,
1842 ("tcp_disconnect: tcp_drop() returned NULL"));
1843 } else {
1844 soisdisconnecting(so);
1845 sbflush(&so->so_rcv);
1846 tcp_usrclosed(tp);
1847 if (!(inp->inp_flags & INP_DROPPED))
1773 tcp_output(tp);
1848 tp->t_fb->tfb_tcp_output(tp);
1774 }
1775}
1776
1777/*
1778 * User issued close, and wish to trail through shutdown states:
1779 * if never received SYN, just forget it. If got a SYN from peer,
1780 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
1781 * If already got a FIN from peer, then almost done; go to LAST_ACK

--- 366 unchanged lines hidden ---
1849 }
1850}
1851
1852/*
1853 * User issued close, and wish to trail through shutdown states:
1854 * if never received SYN, just forget it. If got a SYN from peer,
1855 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
1856 * If already got a FIN from peer, then almost done; go to LAST_ACK

--- 366 unchanged lines hidden ---