Print this page
4596 Callers of ip_srcid_find_id() need to be more careful


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, Joyent Inc. All rights reserved.
  25  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
  26  * Copyright (c) 2013 by Delphix. All rights reserved.

  27  */
  28 /* Copyright (c) 1990 Mentat Inc. */
  29 
  30 #include <sys/types.h>
  31 #include <sys/stream.h>
  32 #include <sys/strsun.h>
  33 #include <sys/strsubr.h>
  34 #include <sys/stropts.h>
  35 #include <sys/strlog.h>
  36 #define _SUN_TPI_VERSION 2
  37 #include <sys/tihdr.h>
  38 #include <sys/timod.h>
  39 #include <sys/ddi.h>
  40 #include <sys/sunddi.h>
  41 #include <sys/suntpi.h>
  42 #include <sys/xti_inet.h>
  43 #include <sys/cmn_err.h>
  44 #include <sys/debug.h>
  45 #include <sys/sdt.h>
  46 #include <sys/vtrace.h>


1566                 /*
1567                  * SunOS 4.x and 4.3 BSD allow an application
1568                  * to connect a TCP socket to INADDR_ANY.
1569                  * When they do this, the kernel picks the
1570                  * address of one interface and uses it
1571                  * instead.  The kernel usually ends up
1572                  * picking the address of the loopback
1573                  * interface.  This is an undocumented feature.
1574                  * However, we provide the same thing here
1575                  * in order to have source and binary
1576                  * compatibility with SunOS 4.x.
1577                  * Update the T_CONN_REQ (sin/sin6) since it is used to
1578                  * generate the T_CONN_CON.
1579                  */
1580                 dstaddr = htonl(INADDR_LOOPBACK);
1581                 *dstaddrp = dstaddr;
1582         }
1583 
1584         /* Handle __sin6_src_id if socket not bound to an IP address */
1585         if (srcid != 0 && connp->conn_laddr_v4 == INADDR_ANY) {
1586                 ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
1587                     IPCL_ZONEID(connp), tcps->tcps_netstack);



1588                 connp->conn_saddr_v6 = connp->conn_laddr_v6;
1589         }
1590 
1591         IN6_IPADDR_TO_V4MAPPED(dstaddr, &connp->conn_faddr_v6);
1592         connp->conn_fport = dstport;
1593 
1594         /*
1595          * At this point the remote destination address and remote port fields
1596          * in the tcp-four-tuple have been filled in the tcp structure. Now we
1597          * have to see which state tcp was in so we can take appropriate action.
1598          */
1599         if (tcp->tcp_state == TCPS_IDLE) {
1600                 /*
1601                  * We support a quick connect capability here, allowing
1602                  * clients to transition directly from IDLE to SYN_SENT
1603                  * tcp_bindi will pick an unused port, insert the connection
1604                  * in the bind hash and transition to BOUND state.
1605                  */
1606                 lport = tcp_update_next_port(tcps->tcps_next_port_to_try,
1607                     tcp, B_TRUE);


1648 
1649         /*
1650          * If we're here, it means that the destination address is a native
1651          * IPv6 address.  Return an error if conn_ipversion is not IPv6.  A
1652          * reason why it might not be IPv6 is if the socket was bound to an
1653          * IPv4-mapped IPv6 address.
1654          */
1655         if (connp->conn_ipversion != IPV6_VERSION)
1656                 return (-TBADADDR);
1657 
1658         /*
1659          * Interpret a zero destination to mean loopback.
1660          * Update the T_CONN_REQ (sin/sin6) since it is used to
1661          * generate the T_CONN_CON.
1662          */
1663         if (IN6_IS_ADDR_UNSPECIFIED(dstaddrp))
1664                 *dstaddrp = ipv6_loopback;
1665 
1666         /* Handle __sin6_src_id if socket not bound to an IP address */
1667         if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
1668                 ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
1669                     IPCL_ZONEID(connp), tcps->tcps_netstack);



1670                 connp->conn_saddr_v6 = connp->conn_laddr_v6;
1671         }
1672 
1673         /*
1674          * Take care of the scope_id now.
1675          */
1676         if (scope_id != 0 && IN6_IS_ADDR_LINKSCOPE(dstaddrp)) {
1677                 connp->conn_ixa->ixa_flags |= IXAF_SCOPEID_SET;
1678                 connp->conn_ixa->ixa_scopeid = scope_id;
1679         } else {
1680                 connp->conn_ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
1681         }
1682 
1683         connp->conn_flowinfo = flowinfo;
1684         connp->conn_faddr_v6 = *dstaddrp;
1685         connp->conn_fport = dstport;
1686 
1687         /*
1688          * At this point the remote destination address and remote port fields
1689          * in the tcp-four-tuple have been filled in the tcp structure. Now we




   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, Joyent Inc. All rights reserved.
  25  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
  26  * Copyright (c) 2013 by Delphix. All rights reserved.
  27  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  28  */
  29 /* Copyright (c) 1990 Mentat Inc. */
  30 
  31 #include <sys/types.h>
  32 #include <sys/stream.h>
  33 #include <sys/strsun.h>
  34 #include <sys/strsubr.h>
  35 #include <sys/stropts.h>
  36 #include <sys/strlog.h>
  37 #define _SUN_TPI_VERSION 2
  38 #include <sys/tihdr.h>
  39 #include <sys/timod.h>
  40 #include <sys/ddi.h>
  41 #include <sys/sunddi.h>
  42 #include <sys/suntpi.h>
  43 #include <sys/xti_inet.h>
  44 #include <sys/cmn_err.h>
  45 #include <sys/debug.h>
  46 #include <sys/sdt.h>
  47 #include <sys/vtrace.h>


1567                 /*
1568                  * SunOS 4.x and 4.3 BSD allow an application
1569                  * to connect a TCP socket to INADDR_ANY.
1570                  * When they do this, the kernel picks the
1571                  * address of one interface and uses it
1572                  * instead.  The kernel usually ends up
1573                  * picking the address of the loopback
1574                  * interface.  This is an undocumented feature.
1575                  * However, we provide the same thing here
1576                  * in order to have source and binary
1577                  * compatibility with SunOS 4.x.
1578                  * Update the T_CONN_REQ (sin/sin6) since it is used to
1579                  * generate the T_CONN_CON.
1580                  */
1581                 dstaddr = htonl(INADDR_LOOPBACK);
1582                 *dstaddrp = dstaddr;
1583         }
1584 
1585         /* Handle __sin6_src_id if socket not bound to an IP address */
1586         if (srcid != 0 && connp->conn_laddr_v4 == INADDR_ANY) {
1587                 if (!ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
1588                     IPCL_ZONEID(connp), B_TRUE, tcps->tcps_netstack)) {
1589                         /* Mismatch - conn_laddr_v6 would be v6 address. */
1590                         return (EADDRNOTAVAIL);
1591                 }
1592                 connp->conn_saddr_v6 = connp->conn_laddr_v6;
1593         }
1594 
1595         IN6_IPADDR_TO_V4MAPPED(dstaddr, &connp->conn_faddr_v6);
1596         connp->conn_fport = dstport;
1597 
1598         /*
1599          * At this point the remote destination address and remote port fields
1600          * in the tcp-four-tuple have been filled in the tcp structure. Now we
1601          * have to see which state tcp was in so we can take appropriate action.
1602          */
1603         if (tcp->tcp_state == TCPS_IDLE) {
1604                 /*
1605                  * We support a quick connect capability here, allowing
1606                  * clients to transition directly from IDLE to SYN_SENT
1607                  * tcp_bindi will pick an unused port, insert the connection
1608                  * in the bind hash and transition to BOUND state.
1609                  */
1610                 lport = tcp_update_next_port(tcps->tcps_next_port_to_try,
1611                     tcp, B_TRUE);


1652 
1653         /*
1654          * If we're here, it means that the destination address is a native
1655          * IPv6 address.  Return an error if conn_ipversion is not IPv6.  A
1656          * reason why it might not be IPv6 is if the socket was bound to an
1657          * IPv4-mapped IPv6 address.
1658          */
1659         if (connp->conn_ipversion != IPV6_VERSION)
1660                 return (-TBADADDR);
1661 
1662         /*
1663          * Interpret a zero destination to mean loopback.
1664          * Update the T_CONN_REQ (sin/sin6) since it is used to
1665          * generate the T_CONN_CON.
1666          */
1667         if (IN6_IS_ADDR_UNSPECIFIED(dstaddrp))
1668                 *dstaddrp = ipv6_loopback;
1669 
1670         /* Handle __sin6_src_id if socket not bound to an IP address */
1671         if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
1672                 if (!ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
1673                     IPCL_ZONEID(connp), B_FALSE, tcps->tcps_netstack)) {
1674                         /* Mismatch - conn_laddr_v6 would be v4-mapped. */
1675                         return (EADDRNOTAVAIL);
1676                 }
1677                 connp->conn_saddr_v6 = connp->conn_laddr_v6;
1678         }
1679 
1680         /*
1681          * Take care of the scope_id now.
1682          */
1683         if (scope_id != 0 && IN6_IS_ADDR_LINKSCOPE(dstaddrp)) {
1684                 connp->conn_ixa->ixa_flags |= IXAF_SCOPEID_SET;
1685                 connp->conn_ixa->ixa_scopeid = scope_id;
1686         } else {
1687                 connp->conn_ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
1688         }
1689 
1690         connp->conn_flowinfo = flowinfo;
1691         connp->conn_faddr_v6 = *dstaddrp;
1692         connp->conn_fport = dstport;
1693 
1694         /*
1695          * At this point the remote destination address and remote port fields
1696          * in the tcp-four-tuple have been filled in the tcp structure. Now we