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

@@ -19,10 +19,12 @@
  * CDDL HEADER END
  */
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 
 /*
  * This is used to support the hidden __sin6_src_id in the sockaddr_in6
  * structure which is there to ensure that applications (such as UDP apps)

@@ -221,31 +223,52 @@
 }
 
 /*
  * Map from a source id to an address.
  * If the id is unknown return the unspecified address.
+ *
+ * For known IDs, check if the returned address is v4mapped or not, and
+ * return B_TRUE if it matches the desired v4mapped state or not.  This
+ * prevents a broken app from requesting (via __sin6_src_id) a v4mapped
+ * address for a v6 destination, or vice versa.
+ *
+ * "addr" will not be set if we return B_FALSE.
  */
-void
+boolean_t
 ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
-    netstack_t *ns)
+    boolean_t v4mapped, netstack_t *ns)
 {
         srcid_map_t     **smpp;
         srcid_map_t     *smp;
         ip_stack_t      *ipst = ns->netstack_ip;
+        boolean_t       rc;
 
         rw_enter(&ipst->ips_srcid_lock, RW_READER);
         smpp = srcid_lookup_id(id, ipst);
         smp = *smpp;
         if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) {
                 /* Not preset */
                 ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id));
                 *addr = ipv6_all_zeros;
+                rc = B_TRUE;
         } else {
                 ASSERT(smp->sm_refcnt != 0);
+                /*
+                 * The caller tells us if it expects a v4mapped address.
+                 * Use it, along with the property of "addr" to set the rc.
+                 */
+                if (IN6_IS_ADDR_V4MAPPED(&smp->sm_addr))
+                        rc = v4mapped;  /* We want a v4mapped address. */
+                else
+                        rc = !v4mapped; /* We don't want a v4mapped address. */
+
+                if (rc)
                 *addr = smp->sm_addr;
+
         }
         rw_exit(&ipst->ips_srcid_lock);
+        return (rc);
 }
 
 /* Assign the next available ID */
 static uint_t
 srcid_nextid(ip_stack_t *ipst)