diff options
author | Sowmini Varadhan <Sowmini.Varadhan@Sun.COM> | 2009-05-19 15:07:44 -0400 |
---|---|---|
committer | Sowmini Varadhan <Sowmini.Varadhan@Sun.COM> | 2009-05-19 15:07:44 -0400 |
commit | ee07f6e76390e460e7a3065fe91b5ca23a0fe6a8 (patch) | |
tree | ef4e30721303fb5bf11d591d82d11759d3952db0 /usr | |
parent | eb42280b2139f489ab9ba5890cd6208cf3e58b38 (diff) | |
download | illumos-gate-ee07f6e76390e460e7a3065fe91b5ca23a0fe6a8.tar.gz |
6835200 IPv6 nce can be created in STALE state with bad link-layer info
6809387 BAD TRAP type=e in module "ip" due to NULL pointer under ipv6
6243060 SIOCSLIFNAME might be too liberal in the flags it allows to be modified
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/common/inet/ip.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip6_if.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_if.c | 89 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_mroute.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_ndp.c | 7 |
5 files changed, 47 insertions, 55 deletions
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h index d688615806..d587fa77fc 100644 --- a/usr/src/uts/common/inet/ip.h +++ b/usr/src/uts/common/inet/ip.h @@ -2893,9 +2893,6 @@ typedef struct ip_pktinfo { #define ILL_CAN_WAIT(ill, q) \ (((q) != NULL) && !((ill)->ill_state_flags & (ILL_CONDEMNED))) -#define ILL_CAN_LOOKUP_WALKER(ill) \ - (!((ill)->ill_state_flags & ILL_CONDEMNED)) - #define IPIF_CAN_LOOKUP(ipif) \ (!((ipif)->ipif_state_flags & (IPIF_CONDEMNED | IPIF_CHANGING)) || \ IAM_WRITER_IPIF(ipif)) diff --git a/usr/src/uts/common/inet/ip/ip6_if.c b/usr/src/uts/common/inet/ip/ip6_if.c index b592fc0cd1..e43ec55519 100644 --- a/usr/src/uts/common/inet/ip/ip6_if.c +++ b/usr/src/uts/common/inet/ip/ip6_if.c @@ -2448,6 +2448,8 @@ ipif_select_source_v6(ill_t *dstill, const in6_addr_t *dst, if (IS_UNDER_IPMP(ill)) continue; + if (ill->ill_ipif == NULL) + continue; /* * For source address selection, we treat the ipif list as * circular and continue until we get back to where we diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c index e6e9030f36..67eff68c28 100644 --- a/usr/src/uts/common/inet/ip/ip_if.c +++ b/usr/src/uts/common/inet/ip/ip_if.c @@ -3728,7 +3728,8 @@ ill_forward_set_on_ill(ill_t *ill, boolean_t enable) if (ill->ill_isv6) ill_set_nce_router_flags(ill, enable); /* Notify routing socket listeners of this change. */ - ip_rts_ifmsg(ill->ill_ipif, RTSQ_DEFAULT); + if (ill->ill_ipif != NULL) + ip_rts_ifmsg(ill->ill_ipif, RTSQ_DEFAULT); } /* @@ -17501,6 +17502,7 @@ ip_sioctl_slifname(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp, phyint_t *phyi; ip_stack_t *ipst; struct lifreq *lifr = if_req; + uint64_t new_flags; ASSERT(ipif != NULL); ip1dbg(("ip_sioctl_slifname %s\n", lifr->lifr_name)); @@ -17522,18 +17524,6 @@ ip_sioctl_slifname(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp, return (EALREADY); /* - * Set all the flags. Allows all kinds of override. Provide some - * sanity checking by not allowing IFF_BROADCAST and IFF_MULTICAST - * unless there is either multicast/broadcast support in the driver - * or it is a pt-pt link. - */ - if (lifr->lifr_flags & (IFF_PROMISC|IFF_ALLMULTI)) { - /* Meaningless to IP thus don't allow them to be set. */ - ip1dbg(("ip_setname: EINVAL 1\n")); - return (EINVAL); - } - - /* * If there's another ill already with the requested name, ensure * that it's of the same type. Otherwise, ill_phyint_reinit() will * fuse together two unrelated ills, which will cause chaos. @@ -17557,59 +17547,60 @@ ip_sioctl_slifname(ipif_t *ipif, sin_t *sin, queue_t *q, mblk_t *mp, } /* - * For a DL_STYLE2 driver (ill_needs_attach), we would not have the - * ill_bcast_addr_length info. + * We start off as IFF_IPV4 in ipif_allocate and become + * IFF_IPV4 or IFF_IPV6 here depending on lifr_flags value. + * The only flags that we read from user space are IFF_IPV4, + * IFF_IPV6, IFF_XRESOLV and IFF_BROADCAST. + * + * This ill has not been inserted into the global list. + * So we are still single threaded and don't need any lock + * + * Saniy check the flags. */ - if (!ill->ill_needs_attach && - ((lifr->lifr_flags & IFF_MULTICAST) && - !(lifr->lifr_flags & IFF_POINTOPOINT) && - ill->ill_bcast_addr_length == 0)) { - /* Link not broadcast/pt-pt capable i.e. no multicast */ - ip1dbg(("ip_setname: EINVAL 2\n")); - return (EINVAL); - } + if ((lifr->lifr_flags & IFF_BROADCAST) && ((lifr->lifr_flags & IFF_IPV6) || (!ill->ill_needs_attach && ill->ill_bcast_addr_length == 0))) { - /* Link not broadcast capable or IPv6 i.e. no broadcast */ - ip1dbg(("ip_setname: EINVAL 3\n")); - return (EINVAL); - } - if (lifr->lifr_flags & IFF_UP) { - /* Can only be set with SIOCSLIFFLAGS */ - ip1dbg(("ip_setname: EINVAL 4\n")); + ip1dbg(("ip_sioctl_slifname: link not broadcast capable " + "or IPv6 i.e., no broadcast \n")); return (EINVAL); } - if ((lifr->lifr_flags & (IFF_IPV6|IFF_IPV4)) != IFF_IPV6 && - (lifr->lifr_flags & (IFF_IPV6|IFF_IPV4)) != IFF_IPV4) { - ip1dbg(("ip_setname: EINVAL 5\n")); + + new_flags = + lifr->lifr_flags & (IFF_IPV6|IFF_IPV4|IFF_XRESOLV|IFF_BROADCAST); + + if ((new_flags ^ (IFF_IPV6|IFF_IPV4)) == 0) { + ip1dbg(("ip_sioctl_slifname: flags must be exactly one of " + "IFF_IPV4 or IFF_IPV6\n")); return (EINVAL); } /* * Only allow the IFF_XRESOLV flag to be set on IPv6 interfaces. */ - if ((lifr->lifr_flags & IFF_XRESOLV) && - !(lifr->lifr_flags & IFF_IPV6) && + if ((new_flags & IFF_XRESOLV) && !(new_flags & IFF_IPV6) && !(ipif->ipif_isv6)) { - ip1dbg(("ip_setname: EINVAL 6\n")); + ip1dbg(("ip_sioctl_slifname: XRESOLV only allowed on " + "IPv6 interface\n")); return (EINVAL); } /* - * The user has done SIOCGLIFFLAGS prior to this ioctl and hence - * we have all the flags here. So, we assign rather than we OR. - * We can't OR the flags here because we don't want to set - * both IFF_IPV4 and IFF_IPV6. We start off as IFF_IPV4 in - * ipif_allocate and become IFF_IPV4 or IFF_IPV6 here depending - * on lifr_flags value here. - */ - /* - * This ill has not been inserted into the global list. - * So we are still single threaded and don't need any lock + * We always start off as IPv4, so only need to check for IPv6. */ - ipif->ipif_flags = lifr->lifr_flags & IFF_LOGINT_FLAGS & ~IFF_DUPLICATE; - ill->ill_flags = lifr->lifr_flags & IFF_PHYINTINST_FLAGS; - ill->ill_phyint->phyint_flags = lifr->lifr_flags & IFF_PHYINT_FLAGS; + if ((new_flags & IFF_IPV6) != 0) { + ill->ill_flags |= ILLF_IPV6; + ill->ill_flags &= ~ILLF_IPV4; + } + + if ((new_flags & IFF_BROADCAST) != 0) + ipif->ipif_flags |= IPIF_BROADCAST; + else + ipif->ipif_flags &= ~IPIF_BROADCAST; + + if ((new_flags & IFF_XRESOLV) != 0) + ill->ill_flags |= ILLF_XRESOLV; + else + ill->ill_flags &= ~ILLF_XRESOLV; /* We started off as V4. */ if (ill->ill_flags & ILLF_IPV6) { diff --git a/usr/src/uts/common/inet/ip/ip_mroute.c b/usr/src/uts/common/inet/ip/ip_mroute.c index 1a3df02418..82d9083488 100644 --- a/usr/src/uts/common/inet/ip/ip_mroute.c +++ b/usr/src/uts/common/inet/ip/ip_mroute.c @@ -3232,6 +3232,7 @@ ip_mroute_vif(mblk_t *mp, ip_stack_t *ipst) if (!snmp_append_data(mp, (char *)&vi, sizeof (vi))) { ip0dbg(("ip_mroute_vif: failed %ld bytes\n", (size_t)sizeof (vi))); + mutex_exit(&ipst->ips_numvifs_mutex); return (0); } } diff --git a/usr/src/uts/common/inet/ip/ip_ndp.c b/usr/src/uts/common/inet/ip/ip_ndp.c index fe6c0c585d..51f1487847 100644 --- a/usr/src/uts/common/inet/ip/ip_ndp.c +++ b/usr/src/uts/common/inet/ip/ip_ndp.c @@ -1355,8 +1355,10 @@ ndp_query(ill_t *ill, struct lif_nd_req *lnr) if (nce == NULL) return (ESRCH); /* If in INCOMPLETE state, no link layer address is available yet */ - if (nce->nce_state == ND_INCOMPLETE) - goto done; + if (!NCE_ISREACHABLE(nce)) { + NCE_REFRELE(nce); + return (ESRCH); + } dl = (dl_unitdata_req_t *)nce->nce_res_mp->b_rptr; if (ill->ill_flags & ILLF_XRESOLV) lnr->lnr_hdw_len = dl->dl_dest_addr_length; @@ -1370,7 +1372,6 @@ ndp_query(ill_t *ill, struct lif_nd_req *lnr) lnr->lnr_flags = NDF_ISROUTER_ON; if (nce->nce_flags & NCE_F_ANYCAST) lnr->lnr_flags |= NDF_ANYCAST_ON; -done: NCE_REFRELE(nce); return (0); } |