- bzero(&sin, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof sin;
- sin.sin_addr = *ap;
- error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
- if (error) {
- return 0;
- }
-
- /*
- * If ifma->ifma_protospec is null, then if_addmulti() created
- * a new record. Otherwise, we are done.
- */
- if (ifma->ifma_protospec != 0) {
- return ifma->ifma_protospec;
- }
-
- inm = (struct in_multi *) _MALLOC(sizeof(*inm), M_IPMADDR, M_WAITOK);
- if (inm == NULL) {
- return (NULL);
- }
-
- bzero(inm, sizeof *inm);
- inm->inm_addr = *ap;
- inm->inm_ifp = ifp;
- inm->inm_ifma = ifma;
- lck_mtx_lock(rnh_lock);
- if (ifma->ifma_protospec == NULL) {
- ifma->ifma_protospec = inm;
- ifma->ifma_free = in_free_inm;
- LIST_INSERT_HEAD(&in_multihead, inm, inm_link);
- }
- lck_mtx_unlock(rnh_lock);
-
- if (ifma->ifma_protospec != inm) {
- _FREE(inm, M_IPMADDR);
- return ifma->ifma_protospec;
- }
-
- /*
- * Let IGMP know that we have joined a new IP multicast group.
- */
- error = igmp_joingroup(inm);
- if (error) {
- char addrbuf[16];
-
- /*
- * We can't free the inm because someone else may already be
- * using it. Once we put it in to ifma->ifma_protospec, it
- * must exist as long as the ifma does. Might be nice to flag
- * the error so we can try igmp_joingroup the next time through.
- */
- log(LOG_ERR, "igmp_joingroup error %d joining multicast %s on %s%d\n",
- error, inet_ntop(AF_INET, &sin.sin_addr, addrbuf, sizeof(addrbuf)),
- ifp->if_name, ifp->if_unit);
- }
-
- return (inm);
-}
-
-/*
- * Delete a multicast address record.
- */
-void
-in_delmulti(
- struct in_multi **inm)
-{
- struct in_multi *inm2;
-
- lck_mtx_lock(rnh_lock);
- LIST_FOREACH(inm2, &in_multihead, inm_link) {
- if (inm2 == *inm)
- break;
- }
- if (inm2 != *inm) {
- lck_mtx_unlock(rnh_lock);
- printf("in_delmulti - ignoring invalid inm (%p)\n", *inm);
- return;
- }
- lck_mtx_unlock(rnh_lock);
-
- /* We intentionally do this a bit differently than BSD */
- if ((*inm)->inm_ifma) {
- if_delmultiaddr((*inm)->inm_ifma, 0);
- ifma_release((*inm)->inm_ifma);
+ err = ifnet_get_address_list_family_internal(ifp, &ifap, AF_INET, 1,
+ M_WAITOK);
+ if (err == 0 && ifap != NULL) {
+ for (i = 0; ifap[i] != NULL; i++) {
+ struct ifaliasreq ifr;
+ struct ifaddr *ifa;
+
+ ifa = ifap[i];
+ bzero(&ifr, sizeof (ifr));
+ IFA_LOCK(ifa);
+ ifr.ifra_addr = *ifa->ifa_addr;
+ if (ifa->ifa_dstaddr != NULL)
+ ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
+ IFA_UNLOCK(ifa);
+ err = in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
+ kernproc);
+ /* if we lost the race, ignore it */
+ if (err == EADDRNOTAVAIL)
+ err = 0;
+ if (err != 0) {
+ char s_addr[MAX_IPv4_STR_LEN];
+ char s_dstaddr[MAX_IPv4_STR_LEN];
+ struct in_addr *s, *d;
+
+ IFA_LOCK(ifa);
+ s = &((struct sockaddr_in *)
+ ifa->ifa_addr)->sin_addr;
+ d = &((struct sockaddr_in *)
+ ifa->ifa_dstaddr)->sin_addr;
+ (void) inet_ntop(AF_INET, &s->s_addr, s_addr,
+ sizeof (s_addr));
+ (void) inet_ntop(AF_INET, &d->s_addr, s_dstaddr,
+ sizeof (s_dstaddr));
+ IFA_UNLOCK(ifa);
+
+ printf("%s: SIOCDIFADDR ifp=%p ifa_addr=%s "
+ "ifa_dstaddr=%s (err=%d)\n", __func__, ifp,
+ s_addr, s_dstaddr, err);
+ }
+ }
+ ifnet_free_address_list(ifap);
+ } else if (err != 0 && err != ENXIO) {
+ printf("%s: error retrieving list of AF_INET addresses for "
+ "ifp=%p (err=%d)\n", __func__, ifp, err);