--- embedaddon/dnsmasq/src/lease.c 2013/07/29 19:37:40 1.1.1.1 +++ embedaddon/dnsmasq/src/lease.c 2021/03/17 00:56:46 1.1.1.4 @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,90 +21,64 @@ static struct dhcp_lease *leases = NULL, *old_leases = NULL; static int dns_dirty, file_dirty, leases_left; -void lease_init(time_t now) +static int read_leases(time_t now, FILE *leasestream) { unsigned long ei; - struct all_addr addr; + union 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 " 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 + int items; + char *domain = NULL; + + *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0'; + + /* client-id max length is 255 which is 255*2 digits + 254 colons + borrow DNS packet buffer which is always larger than 1000 bytes + + Check various buffers are big enough for the code below */ + +#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ < 764) +# error Buffer size breakage in leasefile parsing. #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) + while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2) { + *daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0'; + hw_len = hw_type = clid_len = 0; + #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); + if (daemon->duid_len < 0) + return 0; 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))) { + my_syslog(MS_DHCP | LOG_WARNING, _("ignoring invalid line in lease database: %s %s %s %s ..."), + daemon->dhcp_buff3, daemon->dhcp_buff2, + daemon->namebuff, daemon->dhcp_buff); + continue; + } + + if (inet_pton(AF_INET, daemon->namebuff, &addr.addr4)) + { + if ((lease = lease4_allocate(addr.addr4))) + domain = get_domain(lease->addr); + 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. */ + /* For backwards compatibility, no explicit 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)) + else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr6)) { char *s = daemon->dhcp_buff2; int lease_type = LEASE_NA; @@ -115,23 +89,35 @@ void lease_init(time_t now) s++; } - hw_type = strtoul(s, NULL, 10); - - if ((lease = lease6_allocate(&addr.addr.addr6, lease_type))) + if ((lease = lease6_allocate(&addr.addr6, lease_type))) { - lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, hw_type, clid_len, now, 0); - - if (strcmp(daemon->dhcp_buff, "*") != 0) - lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL); + lease_set_iaid(lease, strtoul(s, NULL, 10)); + domain = get_domain6(&lease->addr6); } } #endif else - break; + { + my_syslog(MS_DHCP | LOG_WARNING, _("ignoring invalid line in lease database, bad address: %s"), + daemon->namebuff); + continue; + } + if (!lease) die (_("too many stored leases"), NULL, EC_MISC); - + + if (strcmp(daemon->packet, "*") != 0) + clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL); + + 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, domain, NULL); + + ei = atol(daemon->dhcp_buff3); + #ifdef HAVE_BROKEN_RTC if (ei != 0) lease->expires = (time_t)ei + now; @@ -147,7 +133,60 @@ void lease_init(time_t now) /* set these correctly: the "old" events are generated later from the startup synthesised SIGHUP. */ lease->flags &= ~(LEASE_NEW | LEASE_CHANGED); + + *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0'; } + + return (items == 0 || items == EOF); +} + +void lease_init(time_t now) +{ + FILE *leasestream; + + leases_left = daemon->dhcp_max; + + if (option_bool(OPT_LEASE_RO)) + { + /* run " 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); + } + + if (leasestream) + { + if (!read_leases(now, leasestream)) + my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database cleanly")); + + if (ferror(leasestream)) + die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE); + } #ifdef HAVE_SCRIPT if (!daemon->lease_stream) @@ -161,6 +200,7 @@ void lease_init(time_t now) errno = ENOENT; else if (WEXITSTATUS(rc) == 126) errno = EACCES; + die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE); } @@ -187,15 +227,17 @@ void lease_update_from_configs(void) char *name; for (lease = leases; lease; lease = lease->next) - 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)) + 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, 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 void ourprintf(int *errp, char *format, ...) { va_list ap; @@ -277,10 +319,10 @@ void lease_update_file(time_t now) ourprintf(&err, "%lu ", (unsigned long)lease->expires); #endif - inet_ntop(AF_INET6, lease->hwaddr, daemon->addrbuff, ADDRSTRLEN); + inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN); ourprintf(&err, "%s%u %s ", (lease->flags & LEASE_TA) ? "T" : "", - lease->hwaddr_type, daemon->addrbuff); + lease->iaid, daemon->addrbuff); ourprintf(&err, "%s ", lease->hostname ? lease->hostname : "*"); if (lease->clid && lease->clid_len != 0) @@ -303,7 +345,7 @@ void lease_update_file(time_t now) file_dirty = 0; } - /* Set alarm for when the first lease expires + slop. */ + /* Set alarm for when the first lease expires. */ next_event = 0; #ifdef HAVE_DHCP6 @@ -328,8 +370,8 @@ void lease_update_file(time_t now) for (lease = leases; lease; lease = lease->next) if (lease->expires != 0 && - (next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0)) - next_event = lease->expires + 10; + (next_event == 0 || difftime(next_event, lease->expires) > 0.0)) + next_event = lease->expires; if (err) { @@ -345,19 +387,25 @@ void lease_update_file(time_t now) } -static int find_interface_v4(struct in_addr local, int if_index, +static int find_interface_v4(struct in_addr local, int if_index, char *label, struct in_addr netmask, struct in_addr broadcast, void *vparam) { struct dhcp_lease *lease; - + int prefix = netmask_length(netmask); + + (void) label; (void) broadcast; (void) vparam; for (lease = leases; lease; lease = lease->next) - if (!(lease->flags & (LEASE_TA | LEASE_NA))) - if (is_same_net(local, lease->addr, netmask)) - lease_set_interface(lease, if_index, *((time_t *)vparam)); - + if (!(lease->flags & (LEASE_TA | LEASE_NA)) && + is_same_net(local, lease->addr, netmask) && + prefix > lease->new_prefixlen) + { + lease->new_interface = if_index; + lease->new_prefixlen = prefix; + } + return 1; } @@ -367,17 +415,23 @@ static int find_interface_v6(struct in6_addr *local, int preferred, int valid, void *vparam) { struct dhcp_lease *lease; - + (void)scope; (void)flags; (void)preferred; (void)valid; + (void)vparam; for (lease = leases; lease; lease = lease->next) if ((lease->flags & (LEASE_TA | LEASE_NA))) - if (is_same_net6(local, (struct in6_addr *)&lease->hwaddr, prefix)) - lease_set_interface(lease, if_index, *((time_t *)vparam)); - + if (is_same_net6(local, &lease->addr6, prefix) && prefix > lease->new_prefixlen) { + /* save prefix length for comparison, as we might get shorter matching + * prefix in upcoming netlink GETADDR responses + * */ + lease->new_interface = if_index; + lease->new_prefixlen = prefix; + } + return 1; } @@ -391,7 +445,7 @@ void lease_ping_reply(struct in6_addr *sender, unsigne void lease_update_slaac(time_t now) { - /* Called when we contruct a new RA-names context, to add putative + /* Called when we construct a new RA-names context, to add putative new SLAAC addresses to existing leases. */ struct dhcp_lease *lease; @@ -410,21 +464,36 @@ void lease_update_slaac(time_t now) start-time. */ void lease_find_interfaces(time_t now) { + struct dhcp_lease *lease; + + for (lease = leases; lease; lease = lease->next) + lease->new_prefixlen = lease->new_interface = 0; + iface_enumerate(AF_INET, &now, find_interface_v4); #ifdef HAVE_DHCP6 iface_enumerate(AF_INET6, &now, find_interface_v6); +#endif + for (lease = leases; lease; lease = lease->next) + if (lease->new_interface != 0) + lease_set_interface(lease, lease->new_interface, now); +} + +#ifdef HAVE_DHCP6 +void lease_make_duid(time_t now) +{ /* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */ - if (!daemon->duid && daemon->dhcp6) + if (!daemon->duid && daemon->doing_dhcp6) { file_dirty = 1; make_duid(now); } -#endif } +#endif + void lease_update_dns(int force) { struct dhcp_lease *lease; @@ -453,22 +522,29 @@ void lease_update_dns(int force) if (slaac->backoff == 0) { if (lease->fqdn) - cache_add_dhcp_entry(lease->fqdn, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires); + cache_add_dhcp_entry(lease->fqdn, AF_INET6, (union all_addr *)&slaac->addr, lease->expires); if (!option_bool(OPT_DHCP_FQDN) && lease->hostname) - cache_add_dhcp_entry(lease->hostname, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires); + cache_add_dhcp_entry(lease->hostname, AF_INET6, (union all_addr *)&slaac->addr, lease->expires); } } -#endif if (lease->fqdn) cache_add_dhcp_entry(lease->fqdn, prot, - prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->hwaddr, + prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6, lease->expires); if (!option_bool(OPT_DHCP_FQDN) && lease->hostname) cache_add_dhcp_entry(lease->hostname, prot, - prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->hwaddr, + prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6, lease->expires); + +#else + if (lease->fqdn) + cache_add_dhcp_entry(lease->fqdn, prot, (union all_addr *)&lease->addr, lease->expires); + + if (!option_bool(OPT_DHCP_FQDN) && lease->hostname) + cache_add_dhcp_entry(lease->hostname, prot, (union all_addr *)&lease->addr, lease->expires); +#endif } dns_dirty = 0; @@ -482,12 +558,14 @@ void lease_prune(struct dhcp_lease *target, time_t now for (lease = leases, up = &leases; lease; lease = tmp) { tmp = lease->next; - if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target) + if ((lease->expires != 0 && difftime(now, lease->expires) >= 0) || lease == target) { file_dirty = 1; if (lease->hostname) dns_dirty = 1; - + + daemon->metrics[lease->addr.s_addr ? METRIC_LEASES_PRUNED_4 : METRIC_LEASES_PRUNED_6]++; + *up = lease->next; /* unlink */ /* Put on old_leases list 'till we @@ -557,16 +635,17 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr a #ifdef HAVE_DHCP6 /* find address for {CLID, IAID, address} */ struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len, - int lease_type, int iaid, struct in6_addr *addr) + int lease_type, unsigned int iaid, + struct in6_addr *addr) { struct dhcp_lease *lease; for (lease = leases; lease; lease = lease->next) { - if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid) + if (!(lease->flags & lease_type) || lease->iaid != iaid) continue; - if (memcmp(lease->hwaddr, addr, IN6ADDRSZ) != 0) + if (!IN6_ARE_ADDR_EQUAL(&lease->addr6, addr)) continue; if ((clid_len != lease->clid_len || @@ -589,7 +668,9 @@ void lease6_reset(void) } /* enumerate all leases belonging to {CLID, IAID} */ -struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, unsigned char *clid, int clid_len, int iaid) +struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, + unsigned char *clid, int clid_len, + unsigned int iaid) { struct dhcp_lease *lease; @@ -603,7 +684,7 @@ struct dhcp_lease *lease6_find_by_client(struct dhcp_l if (lease->flags & LEASE_USED) continue; - if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid) + if (!(lease->flags & lease_type) || lease->iaid != iaid) continue; if ((clid_len != lease->clid_len || @@ -625,8 +706,8 @@ struct dhcp_lease *lease6_find_by_addr(struct in6_addr if (!(lease->flags & (LEASE_TA | LEASE_NA))) continue; - if (is_same_net6((struct in6_addr *)lease->hwaddr, net, prefix) && - (prefix == 128 || addr6part((struct in6_addr *)lease->hwaddr) == addr)) + if (is_same_net6(&lease->addr6, net, prefix) && + (prefix == 128 || addr6part(&lease->addr6) == addr)) return lease; } @@ -645,11 +726,11 @@ u64 lease_find_max_addr6(struct dhcp_context *context) if (!(lease->flags & (LEASE_TA | LEASE_NA))) continue; - if (is_same_net6((struct in6_addr *)lease->hwaddr, &context->start6, 64) && - addr6part((struct in6_addr *)lease->hwaddr) > addr6part(&context->start6) && - addr6part((struct in6_addr *)lease->hwaddr) <= addr6part(&context->end6) && - addr6part((struct in6_addr *)lease->hwaddr) > addr) - addr = addr6part((struct in6_addr *)lease->hwaddr); + if (is_same_net6(&lease->addr6, &context->start6, 64) && + addr6part(&lease->addr6) > addr6part(&context->start6) && + addr6part(&lease->addr6) <= addr6part(&context->end6) && + addr6part(&lease->addr6) > addr) + addr = addr6part(&lease->addr6); } return addr; @@ -691,6 +772,7 @@ static struct dhcp_lease *lease_allocate(void) #ifdef HAVE_BROKEN_RTC lease->length = 0xffffffff; /* illegal value */ #endif + lease->hwaddr_len = 256; /* illegal value */ lease->next = leases; leases = lease; @@ -706,9 +788,9 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr if (lease) { lease->addr = addr; - lease->hwaddr_len = 256; /* illegal value */ + daemon->metrics[METRIC_LEASES_ALLOCATED_4]++; } - + return lease; } @@ -719,8 +801,11 @@ struct dhcp_lease *lease6_allocate(struct in6_addr *ad if (lease) { - memcpy(lease->hwaddr, addrp, sizeof(*addrp)) ; + lease->addr6 = *addrp; lease->flags |= lease_type; + lease->iaid = 0; + + daemon->metrics[METRIC_LEASES_ALLOCATED_6]++; } return lease; @@ -729,20 +814,29 @@ struct dhcp_lease *lease6_allocate(struct in6_addr *ad void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now) { - time_t exp = now + (time_t)len; - + time_t exp; + if (len == 0xffffffff) { exp = 0; len = 0; } - + else + { + exp = now + (time_t)len; + /* Check for 2038 overflow. Make the lease + infinite in that case, as the least disruptive + thing we can do. */ + if (difftime(exp, now) <= 0.0) + exp = 0; + } + if (exp != lease->expires) { dns_dirty = 1; lease->expires = exp; #ifndef HAVE_BROKEN_RTC - lease->flags |= LEASE_AUX_CHANGED; + lease->flags |= LEASE_AUX_CHANGED | LEASE_EXP_CHANGED; file_dirty = 1; #endif } @@ -757,16 +851,28 @@ void lease_set_expires(struct dhcp_lease *lease, unsig #endif } -void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr, - unsigned char *clid, int hw_len, int hw_type, int clid_len, - time_t now, int force) +#ifdef HAVE_DHCP6 +void lease_set_iaid(struct dhcp_lease *lease, unsigned int iaid) { + if (lease->iaid != iaid) + { + lease->iaid = iaid; + lease->flags |= LEASE_CHANGED; + } +} +#endif + +void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr, + const unsigned char *clid, int hw_len, int hw_type, + int clid_len, time_t now, int force) +{ #ifdef HAVE_DHCP6 int change = force; lease->flags |= LEASE_HAVE_HWADDR; #endif (void)force; + (void)now; if (hw_len != lease->hwaddr_len || hw_type != lease->hwaddr_type || @@ -778,9 +884,6 @@ void lease_set_hwaddr(struct dhcp_lease *lease, unsign lease->hwaddr_type = hw_type; lease->flags |= LEASE_CHANGED; file_dirty = 1; /* run script on change */ -#ifdef HAVE_DHCP6 - change = 1; -#endif } /* only update clid when one is available, stops packets @@ -843,7 +946,7 @@ static void kill_name(struct dhcp_lease *lease) lease->hostname = lease->fqdn = NULL; } -void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain) +void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain) { struct dhcp_lease *lease_tmp; char *new_name = NULL, *new_fqdn = NULL; @@ -938,6 +1041,8 @@ void lease_set_hostname(struct dhcp_lease *lease, char void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now) { + (void)now; + if (lease->last_interface == interface) return; @@ -966,6 +1071,8 @@ int do_script_run(time_t now) { struct dhcp_lease *lease; + (void)now; + #ifdef HAVE_DBUS /* If we're going to be sending DBus signals, but the connection is not yet up, delay everything until it is. */ @@ -1029,7 +1136,8 @@ int do_script_run(time_t now) for (lease = leases; lease; lease = lease->next) if ((lease->flags & (LEASE_NEW | LEASE_CHANGED)) || - ((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO))) + ((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO)) || + ((lease->flags & LEASE_EXP_CHANGED) && option_bool(OPT_LEASE_RENEW))) { #ifdef HAVE_SCRIPT queue_script((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease, @@ -1039,7 +1147,7 @@ int do_script_run(time_t now) emit_dbus_signal((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease, lease->fqdn ? lease->fqdn : lease->hostname); #endif - lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED); + lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED | LEASE_EXP_CHANGED); /* this is used for the "add" call, then junked, since they're not in the database */ free(lease->extradata); @@ -1052,18 +1160,22 @@ int do_script_run(time_t now) } #ifdef HAVE_SCRIPT +/* delim == -1 -> delim = 0, but embedded 0s, creating extra records, are OK. */ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim) { unsigned int i; - /* check for embeded NULLs */ - for (i = 0; i < len; i++) - if (data[i] == 0) - { - len = i; - break; - } - + if (delim == -1) + delim = 0; + else + /* check for embedded NULLs */ + for (i = 0; i < len; i++) + if (data[i] == 0) + { + len = i; + break; + } + if ((lease->extradata_size - lease->extradata_len) < (len + 1)) { size_t newsz = lease->extradata_len + len + 100;