Add additional checks for IPV6_PKTINFO handling (RFC 3542):

* Return ENETDOWN when interface specified by ipi6_ifindex is not
  enabled for IPv6 use.
* Return EADDRNOTAVAIL when ipi6_ifindex specifies an interface, but the
  address ipi6_addr is not available for use on that interface.
* Return EINVAL when ipi6_addr is multicast address.

Obtained from:	Yandex LLC
Sponsored by:	Yandex LLC
This commit is contained in:
Andrey V. Elsukov 2014-09-10 14:32:07 +00:00
parent 2c5b89e54b
commit 9196891fc9

View File

@ -2559,7 +2559,8 @@ ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt,
sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) { sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
return (EINVAL); return (EINVAL);
} }
if (IN6_IS_ADDR_MULTICAST(&pktinfo->ipi6_addr))
return (EINVAL);
/* validate the interface index if specified. */ /* validate the interface index if specified. */
if (pktinfo->ipi6_ifindex > V_if_index) if (pktinfo->ipi6_ifindex > V_if_index)
return (ENXIO); return (ENXIO);
@ -2568,7 +2569,19 @@ ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt,
if (ifp == NULL) if (ifp == NULL)
return (ENXIO); return (ENXIO);
} }
if (ifp != NULL && (
ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED))
return (ENETDOWN);
if (ifp != NULL &&
!IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
struct in6_ifaddr *ia;
ia = in6ifa_ifpwithaddr(ifp, &pktinfo->ipi6_addr);
if (ia == NULL)
return (EADDRNOTAVAIL);
ifa_free(&ia->ia_ifa);
}
/* /*
* We store the address anyway, and let in6_selectsrc() * We store the address anyway, and let in6_selectsrc()
* validate the specified address. This is because ipi6_addr * validate the specified address. This is because ipi6_addr