STATIC int RTADVSocketInitTXBuf(RTADVSocketRef sock, uint32_t * txbuf, bool lladdr_ok) { interface_t * if_p = RTADVSocketGetInterface(sock); struct nd_router_solicit * ndrs; int txbuf_used; ndrs = (struct nd_router_solicit *)txbuf; ndrs->nd_rs_type = ND_ROUTER_SOLICIT; ndrs->nd_rs_code = 0; ndrs->nd_rs_cksum = 0; ndrs->nd_rs_reserved = 0; txbuf_used = sizeof(struct nd_router_solicit); /* if it's OK to include [RFC 4429], add source link-layer address option */ if (lladdr_ok && if_link_type(if_p) == IFT_ETHER) { int opt_len; struct nd_opt_hdr * ndopt; opt_len = roundup(if_link_length(if_p) + sizeof(*ndopt), ND_OPT_ALIGN); ndopt = (struct nd_opt_hdr *)(ndrs + 1); ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; ndopt->nd_opt_len = (opt_len / ND_OPT_ALIGN); bcopy(if_link_address(if_p), (ndopt + 1), if_link_length(if_p)); txbuf_used += opt_len; } return (txbuf_used); }
STATIC CFDataRef make_DUID_LL_data(interface_t * if_p) { CFMutableDataRef data; int duid_len; DHCPDUID_LLRef ll_p; duid_len = offsetof(DHCPDUID_LL, linklayer_address) + if_link_length(if_p); data = CFDataCreateMutable(NULL, duid_len); CFDataSetLength(data, duid_len); ll_p = (DHCPDUID_LLRef)CFDataGetMutableBytePtr(data); DHCPDUIDSetType((DHCPDUIDRef)ll_p, kDHCPDUIDTypeLL); DHCPDUID_LLSetHardwareType(ll_p, if_link_arptype(if_p)); bcopy(if_link_address(if_p), ll_p->linklayer_address, if_link_length(if_p)); return (data); }
PRIVATE_EXTERN CFDataRef DHCPDUIDGet(interface_list_t * interfaces) { interface_t * if_p; interface_t * if_with_linkaddr_p = NULL; if (S_DUID != NULL) { goto done; } /* try to load the DUID from filesystem */ if (G_is_netboot == FALSE && load_DUID_info()) { goto done; } if (interfaces == NULL) { goto done; } if_p = ifl_find_name(interfaces, "en0"); if (if_p == NULL) { int count; int i; count = ifl_count(interfaces); for (i = 0; i < count; i++) { interface_t * scan = ifl_at_index(interfaces, i); switch (if_ift_type(scan)) { case IFT_ETHER: case IFT_IEEE1394: break; default: if (if_with_linkaddr_p == NULL && if_link_length(scan) > 0) { if_with_linkaddr_p = scan; } continue; } if (if_p == NULL) { if_p = scan; } else if (strcmp(if_name(scan), if_name(if_p)) < 0) { /* pick "lowest" named interface */ if_p = scan; } } } if (if_p == NULL) { if (G_dhcp_duid_type == kDHCPDUIDTypeLL || if_with_linkaddr_p == NULL) { my_log(LOG_ERR, "DHCPv6Client: can't determine interface for DUID"); goto done; } if_p = if_with_linkaddr_p; } if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "DHCPv6Client: chose %s for DUID", if_name(if_p)); } if (G_dhcp_duid_type == kDHCPDUIDTypeLL || G_is_netboot) { S_DUID = make_DUID_LL_data(if_p); } else { S_DUID = make_DUID_LLT_data(if_p); } save_DUID_info(); done: return (S_DUID); }