diff options
author | Sowmini Varadhan <Sowmini.Varadhan@Sun.COM> | 2009-05-07 20:59:19 -0400 |
---|---|---|
committer | Sowmini Varadhan <Sowmini.Varadhan@Sun.COM> | 2009-05-07 20:59:19 -0400 |
commit | 3efde6d032b3bcd6957e912c3f2a59253f28a9dc (patch) | |
tree | e31ab073589d1ffc6df0d74d9b18d54e40d87654 | |
parent | 19b41302109b7a894f3f97e06ca4a0222a238b14 (diff) | |
download | illumos-joyent-3efde6d032b3bcd6957e912c3f2a59253f28a9dc.tar.gz |
6834698 IPv6 point-to-point ipifs can no longer share source addresses
6834157 libdladm leaks memory in dladm_get_single_mac_stat()
-rw-r--r-- | usr/src/lib/libdladm/common/libdlstat.c | 10 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip6_if.c | 36 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip_ndp.h | 6 |
4 files changed, 37 insertions, 17 deletions
diff --git a/usr/src/lib/libdladm/common/libdlstat.c b/usr/src/lib/libdladm/common/libdlstat.c index b4c2c38692..e69c9d8934 100644 --- a/usr/src/lib/libdladm/common/libdlstat.c +++ b/usr/src/lib/libdladm/common/libdlstat.c @@ -654,11 +654,6 @@ dladm_get_single_mac_stat(dladm_handle_t handle, datalink_id_t linkid, kstat_t *ksp; dladm_phys_attr_t dpap; - if ((kcp = kstat_open()) == NULL) { - warn("kstat_open operation failed"); - return (-1); - } - if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, &media, link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK) return (status); @@ -676,6 +671,11 @@ dladm_get_single_mac_stat(dladm_handle_t handle, datalink_id_t linkid, if (status != DLADM_STATUS_OK) return (status); + if ((kcp = kstat_open()) == NULL) { + warn("kstat_open operation failed"); + return (-1); + } + /* * The kstat query could fail if the underlying MAC * driver was already detached. diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h index f39eff0246..0b2b70c5be 100644 --- a/usr/src/uts/common/inet/ip.h +++ b/usr/src/uts/common/inet/ip.h @@ -1278,7 +1278,7 @@ typedef struct ipif_s { ipif_was_dup : 1, /* DAD had failed */ ipif_joined_allhosts : 1, /* allhosts joined */ - ipif_added_nce:1, /* nce added for local address */ + ipif_added_nce : 1, /* nce added for local address */ ipif_pad_to_31 : 26; uint_t ipif_seqid; /* unique index across all ills */ diff --git a/usr/src/uts/common/inet/ip/ip6_if.c b/usr/src/uts/common/inet/ip/ip6_if.c index 92c1eed048..b592fc0cd1 100644 --- a/usr/src/uts/common/inet/ip/ip6_if.c +++ b/usr/src/uts/common/inet/ip/ip6_if.c @@ -1586,17 +1586,34 @@ ipif_ndp_up(ipif_t *ipif, boolean_t initial) ill->ill_name)); ipif->ipif_addr_ready = 1; ipif->ipif_added_nce = 1; + nce->nce_ipif_cnt++; break; case EINPROGRESS: ip1dbg(("ipif_ndp_up: running DAD now for %s\n", ill->ill_name)); ipif->ipif_added_nce = 1; + nce->nce_ipif_cnt++; break; case EEXIST: - NCE_REFRELE(nce); ip1dbg(("ipif_ndp_up: NCE already exists for %s\n", ill->ill_name)); - goto fail; + if ((ipif->ipif_flags & IPIF_POINTOPOINT) == 0) { + NCE_REFRELE(nce); + goto fail; + } + /* + * Duplicate local addresses are permissible for + * IPIF_POINTOPOINT interfaces which will get marked + * IPIF_UNNUMBERED later in + * ip_addr_availability_check(). + * + * The nce_ipif_cnt field tracks the number of + * ipifs that have nce_addr as their local address. + */ + ipif->ipif_addr_ready = 1; + ipif->ipif_added_nce = 1; + nce->nce_ipif_cnt++; + break; default: ip1dbg(("ipif_ndp_up: NCE creation failed for %s\n", ill->ill_name)); @@ -1644,13 +1661,14 @@ ipif_ndp_down(ipif_t *ipif) B_TRUE, &ipif->ipif_v6lcl_addr, B_FALSE); - if (nce != NULL) { - ndp_delete(nce); - NCE_REFRELE(nce); - } + if (nce == NULL) + goto no_nce; + if (--nce->nce_ipif_cnt == 0) + ndp_delete(nce); /* last ipif for nce */ ipif->ipif_added_nce = 0; + NCE_REFRELE(nce); } - +no_nce: /* * Make IPMP aware of the deleted data address. */ @@ -3221,8 +3239,8 @@ ipif_up_done_v6(ipif_t *ipif) * which is the expected error code. * * Note that, for the non-XRESOLV case, ipif_ndp_down() will - * only delete an nce in the case when one was actually created - * by ipif_ndp_up(), as indicated by the ipif_added_nce bit. + * only delete the nce in the case when the nce_ipif_cnt drops + * to 0. */ if (err == EADDRINUSE) { if (ipif->ipif_ill->ill_flags & ILLF_XRESOLV) { diff --git a/usr/src/uts/common/inet/ip_ndp.h b/usr/src/uts/common/inet/ip_ndp.h index 2211e52c2b..c1a48b1f1a 100644 --- a/usr/src/uts/common/inet/ip_ndp.h +++ b/usr/src/uts/common/inet/ip_ndp.h @@ -96,6 +96,8 @@ typedef struct nce_s { boolean_t nce_trace_disable; /* True when alloc fails */ list_t nce_cb; uint_t nce_cb_walker_cnt; + uint_t nce_ipif_cnt; /* number of ipifs with the nce_addr */ + /* as their local address */ } nce_t; /* @@ -113,8 +115,8 @@ typedef struct nce_s { * Locking notes: * ndp_g_lock protects neighbor cache tables access and * insertion/removal of cache entries into/from these tables. - * nce_lock protects nce_pcnt, nce_rcnt, nce_qd_mp nce_state, - * nce_res_mp, nce_refcnt and nce_last. + * nce_lock protects nce_pcnt, nce_rcnt, nce_qd_mp nce_state, nce_res_mp, + * nce_refcnt, nce_last, and nce_cb_walker_cnt. * nce_refcnt is incremented for every ire pointing to this nce and * every time ndp_lookup() finds an nce. * Should there be a need to obtain nce_lock and ndp_g_lock, ndp_g_lock is |