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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/udp/udp.c
          +++ new/usr/src/uts/common/inet/udp/udp.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  24   25   */
  25   26  /* Copyright (c) 1990 Mentat Inc. */
  26   27  
  27   28  #include <sys/types.h>
  28   29  #include <sys/stream.h>
  29   30  #include <sys/stropts.h>
  30   31  #include <sys/strlog.h>
  31   32  #include <sys/strsun.h>
  32   33  #define _SUN_TPI_VERSION 2
  33   34  #include <sys/tihdr.h>
↓ open down ↓ 2673 lines elided ↑ open up ↑
2707 2708           * from ip_attr_connect() below.
2708 2709           */
2709 2710          v6src = connp->conn_saddr_v6;
2710 2711          if (sin != NULL) {
2711 2712                  IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
2712 2713                  dstport = sin->sin_port;
2713 2714                  flowinfo = 0;
2714 2715                  ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
2715 2716                  ixa->ixa_flags |= IXAF_IS_IPV4;
2716 2717          } else if (sin6 != NULL) {
     2718 +                boolean_t v4mapped;
     2719 +
2717 2720                  v6dst = sin6->sin6_addr;
2718 2721                  dstport = sin6->sin6_port;
2719 2722                  flowinfo = sin6->sin6_flowinfo;
2720 2723                  srcid = sin6->__sin6_src_id;
2721 2724                  if (IN6_IS_ADDR_LINKSCOPE(&v6dst) && sin6->sin6_scope_id != 0) {
2722 2725                          ixa->ixa_scopeid = sin6->sin6_scope_id;
2723 2726                          ixa->ixa_flags |= IXAF_SCOPEID_SET;
2724 2727                  } else {
2725 2728                          ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
2726 2729                  }
2727      -                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
2728      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
2729      -                            connp->conn_netstack);
2730      -                }
2731      -                if (IN6_IS_ADDR_V4MAPPED(&v6dst))
     2730 +                v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
     2731 +                if (v4mapped)
2732 2732                          ixa->ixa_flags |= IXAF_IS_IPV4;
2733 2733                  else
2734 2734                          ixa->ixa_flags &= ~IXAF_IS_IPV4;
     2735 +                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
     2736 +                        if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
     2737 +                            v4mapped, connp->conn_netstack)) {
     2738 +                                /* Mismatch - v4mapped/v6 specified by srcid. */
     2739 +                                mutex_exit(&connp->conn_lock);
     2740 +                                error = EADDRNOTAVAIL;
     2741 +                                goto failed;    /* Does freemsg() and mib. */
     2742 +                        }
     2743 +                }
2735 2744          } else {
2736 2745                  /* Connected case */
2737 2746                  v6dst = connp->conn_faddr_v6;
2738 2747                  dstport = connp->conn_fport;
2739 2748                  flowinfo = connp->conn_flowinfo;
2740 2749          }
2741 2750          mutex_exit(&connp->conn_lock);
2742 2751  
2743 2752          /* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
2744 2753          if (ipp->ipp_fields & IPPF_ADDR) {
↓ open down ↓ 970 lines elided ↑ open up ↑
3715 3724           * want ip_attr_connect to select a source (since it can fail) when
3716 3725           * IPV6_PKTINFO is specified.
3717 3726           * If this doesn't result in a source address then we get a source
3718 3727           * from ip_attr_connect() below.
3719 3728           */
3720 3729          v6src = connp->conn_saddr_v6;
3721 3730          if (sin != NULL) {
3722 3731                  IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
3723 3732                  dstport = sin->sin_port;
3724 3733                  flowinfo = 0;
     3734 +                /* Don't bother with ip_srcid_find_id(), but indicate anyway. */
3725 3735                  srcid = 0;
3726 3736                  ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
3727      -                if (srcid != 0 && V4_PART_OF_V6(&v6src) == INADDR_ANY) {
3728      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
3729      -                            connp->conn_netstack);
3730      -                }
3731 3737                  ixa->ixa_flags |= IXAF_IS_IPV4;
3732 3738          } else {
     3739 +                boolean_t v4mapped;
     3740 +
3733 3741                  v6dst = sin6->sin6_addr;
3734 3742                  dstport = sin6->sin6_port;
3735 3743                  flowinfo = sin6->sin6_flowinfo;
3736 3744                  srcid = sin6->__sin6_src_id;
3737 3745                  if (IN6_IS_ADDR_LINKSCOPE(&v6dst) && sin6->sin6_scope_id != 0) {
3738 3746                          ixa->ixa_scopeid = sin6->sin6_scope_id;
3739 3747                          ixa->ixa_flags |= IXAF_SCOPEID_SET;
3740 3748                  } else {
3741 3749                          ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
3742 3750                  }
3743      -                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
3744      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
3745      -                            connp->conn_netstack);
3746      -                }
3747      -                if (IN6_IS_ADDR_V4MAPPED(&v6dst))
     3751 +                v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
     3752 +                if (v4mapped)
3748 3753                          ixa->ixa_flags |= IXAF_IS_IPV4;
3749 3754                  else
3750 3755                          ixa->ixa_flags &= ~IXAF_IS_IPV4;
     3756 +                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
     3757 +                        if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
     3758 +                            v4mapped, connp->conn_netstack)) {
     3759 +                                /* Mismatched v4mapped/v6 specified by srcid. */
     3760 +                                mutex_exit(&connp->conn_lock);
     3761 +                                error = EADDRNOTAVAIL;
     3762 +                                goto ud_error;
     3763 +                        }
     3764 +                }
3751 3765          }
3752 3766          /* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
3753 3767          if (connp->conn_xmit_ipp.ipp_fields & IPPF_ADDR) {
3754 3768                  ip_pkt_t *ipp = &connp->conn_xmit_ipp;
3755 3769  
3756 3770                  if (ixa->ixa_flags & IXAF_IS_IPV4) {
3757 3771                          if (IN6_IS_ADDR_V4MAPPED(&ipp->ipp_addr))
3758 3772                                  v6src = ipp->ipp_addr;
3759 3773                  } else {
3760 3774                          if (!IN6_IS_ADDR_V4MAPPED(&ipp->ipp_addr))
↓ open down ↓ 1758 lines elided ↑ open up ↑
5519 5533          udp_t           *udp, *udp1;
5520 5534          ushort_t        ipversion;
5521 5535          udp_stack_t     *us;
5522 5536          int             error;
5523 5537          conn_t          *connp1;
5524 5538          ip_xmit_attr_t  *ixa;
5525 5539          ip_xmit_attr_t  *oldixa;
5526 5540          uint_t          scopeid = 0;
5527 5541          uint_t          srcid = 0;
5528 5542          in6_addr_t      v6src = connp->conn_saddr_v6;
     5543 +        boolean_t       v4mapped;
5529 5544  
5530 5545          udp = connp->conn_udp;
5531 5546          us = udp->udp_us;
5532 5547  
5533 5548          /*
5534 5549           * Address has been verified by the caller
5535 5550           */
5536 5551          switch (len) {
5537 5552          default:
5538 5553                  /*
↓ open down ↓ 8 lines elided ↑ open up ↑
5547 5562                  IN6_IPADDR_TO_V4MAPPED(v4dst, &v6dst);
5548 5563                  ASSERT(connp->conn_ipversion == IPV4_VERSION);
5549 5564                  ipversion = IPV4_VERSION;
5550 5565                  break;
5551 5566  
5552 5567          case sizeof (sin6_t):
5553 5568                  sin6 = (sin6_t *)sa;
5554 5569                  v6dst = sin6->sin6_addr;
5555 5570                  dstport = sin6->sin6_port;
5556 5571                  srcid = sin6->__sin6_src_id;
     5572 +                v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
5557 5573                  if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
5558      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
5559      -                            connp->conn_netstack);
     5574 +                        if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
     5575 +                            v4mapped, connp->conn_netstack)) {
     5576 +                                /* Mismatch v4mapped/v6 specified by srcid. */
     5577 +                                return (EADDRNOTAVAIL);
     5578 +                        }
5560 5579                  }
5561      -                if (IN6_IS_ADDR_V4MAPPED(&v6dst)) {
     5580 +                if (v4mapped) {
5562 5581                          if (connp->conn_ipv6_v6only)
5563 5582                                  return (EADDRNOTAVAIL);
5564 5583  
5565 5584                          /*
5566 5585                           * Destination adress is mapped IPv6 address.
5567 5586                           * Source bound address should be unspecified or
5568 5587                           * IPv6 mapped address as well.
5569 5588                           */
5570 5589                          if (!IN6_IS_ADDR_UNSPECIFIED(
5571 5590                              &connp->conn_bound_addr_v6) &&
↓ open down ↓ 871 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX