- struct ifaddr *ifa = (struct ifaddr *) data;
- struct ifreq *ifr = (struct ifreq *) data;
- struct rslvmulti_req *rsreq = (struct rslvmulti_req *) data;
- int error = 0;
- boolean_t funnel_state;
- struct arpcom *ac = (struct arpcom *) ifp;
- struct sockaddr_dl *sdl;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
-
- u_char *e_addr;
-
-
- switch (command) {
- case SIOCRSLVMULTI: {
- switch(rsreq->sa->sa_family) {
-
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *)rsreq->sa;
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
- /*
- * An IP6 address of 0 means listen to all
- * of the Ethernet multicast address used for IP6.
- * (This is used for multicast routers.)
- */
- ifp->if_flags |= IFF_ALLMULTI;
- *rsreq->llsa = 0;
- return 0;
- }
- MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
- M_WAITOK);
- sdl->sdl_len = sizeof *sdl;
- sdl->sdl_family = AF_LINK;
- sdl->sdl_index = ifp->if_index;
- sdl->sdl_type = IFT_ETHER;
- sdl->sdl_nlen = 0;
- sdl->sdl_alen = ETHER_ADDR_LEN;
- sdl->sdl_slen = 0;
- e_addr = LLADDR(sdl);
- ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
-#ifndef __APPLE__
- printf("ether_resolvemulti AF_INET6 Adding %x:%x:%x:%x:%x:%x\n",
- e_addr[0], e_addr[1], e_addr[2], e_addr[3], e_addr[4], e_addr[5]);
-#endif
- *rsreq->llsa = (struct sockaddr *)sdl;
- return 0;
+ static const size_t minsize =
+ offsetof(struct sockaddr_dl, sdl_data[0]) + ETHER_ADDR_LEN;
+ const struct sockaddr_in6 *sin6 =
+ (const struct sockaddr_in6 *)(uintptr_t)(size_t)proto_addr;
+
+ if (proto_addr->sa_family != AF_INET6)
+ return (EAFNOSUPPORT);
+
+ if (proto_addr->sa_len < sizeof (struct sockaddr_in6))
+ return (EINVAL);
+
+ if (ll_len < minsize)
+ return (EMSGSIZE);
+
+ bzero(out_ll, minsize);
+ out_ll->sdl_len = minsize;
+ out_ll->sdl_family = AF_LINK;
+ out_ll->sdl_index = ifp->if_index;
+ out_ll->sdl_type = IFT_ETHER;
+ out_ll->sdl_nlen = 0;
+ out_ll->sdl_alen = ETHER_ADDR_LEN;
+ out_ll->sdl_slen = 0;
+ ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, LLADDR(out_ll));
+
+ return (0);
+}