/* * Function: DHCPLeaseListWrite * * Purpose: * Write the last DHCP lease in the list for the given interface/client_id. * We only save the last (current) lease. See the comments for * DHCPLeaseListRead above for more information. */ void DHCPLeaseListWrite(DHCPLeaseListRef list_p, const char * ifname, uint8_t cid_type, const void * cid, int cid_length) { int count; char filename[PATH_MAX]; CFDictionaryRef lease_dict; DHCPLeaseRef lease_p; if (DHCPLeaseListGetPath(ifname, cid_type, cid, cid_length, filename, sizeof(filename)) == FALSE) { return; } DHCPLeaseListRemoveStaleLeases(list_p); count = dynarray_count(list_p); if (count == 0) { unlink(filename); return; } lease_p = dynarray_element(list_p, count - 1); lease_dict = DHCPLeaseCopyDictionary(lease_p); if (my_CFPropertyListWriteFile(lease_dict, filename, 0644) < 0) { /* * An ENOENT error is expected on a read-only filesystem. All * other errors should be reported. */ if (errno != ENOENT) { my_log(LOG_ERR, "my_CFPropertyListWriteFile(%s) failed, %s", filename, strerror(errno)); } } my_CFRelease(&lease_dict); return; }
/* * Function: DHCPLeaseListRemoveStaleLeases * Purpose: * Scans the list of leases removing any that are no longer valid. */ static void DHCPLeaseListRemoveStaleLeases(DHCPLeaseListRef list_p) { int count; absolute_time_t current_time; int i; count = dynarray_count(list_p); if (count == 0) { return; } current_time = timer_current_secs(); i = 0; while (i < count) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); /* check the lease expiration */ if (lease_p->lease_length != DHCP_INFINITE_LEASE && current_time >= (lease_p->lease_start + lease_p->lease_length)) { /* lease is expired */ if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "Removing Stale Lease " IP_FORMAT " Router " IP_FORMAT, IP_LIST(&lease_p->our_ip), IP_LIST(&lease_p->router_ip)); } dynarray_free_element(list_p, i); count--; } else { i++; } } return; }
STATIC RTADVSocketRef RTADVSocketFind(int if_index) { int i; for (i = 0; i < dynarray_count(&S_globals->sockets); i++) { interface_t * if_p; RTADVSocketRef sock; sock = dynarray_element(&S_globals->sockets, i); if_p = RTADVSocketGetInterface(sock); if (if_index == if_link_index(if_p)) { return (sock); } } return (NULL); }
static void DHCPv6SocketDemux(int if_index, const DHCPv6PacketRef pkt, int pkt_len) { DHCPv6SocketReceiveData data; DHCPv6OptionErrorString err; int i; if (pkt_len < DHCPV6_PACKET_HEADER_LENGTH) { return; } data.pkt = pkt; data.pkt_len = pkt_len; data.options = DHCPv6OptionListCreateWithPacket(pkt, pkt_len, &err); if (data.options == NULL) { my_log(LOG_NOTICE, "DHCPv6Socket: options parse failed, %s", err.str); return; } for (i = 0; i < dynarray_count(&S_globals->sockets); i++) { DHCPv6SocketRef client; client = dynarray_element(&S_globals->sockets, i); if (if_index != if_link_index(DHCPv6SocketGetInterface(client))) { continue; } if (S_verbose) { CFMutableStringRef str; str = CFStringCreateMutable(NULL, 0); DHCPv6PacketPrintToString(str, pkt, pkt_len); if (data.options != NULL) { DHCPv6OptionListPrintToString(str, data.options); } my_log(-LOG_DEBUG, "[%s] Receive %@", if_name(DHCPv6SocketGetInterface(client)), str); CFRelease(str); } if (client->receive_func != NULL) { (*client->receive_func)(client->receive_arg1, client->receive_arg2, &data); } } DHCPv6OptionListRelease(&data.options); return; }
/* * Function: DHCPLeaseListFindLease * Purpose: * Find a lease corresponding to the supplied information. */ int DHCPLeaseListFindLease(DHCPLeaseListRef list_p, struct in_addr our_ip, struct in_addr router_ip, const uint8_t * router_hwaddr, int router_hwaddr_length) { int count; int i; bool private_ip = ip_is_private(our_ip); count = dynarray_count(list_p); for (i = 0; i < count; i++) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); if (lease_p->our_ip.s_addr != our_ip.s_addr) { /* IP doesn't match */ continue; } if (private_ip == FALSE) { /* lease for public IP is unique */ return (i); } if (lease_p->router_ip.s_addr != router_ip.s_addr) { /* router IP doesn't match (or one is set the other isn't)*/ continue; } if (router_ip.s_addr == 0) { /* found lease with no router information */ return (i); } if (lease_p->router_hwaddr_length != router_hwaddr_length) { /* one has router hwaddr, other doesn't */ continue; } if (router_hwaddr == NULL || router_hwaddr_length == 0) { /* found lease with router IP but no router hwaddr */ return (i); } if (bcmp(lease_p->router_hwaddr, router_hwaddr, router_hwaddr_length) == 0) { /* exact match on IP, router IP, router hwaddr */ return (i); } } return (-1); }
interface_t * ifl_find_ip(interface_list_t * list_p, struct in_addr iaddr) { int i; for (i = 0; i < list_p->count; i++) { interface_t * if_p = list_p->list + i; int j; for (j = 0; j < dynarray_count(&if_p->inet); j++) { inet_addrinfo_t * info; info = dynarray_element(&if_p->inet, j); if (info->addr.s_addr == iaddr.s_addr) return (if_p); } } return (NULL); }
static void DHCPLeaseListLog(DHCPLeaseListRef list_p) { int count; int i; CFMutableStringRef str; str = CFStringCreateMutable(NULL, 0); count = dynarray_count(list_p); for (i = 0; i < count; i++) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); STRING_APPEND(str, "\n%d. ", i + 1); DHCPLeasePrintToString(str, lease_p); } my_log(~LOG_DEBUG, "DHCPLeaseList has %d element(s)%@", count, str); CFRelease(str); return; }
interface_t * ifl_find_subnet(interface_list_t * list_p, struct in_addr iaddr) { int i; u_long addr_hl = iptohl(iaddr); for (i = 0; i < list_p->count; i++) { interface_t * if_p = list_p->list + i; int j; for (j = 0; j < dynarray_count(&if_p->inet); j++) { inet_addrinfo_t * info = dynarray_element(&if_p->inet, j); u_long ifnetaddr_hl = iptohl(info->netaddr); u_long ifmask_hl = iptohl(info->mask); if ((addr_hl & ifmask_hl) == ifnetaddr_hl) return (if_p); } } return (NULL); }
/* * Function: DHCPLeaseListUpdateLease * * Purpose: * Update the lease entry for the given lease in the in-memory lease database. */ void DHCPLeaseListUpdateLease(DHCPLeaseListRef list_p, struct in_addr our_ip, struct in_addr router_ip, const uint8_t * router_hwaddr, int router_hwaddr_length, absolute_time_t lease_start, dhcp_lease_time_t lease_length, const uint8_t * pkt, int pkt_size, CFStringRef ssid) { int count; int i; DHCPLeaseRef lease_p; boolean_t private_ip = ip_is_private(our_ip); lease_p = DHCPLeaseCreate(our_ip, router_ip, router_hwaddr, router_hwaddr_length, lease_start, lease_length, pkt, pkt_size, ssid); /* scan lease list to eliminate NAK'd, incomplete, and duplicate leases */ count = dynarray_count(list_p); for (i = 0; i < count; i++) { DHCPLeaseRef scan_p = dynarray_element(list_p, i); if (DHCPLeaseShouldBeRemoved(scan_p, lease_p, private_ip)) { dynarray_free_element(list_p, i); i--; count--; } } dynarray_add(list_p, lease_p); if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "Saved lease for " IP_FORMAT, IP_LIST(&lease_p->our_ip)); if (G_IPConfiguration_verbose) { DHCPLeaseListLog(list_p); } } return; }
inet_addrinfo_t * if_inet_addr_at(interface_t * if_p, int i) { return (dynarray_element(&if_p->inet, i)); }
/* * Function: DHCPLeaseListCopyARPAddressInfo * Purpose: * Returns a list of arp_address_info_t's corresponding to each * discoverable lease. */ arp_address_info_t * DHCPLeaseListCopyARPAddressInfo(DHCPLeaseListRef list_p, CFStringRef ssid, absolute_time_t * start_time_threshold_p, bool tentative_ok, int * ret_count) { int arp_info_count; arp_address_info_t * arp_info_p; int count; int i; arp_address_info_t * info_p; DHCPLeaseListRemoveStaleLeases(list_p); count = dynarray_count(list_p); if (count == 0) { *ret_count = 0; return (NULL); } arp_info_p = (arp_address_info_t *)malloc(sizeof(*arp_info_p) * count); arp_info_count = 0; info_p = arp_info_p; for (i = 0; i < count; i++) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); if (ssid != NULL) { if (lease_p->ssid == NULL || !CFEqual(lease_p->ssid, ssid)) { if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "ignoring lease with SSID %@", lease_p->ssid); continue; } } } if (lease_p->router_ip.s_addr == 0 || lease_p->router_hwaddr_length == 0) { /* can't use this with ARP discovery */ if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "ignoring lease for " IP_FORMAT, IP_LIST(&lease_p->our_ip)); } continue; } if (lease_p->tentative && tentative_ok == FALSE) { /* ignore tentative lease */ continue; } if (start_time_threshold_p != NULL && lease_p->lease_start < *start_time_threshold_p) { if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "start time on lease " IP_FORMAT " too old (%ld < %ld)", IP_LIST(&lease_p->our_ip), lease_p->lease_start, *start_time_threshold_p); } continue; } info_p->sender_ip = lease_p->our_ip; info_p->target_ip = lease_p->router_ip; bcopy(lease_p->router_hwaddr, info_p->target_hardware, lease_p->router_hwaddr_length); arp_info_count++; info_p++; } if (arp_info_count == 0) { free(arp_info_p); arp_info_p = NULL; } *ret_count = arp_info_count; return (arp_info_p); }