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/ip/icmp.c
          +++ new/usr/src/uts/common/inet/ip/icmp.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 (c) 2013 by Delphix. 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 ↓ 727 lines elided ↑ open up ↑
 761  762                          return (EADDRNOTAVAIL);
 762  763                  }
 763  764                  v6dst = sin6->sin6_addr;
 764  765                  dstport = sin6->sin6_port;
 765  766                  ASSERT(connp->conn_ipversion == IPV6_VERSION);
 766  767                  flowinfo = sin6->sin6_flowinfo;
 767  768                  if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 768  769                          scopeid = sin6->sin6_scope_id;
 769  770                  srcid = sin6->__sin6_src_id;
 770  771                  if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
 771      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
 772      -                            connp->conn_netstack);
      772 +                        /* Due to check above, we know sin6_addr is v6-only. */
      773 +                        if (!ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
      774 +                            B_FALSE, connp->conn_netstack)) {
      775 +                                /* Mismatch - v6src would be v4mapped. */
      776 +                                return (EADDRNOTAVAIL);
      777 +                        }
 773  778                  }
 774  779                  break;
 775  780          }
 776  781  
 777  782          /*
 778  783           * If there is a different thread using conn_ixa then we get a new
 779  784           * copy and cut the old one loose from conn_ixa. Otherwise we use
 780  785           * conn_ixa and prevent any other thread from using/changing it.
 781  786           * Once connect() is done other threads can use conn_ixa since the
 782  787           * refcnt will be back at one.
↓ open down ↓ 2547 lines elided ↑ open up ↑
3330 3335          icmp_t          *icmp = connp->conn_icmp;
3331 3336          icmp_stack_t    *is = icmp->icmp_is;
3332 3337          int             error;
3333 3338          ip_xmit_attr_t  *ixa;
3334 3339          ip_pkt_t        *ipp;
3335 3340          in6_addr_t      v6src;
3336 3341          in6_addr_t      v6dst;
3337 3342          in6_addr_t      v6nexthop;
3338 3343          in_port_t       dstport;
3339 3344          uint32_t        flowinfo;
3340      -        uint_t          srcid;
3341 3345          int             is_absreq_failure = 0;
3342 3346          conn_opt_arg_t  coas, *coa;
3343 3347  
3344 3348          ASSERT(tudr_mp != NULL || msg != NULL);
3345 3349  
3346 3350          /*
3347 3351           * Get ixa before checking state to handle a disconnect race.
3348 3352           *
3349 3353           * We need an exclusive copy of conn_ixa since the ancillary data
3350 3354           * options might modify it. That copy has no pointers hence we
↓ open down ↓ 82 lines elided ↑ open up ↑
3433 3437           * from ip_attr_connect() below.
3434 3438           */
3435 3439          v6src = connp->conn_saddr_v6;
3436 3440          if (sin != NULL) {
3437 3441                  IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
3438 3442                  dstport = sin->sin_port;
3439 3443                  flowinfo = 0;
3440 3444                  ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
3441 3445                  ixa->ixa_flags |= IXAF_IS_IPV4;
3442 3446          } else if (sin6 != NULL) {
     3447 +                boolean_t v4mapped;
     3448 +                uint_t srcid;
     3449 +
3443 3450                  v6dst = sin6->sin6_addr;
3444 3451                  dstport = sin6->sin6_port;
3445 3452                  flowinfo = sin6->sin6_flowinfo;
3446 3453                  srcid = sin6->__sin6_src_id;
3447 3454                  if (IN6_IS_ADDR_LINKSCOPE(&v6dst) && sin6->sin6_scope_id != 0) {
3448 3455                          ixa->ixa_scopeid = sin6->sin6_scope_id;
3449 3456                          ixa->ixa_flags |= IXAF_SCOPEID_SET;
3450 3457                  } else {
3451 3458                          ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
3452 3459                  }
3453      -                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
3454      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
3455      -                            connp->conn_netstack);
3456      -                }
3457      -                if (IN6_IS_ADDR_V4MAPPED(&v6dst))
     3460 +                v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
     3461 +                if (v4mapped)
3458 3462                          ixa->ixa_flags |= IXAF_IS_IPV4;
3459 3463                  else
3460 3464                          ixa->ixa_flags &= ~IXAF_IS_IPV4;
     3465 +                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
     3466 +                        if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
     3467 +                            v4mapped, connp->conn_netstack)) {
     3468 +                                /* Mismatched v4mapped/v6 specified by srcid. */
     3469 +                                mutex_exit(&connp->conn_lock);
     3470 +                                error = EADDRNOTAVAIL;
     3471 +                                goto failed;    /* Does freemsg() and mib. */
     3472 +                        }
     3473 +                }
3461 3474          } else {
3462 3475                  /* Connected case */
3463 3476                  v6dst = connp->conn_faddr_v6;
3464 3477                  flowinfo = connp->conn_flowinfo;
3465 3478          }
3466 3479          mutex_exit(&connp->conn_lock);
3467 3480          /* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
3468 3481          if (ipp->ipp_fields & IPPF_ADDR) {
3469 3482                  if (ixa->ixa_flags & IXAF_IS_IPV4) {
3470 3483                          if (IN6_IS_ADDR_V4MAPPED(&ipp->ipp_addr))
↓ open down ↓ 941 lines elided ↑ open up ↑
4412 4425           * want ip_attr_connect to select a source (since it can fail) when
4413 4426           * IPV6_PKTINFO is specified.
4414 4427           * If this doesn't result in a source address then we get a source
4415 4428           * from ip_attr_connect() below.
4416 4429           */
4417 4430          v6src = connp->conn_saddr_v6;
4418 4431          if (sin != NULL) {
4419 4432                  IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
4420 4433                  dstport = sin->sin_port;
4421 4434                  flowinfo = 0;
     4435 +                /* Don't bother with ip_srcid_find_id(), but indicate anyway. */
4422 4436                  srcid = 0;
4423 4437                  ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
4424      -                if (srcid != 0 && V4_PART_OF_V6(&v6src) == INADDR_ANY) {
4425      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
4426      -                            connp->conn_netstack);
4427      -                }
4428 4438                  ixa->ixa_flags |= IXAF_IS_IPV4;
4429 4439          } else {
     4440 +                boolean_t v4mapped;
     4441 +
4430 4442                  v6dst = sin6->sin6_addr;
4431 4443                  dstport = sin6->sin6_port;
4432 4444                  flowinfo = sin6->sin6_flowinfo;
4433 4445                  srcid = sin6->__sin6_src_id;
4434 4446                  if (IN6_IS_ADDR_LINKSCOPE(&v6dst) && sin6->sin6_scope_id != 0) {
4435 4447                          ixa->ixa_scopeid = sin6->sin6_scope_id;
4436 4448                          ixa->ixa_flags |= IXAF_SCOPEID_SET;
4437 4449                  } else {
4438 4450                          ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
4439 4451                  }
4440      -                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
4441      -                        ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
4442      -                            connp->conn_netstack);
4443      -                }
4444      -                if (IN6_IS_ADDR_V4MAPPED(&v6dst))
     4452 +                v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
     4453 +                if (v4mapped)
4445 4454                          ixa->ixa_flags |= IXAF_IS_IPV4;
4446 4455                  else
4447 4456                          ixa->ixa_flags &= ~IXAF_IS_IPV4;
     4457 +                if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
     4458 +                        if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
     4459 +                            v4mapped, connp->conn_netstack)) {
     4460 +                                /* Mismatched v4mapped/v6 specified by srcid. */
     4461 +                                mutex_exit(&connp->conn_lock);
     4462 +                                error = EADDRNOTAVAIL;
     4463 +                                goto ud_error;
     4464 +                        }
     4465 +                }
4448 4466          }
4449 4467          /* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
4450 4468          if (connp->conn_xmit_ipp.ipp_fields & IPPF_ADDR) {
4451 4469                  ip_pkt_t *ipp = &connp->conn_xmit_ipp;
4452 4470  
4453 4471                  if (ixa->ixa_flags & IXAF_IS_IPV4) {
4454 4472                          if (IN6_IS_ADDR_V4MAPPED(&ipp->ipp_addr))
4455 4473                                  v6src = ipp->ipp_addr;
4456 4474                  } else {
4457 4475                          if (!IN6_IS_ADDR_V4MAPPED(&ipp->ipp_addr))
↓ open down ↓ 1385 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX