void lease_update_from_configs(void) { /* changes to the config may change current leases. */ struct dhcp_lease *lease; struct dhcp_config *config; char *name; for (lease = leases; lease; lease = lease->next) if (lease->flags & (LEASE_TA | LEASE_NA)) continue; else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && (config->flags & CONFIG_NAME) && (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr)) lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL); else if ((name = host_from_dns(lease->addr))) lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */ }
static DBusMessage *dbus_add_lease(DBusMessage* message) { struct dhcp_lease *lease; const char *ipaddr, *hwaddr, *hostname, *tmp; const unsigned char* clid; int clid_len, hostname_len, hw_len, hw_type; dbus_uint32_t expires, ia_id; dbus_bool_t is_temporary; struct all_addr addr; time_t now = dnsmasq_time(); unsigned char dhcp_chaddr[DHCP_CHADDR_MAX]; DBusMessageIter iter, array_iter; if (!dbus_message_iter_init(message, &iter)) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Failed to initialize dbus message iter"); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected string as first argument"); dbus_message_iter_get_basic(&iter, &ipaddr); dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected string as second argument"); dbus_message_iter_get_basic(&iter, &hwaddr); dbus_message_iter_next(&iter); if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) || (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected byte array as third argument"); dbus_message_iter_recurse(&iter, &array_iter); dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len); tmp = memchr(hostname, '\0', hostname_len); if (tmp) { if (tmp == &hostname[hostname_len - 1]) hostname_len--; else return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Hostname contains an embedded NUL character"); } dbus_message_iter_next(&iter); if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) || (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected byte array as fourth argument"); dbus_message_iter_recurse(&iter, &array_iter); dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len); dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected uint32 as fifth argument"); dbus_message_iter_get_basic(&iter, &expires); dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected uint32 as sixth argument"); dbus_message_iter_get_basic(&iter, &ia_id); dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected uint32 as sixth argument"); dbus_message_iter_get_basic(&iter, &is_temporary); if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4)) { if (ia_id != 0 || is_temporary) return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "ia_id and is_temporary must be zero for IPv4 lease"); if (!(lease = lease_find_by_addr(addr.addr.addr4))) lease = lease4_allocate(addr.addr.addr4); } #ifdef HAVE_DHCP6 else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6)) { if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0))) lease = lease6_allocate(&addr.addr.addr6, is_temporary ? LEASE_TA : LEASE_NA); lease_set_iaid(lease, ia_id); } #endif else return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS, "Invalid IP address '%s'", ipaddr); hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type); if (hw_type == 0 && hw_len != 0) hw_type = ARPHRD_ETHER; lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type, clid_len, now, 0); lease_set_expires(lease, expires, now); if (hostname_len != 0) lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL); lease_update_file(now); lease_update_dns(0); return NULL; }
void lease_init(time_t now) { unsigned long ei; struct all_addr addr; struct dhcp_lease *lease; int clid_len, hw_len, hw_type; FILE *leasestream; leases_left = daemon->dhcp_max; if (option_bool(OPT_LEASE_RO)) { /* run "<lease_change_script> init" once to get the initial state of the database. If leasefile-ro is set without a script, we just do without any lease database. */ #ifdef HAVE_SCRIPT if (daemon->lease_change_command) { strcpy(daemon->dhcp_buff, daemon->lease_change_command); strcat(daemon->dhcp_buff, " init"); leasestream = popen(daemon->dhcp_buff, "r"); } else #endif { file_dirty = dns_dirty = 0; return; } } else { /* NOTE: need a+ mode to create file if it doesn't exist */ leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+"); if (!leasestream) die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE); /* a+ mode leaves pointer at end. */ rewind(leasestream); } /* client-id max length is 255 which is 255*2 digits + 254 colons borrow DNS packet buffer which is always larger than 1000 bytes */ if (leasestream) while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2) { #ifdef HAVE_DHCP6 if (strcmp(daemon->dhcp_buff3, "duid") == 0) { daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL); daemon->duid = safe_malloc(daemon->duid_len); memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len); continue; } #endif ei = atol(daemon->dhcp_buff3); if (fscanf(leasestream, " %64s %255s %764s", daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3) break; clid_len = 0; if (strcmp(daemon->packet, "*") != 0) clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL); if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) && (lease = lease4_allocate(addr.addr.addr4))) { hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type); /* For backwards compatibility, no explict MAC address type means ether. */ if (hw_type == 0 && hw_len != 0) hw_type = ARPHRD_ETHER; lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len, now, 0); if (strcmp(daemon->dhcp_buff, "*") != 0) lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL); } #ifdef HAVE_DHCP6 else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6)) { char *s = daemon->dhcp_buff2; int lease_type = LEASE_NA; int iaid; if (s[0] == 'T') { lease_type = LEASE_TA; s++; } iaid = strtoul(s, NULL, 10); if ((lease = lease6_allocate(&addr.addr.addr6, lease_type))) { lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0); lease_set_iaid(lease, iaid); if (strcmp(daemon->dhcp_buff, "*") != 0) lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL); } } #endif else break; if (!lease) die (_("too many stored leases"), NULL, EC_MISC); //Some ASUS & TOMATO tweaks #if defined(HAVE_BROKEN_RTC) || defined(HAVE_LEASEFILE_EXPIRE) if (ei != 0) lease->expires = (time_t)ei + now; else lease->expires = (time_t)0; #ifdef HAVE_BROKEN_RT lease->length = ei; #endif #else /* strictly time_t is opaque, but this hack should work on all sane systems, even when sizeof(time_t) == 8 */ lease->expires = (time_t)ei; #endif /* set these correctly: the "old" events are generated later from the startup synthesised SIGHUP. */ lease->flags &= ~(LEASE_NEW | LEASE_CHANGED); } #ifdef HAVE_SCRIPT if (!daemon->lease_stream) { int rc = 0; /* shell returns 127 for "command not found", 126 for bad permissions. */ if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126) { if (WEXITSTATUS(rc) == 127) errno = ENOENT; else if (WEXITSTATUS(rc) == 126) errno = EACCES; die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE); } if (WEXITSTATUS(rc) != 0) { sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc)); die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET); } } #endif /* Some leases may have expired */ file_dirty = 0; lease_prune(NULL, now); dns_dirty = 1; }