#include "ipv4ll.h"
#include "net.h"
-static struct dhcp_message*
-make_ipv4ll_lease(uint32_t old_addr)
+static struct dhcp_message *
+make_ipv4ll_lease(uint32_t addr)
{
uint32_t u32;
struct dhcp_message *dhcp;
dhcp = xzalloc(sizeof(*dhcp));
/* Put some LL options in */
+ dhcp->yiaddr = addr;
p = dhcp->options;
*p++ = DHO_SUBNETMASK;
*p++ = sizeof(u32);
p += sizeof(u32);
*p++ = DHO_END;
+ return dhcp;
+}
+
+static struct dhcp_message *
+find_ipv4ll_lease(uint32_t old_addr)
+{
+ uint32_t addr;
+
for (;;) {
- dhcp->yiaddr = htonl(LINKLOCAL_ADDR |
+ addr = htonl(LINKLOCAL_ADDR |
(((uint32_t)abs((int)arc4random())
% 0xFD00) + 0x0100));
- if (dhcp->yiaddr != old_addr &&
- IN_LINKLOCAL(ntohl(dhcp->yiaddr)))
+ if (addr != old_addr &&
+ IN_LINKLOCAL(ntohl(addr)))
break;
}
- return dhcp;
+ return make_ipv4ll_lease(addr);
}
void
start_ipv4ll(void *arg)
{
struct interface *iface = arg;
+ uint32_t addr;
delete_timeout(NULL, iface);
iface->state->probes = 0;
}
}
+ if (iface->state->offer == NULL)
+ addr = 0;
+ else {
+ addr = iface->state->offer->yiaddr;
+ free(iface->state->offer);
+ }
/* We maybe rebooting an IPv4LL address. */
- if (!iface->state->offer ||
- !IN_LINKLOCAL(htonl(iface->state->offer->yiaddr)))
- {
+ if (!IN_LINKLOCAL(htonl(addr))) {
syslog(LOG_INFO, "%s: probing for an IPv4LL address",
iface->name);
- delete_timeout(NULL, iface);
- free(iface->state->offer);
- iface->state->offer = make_ipv4ll_lease(0);
- iface->state->lease.frominfo = 0;
+ addr = 0;
}
- /* Ensure we don't have a cookie */
- iface->state->offer->cookie = 0;
+ if (addr == 0)
+ iface->state->offer = find_ipv4ll_lease(addr);
+ else
+ iface->state->offer = make_ipv4ll_lease(addr);
+ iface->state->lease.frominfo = 0;
send_arp_probe(iface);
}