-/* $OpenBSD: dhclient.c,v 1.428 2017/06/16 14:12:12 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.429 2017/06/17 15:53:03 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
cancel_timeout();
- /* Take the first valid DHCPOFFER. */
- TAILQ_FOREACH_SAFE(picked, &ifi->offered_leases, next, lease) {
- if (picked->is_invalid == 0) {
- TAILQ_REMOVE(&ifi->offered_leases, picked, next);
- break;
- }
+ if (TAILQ_EMPTY(&ifi->offered_leases)) {
+ state_panic(ifi);
+ return;
}
+
+ picked = TAILQ_FIRST(&ifi->offered_leases);
+ TAILQ_REMOVE(&ifi->offered_leases, picked, next);
+
/* DECLINE the rest of the offers. */
while (!TAILQ_EMPTY(&ifi->offered_leases)) {
lease = TAILQ_FIRST(&ifi->offered_leases);
free_client_lease(lease);
}
- if (!picked) {
- state_panic(ifi);
- return;
- }
-
/* If it was a BOOTREPLY, we can just take the lease right now. */
if (BOOTP_LEASE(picked)) {
struct option_data *option;
log_info("%s", info);
lease = packet_to_lease(ifi, options);
- if (lease->is_invalid) {
- log_info("Unsatisfactory %s", info);
- make_decline(ifi, lease);
- send_decline(ifi);
- free_client_lease(lease);
+ if (lease == NULL) {
ifi->state = S_INIT;
state_init(ifi);
return;
}
lease = packet_to_lease(ifi, options);
+ if (lease != NULL) {
+ if (TAILQ_EMPTY(&ifi->offered_leases)) {
+ TAILQ_INSERT_HEAD(&ifi->offered_leases, lease, next);
+ } else if (lease->address.s_addr ==
+ ifi->requested_address.s_addr) {
+ /* The expected lease - put it first. */
+ TAILQ_INSERT_HEAD(&ifi->offered_leases, lease, next);
+ } else {
+ /* Put it at the end of the list. */
+ TAILQ_INSERT_TAIL(&ifi->offered_leases, lease, next);
+ }
+ }
/* Figure out when we're supposed to stop selecting. */
stop_selecting = ifi->first_sending + config->select_interval;
-
- if (TAILQ_EMPTY(&ifi->offered_leases)) {
- TAILQ_INSERT_HEAD(&ifi->offered_leases, lease, next);
- } else if (lease->address.s_addr == ifi->requested_address.s_addr) {
- /* The expected lease - put it at the head of the list. */
- TAILQ_INSERT_HEAD(&ifi->offered_leases, lease, next);
- } else {
- /* Not the expected lease - put it at the end of the list. */
- TAILQ_INSERT_TAIL(&ifi->offered_leases, lease, next);
- }
-
if (stop_selecting <= time(NULL))
state_selecting(ifi);
else
/*
* Allocate a client_lease structure and initialize it from the
- * parameters in the specified packet.
+ * parameters in the received packet.
+ *
+ * Return NULL and decline the lease if a valid lease cannot be
+ * constructed.
*/
struct client_lease *
packet_to_lease(struct interface_info *ifi, struct option_data *options)
int i;
lease = calloc(1, sizeof(struct client_lease));
- if (!lease) {
- log_warnx("dhcpoffer: no memory to create lease.");
- return (NULL);
+ if (lease == NULL) {
+ log_warnx("lease declined: no memory for lease.");
+ return NULL;
}
/* Copy the lease options. */
continue;
if (!unknown_ok && strncmp("option-",
dhcp_options[i].name, 7) != 0) {
- log_warnx("dhcpoffer: unknown option %d", i);
- lease->is_invalid = 1;
+ log_warnx("lease declined: unknown option %d", i);
+ goto decline;
}
pretty = pretty_print_option(i, &options[i], 0);
if (strlen(pretty) == 0)
options[i].len);
if (buf == NULL)
continue;
- if (!res_hnok_list(buf))
- log_warnx("Bogus data for option %s",
- dhcp_options[i].name);
+ if (!res_hnok_list(buf)) {
+ log_warnx("lease declined: invalid host "
+ "name(s) in %s", dhcp_options[i].name);
+ goto decline;
+ }
break;
case DHO_DOMAIN_NAME:
/*
* entries in the resolv.conf 'search' statement.
*/
if (!res_hnok_list(pretty)) {
- log_warnx("Bogus data for option %s",
- dhcp_options[i].name);
- continue;
+ log_warnx("lease declined: invalid host "
+ "names in %s", dhcp_options[i].name);
+ goto decline;
}
break;
case DHO_HOST_NAME:
case DHO_NIS_DOMAIN:
if (!res_hnok(pretty)) {
- log_warnx("Bogus data for option %s",
- dhcp_options[i].name);
- continue;
+ log_warnx("lease declined: invalid host name "
+ "in %s", dhcp_options[i].name);
+ goto decline;
}
break;
default:
*/
for (i = 0; i < config->required_option_count; i++) {
if (!lease->options[config->required_options[i]].len) {
- log_warnx("Missing required parameter %s",
+ log_warnx("lease declined: %s required but missing",
dhcp_options[i].name);
- lease->is_invalid = 1;
+ goto decline;
}
}
memset(ifname, 0, sizeof(ifname));
if (addressinuse(ifi, lease->address, ifname) &&
strncmp(ifname, ifi->name, IF_NAMESIZE) != 0) {
- log_warnx("%s already configured on %s",
+ log_warnx("lease declined: %s already configured on %s",
inet_ntoa(lease->address), ifname);
- lease->is_invalid = 1;
+ goto decline;
}
/* Save the siaddr (a.k.a. next-server) info. */
packet->sname[0]) {
lease->server_name = malloc(DHCP_SNAME_LEN + 1);
if (!lease->server_name) {
- log_warnx("dhcpoffer: no memory for server name.");
- lease->is_invalid = 1;
+ log_warnx("lease declined:: no memory for SNAME.");
+ goto decline;
}
memcpy(lease->server_name, packet->sname, DHCP_SNAME_LEN);
lease->server_name[DHCP_SNAME_LEN] = '\0';
if (!res_hnok(lease->server_name)) {
- log_warnx("Bogus server name %s", lease->server_name);
- lease->is_invalid = 1;
+ log_warnx("lease declined: invalid host name in SNAME");
+ goto decline;
}
}
/* Don't count on the NUL terminator. */
lease->filename = malloc(DHCP_FILE_LEN + 1);
if (!lease->filename) {
- log_warnx("dhcpoffer: no memory for filename.");
- lease->is_invalid = 1;
+ log_warnx("lease declined: no memory for filename.");
+ goto decline;
}
memcpy(lease->filename, packet->file, DHCP_FILE_LEN);
lease->filename[DHCP_FILE_LEN] = '\0';
}
return lease;
+
+ decline:
+ make_decline(ifi, lease);
+ send_decline(ifi);
+ free_client_lease(lease);
+ return NULL;
}
void