Print this page
tcp: maybe related to 721fffe3


  37 #include <sys/tihdr.h>
  38 #include <sys/timod.h>
  39 #include <sys/tpicommon.h>
  40 #include <sys/socketvar.h>
  41 
  42 #include <inet/common.h>
  43 #include <inet/proto_set.h>
  44 #include <inet/ip.h>
  45 #include <inet/tcp.h>
  46 #include <inet/tcp_impl.h>
  47 
  48 static void     tcp_activate(sock_lower_handle_t, sock_upper_handle_t,
  49                     sock_upcalls_t *, int, cred_t *);
  50 static int      tcp_accept(sock_lower_handle_t, sock_lower_handle_t,
  51                     sock_upper_handle_t, cred_t *);
  52 static int      tcp_bind(sock_lower_handle_t, struct sockaddr *,
  53                     socklen_t, cred_t *);
  54 static int      tcp_listen(sock_lower_handle_t, int, cred_t *);
  55 static int      tcp_connect(sock_lower_handle_t, const struct sockaddr *,
  56                     socklen_t, sock_connid_t *, cred_t *);




  57 static int      tcp_getsockopt(sock_lower_handle_t, int, int, void *,
  58                     socklen_t *, cred_t *);
  59 static int      tcp_setsockopt(sock_lower_handle_t, int, int, const void *,
  60                     socklen_t, cred_t *);
  61 static int      tcp_sendmsg(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
  62                     cred_t *cr);
  63 static int      tcp_shutdown(sock_lower_handle_t, int, cred_t *);
  64 static void     tcp_clr_flowctrl(sock_lower_handle_t);
  65 static int      tcp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
  66                     cred_t *);
  67 static int      tcp_close(sock_lower_handle_t, int, cred_t *);
  68 
  69 sock_downcalls_t sock_tcp_downcalls = {
  70         tcp_activate,
  71         tcp_accept,
  72         tcp_bind,
  73         tcp_listen,
  74         tcp_connect,
  75         tcp_getpeername,
  76         tcp_getsockname,
  77         tcp_getsockopt,
  78         tcp_setsockopt,
  79         tcp_sendmsg,
  80         NULL,
  81         NULL,
  82         NULL,


 310                                 error = EOPNOTSUPP;
 311                                 break;
 312                         default:
 313                                 error = EINVAL;
 314                                 break;
 315                         }
 316                 } else {
 317                         error = proto_tlitosyserr(-error);
 318                 }
 319         }
 320 
 321         if (connp->conn_tcp->tcp_loopback) {
 322                 struct sock_proto_props sopp;
 323 
 324                 sopp.sopp_flags = SOCKOPT_LOOPBACK;
 325                 sopp.sopp_loopback = B_TRUE;
 326 
 327                 (*connp->conn_upcalls->su_set_proto_props)(
 328                     connp->conn_upper_handle, &sopp);
 329         }
 330 done:
 331         squeue_synch_exit(connp);
 332 
 333         return ((error == 0) ? EINPROGRESS : error);
 334 }
 335 
 336 /* ARGSUSED3 */
 337 int
 338 tcp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
 339     socklen_t *addrlenp, cred_t *cr)
 340 {
 341         conn_t  *connp = (conn_t *)proto_handle;
 342         tcp_t   *tcp = connp->conn_tcp;
 343 
 344         /* All Solaris components should pass a cred for this operation. */
 345         ASSERT(cr != NULL);
 346 
 347         ASSERT(tcp != NULL);
 348         if (tcp->tcp_state < TCPS_SYN_RCVD)
 349                 return (ENOTCONN);
 350 


 735          * We can't assert the references because there might be other
 736          * transient reference places because of some walkers or queued
 737          * packets in squeue for the timewait state.
 738          */
 739         CONN_DEC_REF(connp);
 740 
 741         /*
 742          * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
 743          * freeing the socket.
 744          */
 745         return (EINPROGRESS);
 746 }
 747 
 748 /* ARGSUSED */
 749 sock_lower_handle_t
 750 tcp_create(int family, int type, int proto, sock_downcalls_t **sock_downcalls,
 751     uint_t *smodep, int *errorp, int flags, cred_t *credp)
 752 {
 753         conn_t          *connp;
 754         boolean_t       isv6 = family == AF_INET6;

 755         if (type != SOCK_STREAM || (family != AF_INET && family != AF_INET6) ||
 756             (proto != 0 && proto != IPPROTO_TCP)) {
 757                 *errorp = EPROTONOSUPPORT;
 758                 return (NULL);
 759         }
 760 
 761         connp = tcp_create_common(credp, isv6, B_TRUE, errorp);
 762         if (connp == NULL) {
 763                 return (NULL);
 764         }
 765 
 766         /*
 767          * Put the ref for TCP. Ref for IP was already put
 768          * by ipcl_conn_create. Also Make the conn_t globally
 769          * visible to walkers
 770          */
 771         mutex_enter(&connp->conn_lock);
 772         CONN_INC_REF_LOCKED(connp);
 773         ASSERT(connp->conn_ref == 2);
 774         connp->conn_state_flags &= ~CONN_INCIPIENT;
 775 
 776         connp->conn_flags |= IPCL_NONSTR;
 777         mutex_exit(&connp->conn_lock);
 778 
 779         ASSERT(errorp != NULL);
 780         *errorp = 0;
 781         *sock_downcalls = &sock_tcp_downcalls;
 782         *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
 783             SM_SENDFILESUPP;
 784 
 785         return ((sock_lower_handle_t)connp);
 786 }
 787 
 788 /*
 789  * tcp_fallback




  37 #include <sys/tihdr.h>
  38 #include <sys/timod.h>
  39 #include <sys/tpicommon.h>
  40 #include <sys/socketvar.h>
  41 
  42 #include <inet/common.h>
  43 #include <inet/proto_set.h>
  44 #include <inet/ip.h>
  45 #include <inet/tcp.h>
  46 #include <inet/tcp_impl.h>
  47 
  48 static void     tcp_activate(sock_lower_handle_t, sock_upper_handle_t,
  49                     sock_upcalls_t *, int, cred_t *);
  50 static int      tcp_accept(sock_lower_handle_t, sock_lower_handle_t,
  51                     sock_upper_handle_t, cred_t *);
  52 static int      tcp_bind(sock_lower_handle_t, struct sockaddr *,
  53                     socklen_t, cred_t *);
  54 static int      tcp_listen(sock_lower_handle_t, int, cred_t *);
  55 static int      tcp_connect(sock_lower_handle_t, const struct sockaddr *,
  56                     socklen_t, sock_connid_t *, cred_t *);
  57 static int      tcp_getpeername(sock_lower_handle_t, struct sockaddr *,
  58                     socklen_t *, cred_t *);
  59 static int      tcp_getsockname(sock_lower_handle_t, struct sockaddr *,
  60                     socklen_t *, cred_t *);
  61 static int      tcp_getsockopt(sock_lower_handle_t, int, int, void *,
  62                     socklen_t *, cred_t *);
  63 static int      tcp_setsockopt(sock_lower_handle_t, int, int, const void *,
  64                     socklen_t, cred_t *);
  65 static int      tcp_sendmsg(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
  66                     cred_t *);
  67 static int      tcp_shutdown(sock_lower_handle_t, int, cred_t *);
  68 static void     tcp_clr_flowctrl(sock_lower_handle_t);
  69 static int      tcp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
  70                     cred_t *);
  71 static int      tcp_close(sock_lower_handle_t, int, cred_t *);
  72 
  73 sock_downcalls_t sock_tcp_downcalls = {
  74         tcp_activate,
  75         tcp_accept,
  76         tcp_bind,
  77         tcp_listen,
  78         tcp_connect,
  79         tcp_getpeername,
  80         tcp_getsockname,
  81         tcp_getsockopt,
  82         tcp_setsockopt,
  83         tcp_sendmsg,
  84         NULL,
  85         NULL,
  86         NULL,


 314                                 error = EOPNOTSUPP;
 315                                 break;
 316                         default:
 317                                 error = EINVAL;
 318                                 break;
 319                         }
 320                 } else {
 321                         error = proto_tlitosyserr(-error);
 322                 }
 323         }
 324 
 325         if (connp->conn_tcp->tcp_loopback) {
 326                 struct sock_proto_props sopp;
 327 
 328                 sopp.sopp_flags = SOCKOPT_LOOPBACK;
 329                 sopp.sopp_loopback = B_TRUE;
 330 
 331                 (*connp->conn_upcalls->su_set_proto_props)(
 332                     connp->conn_upper_handle, &sopp);
 333         }

 334         squeue_synch_exit(connp);
 335 
 336         return ((error == 0) ? EINPROGRESS : error);
 337 }
 338 
 339 /* ARGSUSED3 */
 340 int
 341 tcp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
 342     socklen_t *addrlenp, cred_t *cr)
 343 {
 344         conn_t  *connp = (conn_t *)proto_handle;
 345         tcp_t   *tcp = connp->conn_tcp;
 346 
 347         /* All Solaris components should pass a cred for this operation. */
 348         ASSERT(cr != NULL);
 349 
 350         ASSERT(tcp != NULL);
 351         if (tcp->tcp_state < TCPS_SYN_RCVD)
 352                 return (ENOTCONN);
 353 


 738          * We can't assert the references because there might be other
 739          * transient reference places because of some walkers or queued
 740          * packets in squeue for the timewait state.
 741          */
 742         CONN_DEC_REF(connp);
 743 
 744         /*
 745          * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
 746          * freeing the socket.
 747          */
 748         return (EINPROGRESS);
 749 }
 750 
 751 /* ARGSUSED */
 752 sock_lower_handle_t
 753 tcp_create(int family, int type, int proto, sock_downcalls_t **sock_downcalls,
 754     uint_t *smodep, int *errorp, int flags, cred_t *credp)
 755 {
 756         conn_t          *connp;
 757         boolean_t       isv6 = family == AF_INET6;
 758 
 759         if (type != SOCK_STREAM || (family != AF_INET && family != AF_INET6) ||
 760             (proto != 0 && proto != IPPROTO_TCP)) {
 761                 *errorp = EPROTONOSUPPORT;
 762                 return (NULL);
 763         }
 764 
 765         connp = tcp_create_common(credp, isv6, B_TRUE, errorp);
 766         if (connp == NULL) {
 767                 return (NULL);
 768         }
 769 
 770         /*
 771          * Put the ref for TCP. Ref for IP was already put
 772          * by ipcl_conn_create. Also make the conn_t globally
 773          * visible to walkers.
 774          */
 775         mutex_enter(&connp->conn_lock);
 776         CONN_INC_REF_LOCKED(connp);
 777         ASSERT(connp->conn_ref == 2);
 778         connp->conn_state_flags &= ~CONN_INCIPIENT;
 779 
 780         connp->conn_flags |= IPCL_NONSTR;
 781         mutex_exit(&connp->conn_lock);
 782 
 783         ASSERT(errorp != NULL);
 784         *errorp = 0;
 785         *sock_downcalls = &sock_tcp_downcalls;
 786         *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
 787             SM_SENDFILESUPP;
 788 
 789         return ((sock_lower_handle_t)connp);
 790 }
 791 
 792 /*
 793  * tcp_fallback