return false;
}
-static bool leases_require_fr(struct interface *iface, struct odhcpd_ipaddr *addr,
- uint32_t mask)
+static bool leases_require_fr(struct interface *iface, struct odhcpd_ipaddr *oaddr)
{
struct dhcpv4_lease *lease = NULL;
struct odhcpd_ref_ip *fr_ip = NULL;
avl_for_each_element(&iface->dhcpv4_leases, lease, iface_avl) {
- if ((lease->accept_fr_nonce || iface->dhcpv4_forcereconf) &&
- !lease->fr_ip &&
- ((lease->ipv4.s_addr & mask) == (addr->addr.in.s_addr & mask))) {
- if (!fr_ip) {
- fr_ip = calloc(1, sizeof(*fr_ip));
- if (!fr_ip)
- break;
+ if (!lease->accept_fr_nonce && !iface->dhcpv4_forcereconf)
+ continue;
- list_add(&fr_ip->head, &iface->dhcpv4_fr_ips);
- fr_ip->addr = *addr;
- }
- inc_ref_cnt_ip(&lease->fr_ip, fr_ip);
+ if (lease->fr_ip)
+ continue;
+
+ if ((lease->ipv4.s_addr & oaddr->netmask) != (oaddr->addr.in.s_addr & oaddr->netmask))
+ continue;
+
+ if (!fr_ip) {
+ fr_ip = calloc(1, sizeof(*fr_ip));
+ if (!fr_ip)
+ break;
+
+ list_add(&fr_ip->head, &iface->dhcpv4_fr_ips);
+ fr_ip->addr = *oaddr;
}
+ inc_ref_cnt_ip(&lease->fr_ip, fr_ip);
}
return fr_ip ? true : false;
.flags = req->flags,
.ciaddr = { INADDR_ANY },
.yiaddr = { INADDR_ANY },
- .siaddr = iface->dhcpv4_local,
+ .siaddr = iface->dhcpv4_own_ip.addr.in,
.giaddr = req->giaddr,
.chaddr = { 0 },
.sname = { 0 },
struct dhcpv4_option_u32 reply_serverid = {
.code = DHCPV4_OPT_SERVERID,
.len = sizeof(struct in_addr),
- .data = iface->dhcpv4_local.s_addr,
+ .data = iface->dhcpv4_own_ip.addr.in.s_addr,
};
struct dhcpv4_option reply_clientid = {
.code = DHCPV4_OPT_CLIENTID,
req_msg = opt->data[0];
break;
case DHCPV4_OPT_SERVERID:
- if (opt->len == 4 && memcmp(opt->data, &iface->dhcpv4_local, 4))
+ if (opt->len == 4 && memcmp(opt->data, &iface->dhcpv4_own_ip, 4))
return;
break;
case DHCPV4_OPT_REQOPTS:
reply_router.len = iface->dhcpv4_router_cnt * sizeof(*iface->dhcpv4_router);
iov[IOV_ROUTER_ADDR].iov_base = iface->dhcpv4_router;
} else {
- reply_router.len = sizeof(iface->dhcpv4_local);
- iov[IOV_ROUTER_ADDR].iov_base = &iface->dhcpv4_local;
+ reply_router.len = sizeof(iface->dhcpv4_own_ip.addr.in);
+ iov[IOV_ROUTER_ADDR].iov_base = &iface->dhcpv4_own_ip.addr.in;
}
iov[IOV_ROUTER_ADDR].iov_len = reply_router.len;
break;
reply_dnsserver.len = iface->dhcpv4_dns_cnt * sizeof(*iface->dhcpv4_dns);
iov[IOV_DNSSERVER_ADDR].iov_base = iface->dhcpv4_dns;
} else {
- reply_dnsserver.len = sizeof(iface->dhcpv4_local);
- iov[IOV_DNSSERVER_ADDR].iov_base = &iface->dhcpv4_local;
+ reply_dnsserver.len = sizeof(iface->dhcpv4_own_ip);
+ iov[IOV_DNSSERVER_ADDR].iov_base = &iface->dhcpv4_own_ip;
}
iov[IOV_DNSSERVER_ADDR].iov_len = reply_dnsserver.len;
break;
iface->dhcpv4_start_ip.s_addr = INADDR_ANY;
iface->dhcpv4_end_ip.s_addr = INADDR_ANY;
- iface->dhcpv4_local.s_addr = INADDR_ANY;
+ iface->dhcpv4_own_ip = (struct odhcpd_ipaddr){ .addr.in.s_addr = INADDR_ANY };
iface->dhcpv4_bcast.s_addr = INADDR_ANY;
iface->dhcpv4_mask.s_addr = INADDR_ANY;
if (!iface->oaddrs4_cnt)
goto error;
- iface->dhcpv4_local.s_addr = iface->oaddrs4[0].addr.in.s_addr;
+ iface->dhcpv4_own_ip = iface->oaddrs4[0];
iface->dhcpv4_bcast = iface->oaddrs4[0].broadcast;
iface->dhcpv4_mask.s_addr = iface->oaddrs4[0].netmask;
iface->dhcpv4_start_ip.s_addr = (oaddr->addr.in.s_addr & oaddr->netmask) | htonl(pool_start);
iface->dhcpv4_end_ip.s_addr = (oaddr->addr.in.s_addr & oaddr->netmask) | htonl(pool_end);
- iface->dhcpv4_local.s_addr = oaddr->addr.in.s_addr;
+ iface->dhcpv4_own_ip = *oaddr;
iface->dhcpv4_bcast = oaddr->broadcast;
iface->dhcpv4_mask.s_addr = oaddr->netmask;
static void dhcpv4_addrlist_change(struct interface *iface)
{
- struct odhcpd_ipaddr ip;
+ struct odhcpd_ipaddr ip = iface->dhcpv4_own_ip;
struct odhcpd_ref_ip *a;
struct dhcpv4_lease *lease;
- uint32_t mask = iface->dhcpv4_mask.s_addr;
-
- memset(&ip, 0, sizeof(ip));
- ip.addr.in = iface->dhcpv4_local;
- ip.prefix_len = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask);
- ip.broadcast = iface->dhcpv4_bcast;
dhcpv4_setup_addresses(iface);
- if ((ip.addr.in.s_addr & mask) ==
- (iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr))
+ if ((ip.addr.in.s_addr & ip.netmask) ==
+ (iface->dhcpv4_own_ip.addr.in.s_addr & iface->dhcpv4_own_ip.netmask))
+ return;
+
+ if (ip.addr.in.s_addr && !leases_require_fr(iface, &ip))
return;
- if (ip.addr.in.s_addr && !leases_require_fr(iface, &ip, mask))
+ if (iface->dhcpv4_own_ip.addr.in.s_addr == INADDR_ANY)
return;
- if (iface->dhcpv4_local.s_addr == INADDR_ANY || list_empty(&iface->dhcpv4_fr_ips))
+ if (list_empty(&iface->dhcpv4_fr_ips))
return;
a = list_first_entry(&iface->dhcpv4_fr_ips, struct odhcpd_ref_ip, head);
uint32_t dhcpv4_pool_end; // Offset to last dynamic address
struct in_addr dhcpv4_start_ip;
struct in_addr dhcpv4_end_ip;
- struct in_addr dhcpv4_local;
+ struct odhcpd_ipaddr dhcpv4_own_ip;
struct in_addr dhcpv4_bcast;
struct in_addr dhcpv4_mask;
struct in_addr *dhcpv4_router;
void odhcpd_enum_addr6(struct interface *iface, struct dhcpv6_lease *lease,
time_t now, odhcpd_enum_addr6_cb_t func, void *arg);
int odhcpd_parse_addr6_prefix(const char *str, struct in6_addr *addr, uint8_t *prefix);
-int odhcpd_netmask2bitlen(bool v6, void *mask);
bool odhcpd_valid_hostname(const char *name);
int config_parse_interface(void *data, size_t len, const char *iname, bool overwrite);