IOReturn REACConnection::getInterfaceMacAddress(ifnet_t interface, UInt8* resultAddr, UInt32 addrLen) { ifaddr_t *addresses; ifaddr_t *address; REACSockaddr addr; IOReturn ret = kIOReturnError; if (ETHER_ADDR_LEN != addrLen) { return kIOReturnBadArgument; } if (ifnet_get_address_list_family(interface, &addresses, AF_LINK)) { return kIOReturnError; } address = addresses; while (*address) { if (0 == ifaddr_address(*address, (sockaddr*) &addr, sizeof(addr))) { if (addr.sdl_alen == ETHER_ADDR_LEN) { memcpy(resultAddr, addr.sdl_data+addr.sdl_nlen, addrLen); ret = kIOReturnSuccess; break; } } ++address; } ifnet_free_address_list(addresses); return ret; }
void firewire_inet_event( ifnet_t ifp, __unused protocol_family_t protocol, const struct kev_msg *event) { ifaddr_t *addresses; if (event->vendor_code != KEV_VENDOR_APPLE || event->kev_class != KEV_NETWORK_CLASS || event->kev_subclass != KEV_DL_SUBCLASS || event->event_code != KEV_DL_LINK_ADDRESS_CHANGED) return; if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) { int i; for (i = 0; addresses[i] != NULL; i++) inet_arp_init_ifaddr(ifp, addresses[i]); ifnet_free_address_list(addresses); } }
static void utun_cleanup_family( ifnet_t interface, protocol_family_t protocol) { errno_t result = 0; socket_t pf_socket = NULL; ifaddr_t *addresses = NULL; int i; if (protocol != PF_INET && protocol != PF_INET6) { printf("utun_cleanup_family - invalid protocol family %d\n", protocol); return; } /* Create a socket for removing addresses and detaching the protocol */ result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket); if (result != 0) { if (result != EAFNOSUPPORT) printf("utun_cleanup_family - failed to create %s socket: %d\n", protocol == PF_INET ? "IP" : "IPv6", result); goto cleanup; } /* always set SS_PRIV, we want to close and detach regardless */ sock_setpriv(pf_socket, 1); result = utun_detach_ip(interface, protocol, pf_socket); if (result == 0 || result == ENXIO) { /* We are done! We either detached or weren't attached. */ goto cleanup; } else if (result != EBUSY) { /* Uh, not really sure what happened here... */ printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result); goto cleanup; } /* * At this point, we received an EBUSY error. This means there are * addresses attached. We should detach them and then try again. */ result = ifnet_get_address_list_family(interface, &addresses, protocol); if (result != 0) { printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n", ifnet_name(interface), ifnet_unit(interface), protocol == PF_INET ? "PF_INET" : "PF_INET6", result); goto cleanup; } for (i = 0; addresses[i] != 0; i++) { utun_remove_address(interface, protocol, addresses[i], pf_socket); } ifnet_free_address_list(addresses); addresses = NULL; /* * The addresses should be gone, we should try the remove again. */ result = utun_detach_ip(interface, protocol, pf_socket); if (result != 0 && result != ENXIO) { printf("utun_cleanup_family - utun_detach_ip failed: %d\n", result); } cleanup: if (pf_socket != NULL) sock_close(pf_socket); if (addresses != NULL) ifnet_free_address_list(addresses); }
errno_t firewire_inet_arp( ifnet_t ifp, u_short arpop, const struct sockaddr_dl* sender_hw, const struct sockaddr* sender_proto, const struct sockaddr_dl* target_hw, const struct sockaddr* target_proto) { mbuf_t m; errno_t result; register struct firewire_header *fwh; register IP1394_ARP *fwa; const struct sockaddr_in* sender_ip = (const struct sockaddr_in*)sender_proto; const struct sockaddr_in* target_ip = (const struct sockaddr_in*)target_proto; char *datap; IOFWInterface *fwIf = (IOFWInterface*)ifnet_softc(ifp); if(fwIf == NULL) return EINVAL; IOFireWireIP *fwIpObj = (IOFireWireIP*)fwIf->getController(); if(fwIpObj == NULL) return EINVAL; LCB *lcb = fwIpObj->getLcb(); if (target_ip == NULL) return EINVAL; if ((sender_ip && sender_ip->sin_family != AF_INET) || (target_ip && target_ip->sin_family != AF_INET)) return EAFNOSUPPORT; result = mbuf_gethdr(MBUF_DONTWAIT, MBUF_TYPE_DATA, &m); if (result != 0) return result; mbuf_setlen(m, sizeof(*fwa)); mbuf_pkthdr_setlen(m, sizeof(*fwa)); /* Move the data pointer in the mbuf to the end, aligned to 4 bytes */ datap = (char*)mbuf_datastart(m); datap += mbuf_trailingspace(m); datap -= (((u_long)datap) & 0x3); mbuf_setdata(m, datap, sizeof(*fwa)); fwa = (IP1394_ARP*)mbuf_data(m); bzero((caddr_t)fwa, sizeof(*fwa)); /* Prepend the ethernet header, we will send the raw frame */ result = mbuf_prepend(&m, sizeof(*fwh), MBUF_DONTWAIT); if(result != 0) return result; fwh = (struct firewire_header*)mbuf_data(m); fwh->fw_type = htons(FWTYPE_ARP); /* Fill out the arp packet */ fwa->hardwareType = htons(ARP_HDW_TYPE); fwa->protocolType = htons(FWTYPE_IP); fwa->hwAddrLen = sizeof(IP1394_HDW_ADDR); fwa->ipAddrLen = IPV4_ADDR_SIZE; fwa->opcode = htons(arpop); fwa->senderMaxRec = lcb->ownHardwareAddress.maxRec; fwa->sspd = lcb->ownHardwareAddress.spd; fwa->senderUnicastFifoHi = htons(lcb->ownHardwareAddress.unicastFifoHi); fwa->senderUnicastFifoLo = htonl(lcb->ownHardwareAddress.unicastFifoLo); /* Sender Hardware */ if (sender_hw != NULL) bcopy(CONST_LLADDR(sender_hw), &fwa->senderUniqueID, sizeof(fwa->senderUniqueID)); else ifnet_lladdr_copy_bytes(ifp, &fwa->senderUniqueID, FIREWIRE_ADDR_LEN); ifnet_lladdr_copy_bytes(ifp, fwh->fw_shost, sizeof(fwh->fw_shost)); /* Sender IP */ if (sender_ip != NULL) fwa->senderIpAddress = sender_ip->sin_addr.s_addr; else { ifaddr_t *addresses; struct sockaddr sa; if (ifnet_get_address_list_family(ifp, &addresses, AF_INET) == 0) { ifaddr_address( addresses[0], &sa, 16 ); fwa->senderIpAddress = ((UInt32)(sa.sa_data[5] & 0xFF)) << 24; fwa->senderIpAddress |= ((UInt32)(sa.sa_data[4] & 0xFF)) << 16; fwa->senderIpAddress |= ((UInt32)(sa.sa_data[3] & 0xFF)) << 8; fwa->senderIpAddress |= ((UInt32)(sa.sa_data[2] & 0xFF)); ifnet_free_address_list(addresses); } else { mbuf_free(m); return ENXIO; } } /* Target Hardware */ if (target_hw == 0) bcopy(fwbroadcastaddr, fwh->fw_dhost, sizeof(fwh->fw_dhost)); else bcopy(CONST_LLADDR(target_hw), fwh->fw_dhost, sizeof(fwh->fw_dhost)); /* Target IP */ fwa->targetIpAddress = target_ip->sin_addr.s_addr; ifnet_output_raw(ifp, PF_INET, m); return 0; }