summaryrefslogtreecommitdiff
path: root/sbin/dhclient/dhclient.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2013-07-15 14:03:02 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2013-07-15 14:03:02 +0000
commitb74692e3063367c6a49346f5bfb954359e108a5a (patch)
tree7fa55ddb5f9eb7097b4b90c69b90a0c7e435d8aa /sbin/dhclient/dhclient.c
parenta2b76d9d3d6cf6a707933ea4b12ea3344c111fc3 (diff)
If a DHCPREQUEST returns a lease identical to the one currently bound to
the interface, skip the address deleting/adding and route deleting/adding and simply update the timestamps. Suggested by sthen@. Tweaks from millert@. ok sthen@ millert@
Diffstat (limited to 'sbin/dhclient/dhclient.c')
-rw-r--r--sbin/dhclient/dhclient.c66
1 files changed, 62 insertions, 4 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index ceeea506b00..631af5c7c7e 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.259 2013/07/06 03:13:34 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.260 2013/07/15 14:03:01 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -112,6 +112,8 @@ void add_default_route(int, struct in_addr, struct in_addr);
void add_static_routes(int, struct option_data *);
void add_classless_static_routes(int, struct option_data *);
+int compare_lease(struct client_lease *, struct client_lease *);
+
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
@@ -798,13 +800,27 @@ bind_lease(void)
struct option_data *options;
struct client_lease *lease;
+ lease = apply_defaults(client->new);
+ options = lease->options;
+
+ /*
+ * A duplicate lease once we are responsible means we don't
+ * need to change the interface, routing table or resolv.conf.
+ */
+ if ((client->flags & IS_RESPONSIBLE) &&
+ compare_lease(client->active, client->new) == 0) {
+ client->new->resolv_conf = client->active->resolv_conf;
+ client->active->resolv_conf = NULL;
+ note("bound to %s -- renewal in %lld seconds.",
+ inet_ntoa(client->new->address),
+ (long long)(client->new->renewal - time(NULL)));
+ goto newlease;
+ }
+
/* Deleting the addresses also clears out arp entries. */
delete_addresses(ifi->name, ifi->rdomain);
flush_routes(ifi->name, ifi->rdomain);
- lease = apply_defaults(client->new);
- options = lease->options;
-
memset(&mask, 0, sizeof(mask));
memcpy(&mask.s_addr, options[DHO_SUBNET_MASK].data,
options[DHO_SUBNET_MASK].len);
@@ -840,6 +856,7 @@ bind_lease(void)
client->new->resolv_conf, strlen(client->new->resolv_conf));
/* Replace the old active lease with the new one. */
+newlease:
if (client->active)
free_client_lease(client->active);
client->active = client->new;
@@ -2399,3 +2416,44 @@ void add_classless_static_routes(int rdomain,
RTF_GATEWAY | RTF_STATIC);
}
}
+
+int
+compare_lease(struct client_lease *active, struct client_lease *new)
+{
+ int i;
+
+ if (active == new)
+ return (0);
+
+ if (!new || !active)
+ return (1);
+
+ if (active->address.s_addr != new->address.s_addr ||
+ active->is_static != new->is_static ||
+ active->is_bootp != new->is_bootp)
+ return (1);
+
+ if (active->server_name != new->server_name) {
+ if (!active->server_name || !new->server_name)
+ return (1);
+ if (strcmp(active->server_name, new->server_name))
+ return (1);
+ }
+
+ if (active->filename != new->filename) {
+ if (!active->filename || !new->filename)
+ return (1);
+ if (strcmp(active->filename, new->filename))
+ return (1);
+ }
+
+ for (i = 0; i < 256; i++) {
+ if (active->options[i].len != new->options[i].len)
+ return (1);
+ if (memcmp(active->options[i].data, new->options[i].data,
+ active->options[i].len))
+ return (1);
+ }
+
+ return (0);
+}