OpenSolaris

Printable Version Enter a New Search
Bug ID 6781883
Synopsis ip_ndp_find_solicitation() can be passed adverts, and has API issues
State 10-Fix Delivered (Fix available in build)
Category:Subcategory kernel:tcp-ip
Keywords
Responsible Engineer Peter Memishian
Reported Against
Duplicate Of
Introduced In solaris_nevada
Commit to Fix snv_107
Fixed In snv_107
Release Fixed solaris_nevada(snv_107)
Related Bugs 4705220 , 6783149
Submit Date 7-December-2008
Last Update Date 28-January-2009
Description
While diagnosing an issue with Clearview IPMP, I found that ip_ndp_conflict()
would report:

   node 00:00:00:00:00:00 is using our IP address 2007:56::f0a3:df91:b7dd:432d on bge2

Note in particular the all-zeroes hardware address.  Some rummaging around
revealed the source of the problem: the packet in question that caused this
message was actually an unsolicited neighbor advertisement that got looped
back by ip_wput_ire_v6() -> ip_wput_ire_local_v6() and wasn't getting
properly detected in ndp_input_advert().  Nonetheless, ndp_input_advert()
called ip_ndp_conflict() which then called ip_ndp_find_solicitation(),
even though this was an advertisement.  While the layouts of advertisements
and solicitations are identical, the option codes are different.  Thus, when
we took this path:

                ns = (nd_neighbor_solicit_t *)((char *)ip6h + IPV6_HDR_LEN);
                nslen = mp->b_wptr - (uchar_t *)ns;
                if ((nslen -= sizeof (*ns)) > 0) {
(1) -->                 opt = ndp_get_option((nd_opt_hdr_t *)(ns + 1), nslen,
                            ND_OPT_SOURCE_LINKADDR);
                        if (opt != NULL &&
                            opt->nd_opt_len * 8 - sizeof (*opt) >=
                            ill->ill_nd_lla_len) {
                                addr = (uchar_t *)(opt + 1);
                                alen = ill->ill_nd_lla_len;
                        }
                }
                /*
                 * We cheat a bit here for the sake of printing usable log
                 * messages in the rare case where the reply we got was unicast
                 * without a source linkaddr option, and the interface is in
                 * fastpath mode.  (Sigh.)
                 */
                if (alen == 0 && ill->ill_type == IFT_ETHER &&
(2) -->             MBLKHEAD(mp) >= sizeof (struct ether_header)) {
                        struct ether_header *pether;

                        pether = (struct ether_header *)((char *)ip6h -
                            sizeof (*pether));
                        addr = pether->ether_shost.ether_addr_octet;
                        alen = ETHERADDRL;
                }

... the ndp_get_option() call at (1) returned NULL (since the option is
ND_OPT_TARGET_LINKADDR for an advertisement).   We then continued on to
(2), and since this was an Ethernet interface and there was space before
the Ethernet header (for the fastpath header, which has not been added
since this is a loopback packet), we printed whatever garbage happened
to be there (all zeroes).
Work Around
N/A
Comments
This issue was introduced with the IPv6 DAD work for 4705220; setting
"Introduced in Release" and "Introduced in Build" accordingly.