+ ifnet_lock_shared(ifp);
+ /*
+ * Holding ifnet lock here prevents the link address
+ * from changing contents, so no need to hold the ifa
+ * lock. The link address is always present; it's
+ * never freed.
+ */
+ ifa = ifp->if_lladdr;
+ info.rti_info[RTAX_IFP] = ifa->ifa_addr;
+ len = rt_msg2(RTM_IFINFO2, &info, NULL, NULL, &cred);
+ if (pass == 0) {
+ total_len += len;
+ } else {
+ struct if_msghdr2 *ifm;
+
+ if (current_len + len > total_len) {
+ ifnet_lock_done(ifp);
+ error = ENOBUFS;
+ break;
+ }
+ info.rti_info[RTAX_IFP] = ifa->ifa_addr;
+ len = rt_msg2(RTM_IFINFO2, &info,
+ (caddr_t)cp, NULL, &cred);
+ info.rti_info[RTAX_IFP] = NULL;
+
+ ifm = (struct if_msghdr2 *)(void *)cp;
+ ifm->ifm_addrs = info.rti_addrs;
+ ifm->ifm_flags = (u_short)ifp->if_flags;
+ ifm->ifm_index = ifp->if_index;
+ ifm->ifm_snd_len = IFCQ_LEN(&ifp->if_snd);
+ ifm->ifm_snd_maxlen = IFCQ_MAXLEN(&ifp->if_snd);
+ ifm->ifm_snd_drops =
+ ifp->if_snd.ifcq_dropcnt.packets;
+ ifm->ifm_timer = ifp->if_timer;
+ if_data_internal_to_if_data64(ifp,
+ &ifp->if_data, &ifm->ifm_data);
+ /*
+ * <rdar://problem/32940901>
+ * Round bytes only for non-platform
+ */
+ if (!csproc_get_platform_binary(w->w_req->p)) {
+ ALIGN_BYTES(ifm->ifm_data.ifi_ibytes);
+ ALIGN_BYTES(ifm->ifm_data.ifi_obytes);
+ }
+
+ cp += len;
+ VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
+ current_len += len;
+ }
+ while ((ifa = ifa->ifa_link.tqe_next) != NULL) {
+ IFA_LOCK(ifa);
+ if (af && af != ifa->ifa_addr->sa_family) {
+ IFA_UNLOCK(ifa);
+ continue;
+ }
+ info.rti_info[RTAX_IFA] = ifa->ifa_addr;
+ info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
+ info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
+ len = rt_msg2(RTM_NEWADDR, &info, NULL, NULL,
+ &cred);
+ if (pass == 0) {
+ total_len += len;
+ } else {
+ struct ifa_msghdr *ifam;
+
+ if (current_len + len > total_len) {
+ IFA_UNLOCK(ifa);
+ error = ENOBUFS;
+ break;
+ }
+ len = rt_msg2(RTM_NEWADDR, &info,
+ (caddr_t)cp, NULL, &cred);
+
+ ifam = (struct ifa_msghdr *)(void *)cp;
+ ifam->ifam_index =
+ ifa->ifa_ifp->if_index;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_metric = ifa->ifa_metric;
+ ifam->ifam_addrs = info.rti_addrs;
+
+ cp += len;
+ VERIFY(IS_P2ALIGNED(cp,
+ sizeof (u_int32_t)));
+ current_len += len;
+ }
+ IFA_UNLOCK(ifa);
+ }
+ if (error) {
+ ifnet_lock_done(ifp);
+ break;
+ }
+
+ for (ifma = LIST_FIRST(&ifp->if_multiaddrs);
+ ifma != NULL; ifma = LIST_NEXT(ifma, ifma_link)) {
+ struct ifaddr *ifa0;
+
+ IFMA_LOCK(ifma);
+ if (af && af != ifma->ifma_addr->sa_family) {
+ IFMA_UNLOCK(ifma);
+ continue;
+ }
+ bzero((caddr_t)&info, sizeof (info));
+ info.rti_info[RTAX_IFA] = ifma->ifma_addr;
+ /*
+ * Holding ifnet lock here prevents the link
+ * address from changing contents, so no need
+ * to hold the ifa0 lock. The link address is
+ * always present; it's never freed.
+ */
+ ifa0 = ifp->if_lladdr;
+ info.rti_info[RTAX_IFP] = ifa0->ifa_addr;
+ if (ifma->ifma_ll != NULL)
+ info.rti_info[RTAX_GATEWAY] =
+ ifma->ifma_ll->ifma_addr;
+ len = rt_msg2(RTM_NEWMADDR2, &info, NULL, NULL,
+ &cred);
+ if (pass == 0) {
+ total_len += len;
+ } else {
+ struct ifma_msghdr2 *ifmam;
+
+ if (current_len + len > total_len) {
+ IFMA_UNLOCK(ifma);
+ error = ENOBUFS;
+ break;
+ }
+ len = rt_msg2(RTM_NEWMADDR2, &info,
+ (caddr_t)cp, NULL, &cred);
+
+ ifmam =
+ (struct ifma_msghdr2 *)(void *)cp;
+ ifmam->ifmam_addrs = info.rti_addrs;
+ ifmam->ifmam_flags = 0;
+ ifmam->ifmam_index =
+ ifma->ifma_ifp->if_index;
+ ifmam->ifmam_refcount =
+ ifma->ifma_reqcnt;
+
+ cp += len;
+ VERIFY(IS_P2ALIGNED(cp,
+ sizeof (u_int32_t)));
+ current_len += len;
+ }
+ IFMA_UNLOCK(ifma);