summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authormbr <mbr@FreeBSD.org>2003-07-28 08:30:11 +0000
committermbr <mbr@FreeBSD.org>2003-07-28 08:30:11 +0000
commit6416064bd673071db7aee16cb9b737f8ca527e5b (patch)
tree1c6e259ba89a48fad62b7203a5d3cac6e6ac42fe /contrib
parent40b6665d85a1da035de6a350ced06586632d9a59 (diff)
downloadFreeBSD-src-6416064bd673071db7aee16cb9b737f8ca527e5b.zip
FreeBSD-src-6416064bd673071db7aee16cb9b737f8ca527e5b.tar.gz
Enable dhclient to poll the interface state and send only
requests if the interface has an active link. This is a great benefit if you often change networks with your laptop and you do not like to kill/restart dhclient all the time. Changes are automatically detected and the link is refreshed. The change allows us to start dhclient in background mode Enable dhclient to poll the interface state and send only requests if the interface has an active link. This is a great benefit if you often change networks with your laptop and you do not like to kill/restart dhclient all the time. Changes are automatically detected and the link is refreshed. The change allows us to start dhclient in background mode while the network cable is not plugged in. To control the polling interval, the option -i has been introduced. It takes seconds as parameter, the minimum is one second, the default is five seconds. Polling is done in seconds, not microseconds, because dhclient does internally work with timeouts in seconds. This change will be part of the next major ISC-dhcpd release. Tested by: bms, imp, and many many others. Reviewed by: murray, eivind, dhclient folks
Diffstat (limited to 'contrib')
-rw-r--r--contrib/isc-dhcp/FREEBSD-upgrade10
-rw-r--r--contrib/isc-dhcp/client/dhclient.810
-rw-r--r--contrib/isc-dhcp/client/dhclient.c197
-rw-r--r--contrib/isc-dhcp/common/dispatch.c20
-rw-r--r--contrib/isc-dhcp/includes/dhcpd.h9
5 files changed, 240 insertions, 6 deletions
diff --git a/contrib/isc-dhcp/FREEBSD-upgrade b/contrib/isc-dhcp/FREEBSD-upgrade
index 9172e5a..b36e85a 100644
--- a/contrib/isc-dhcp/FREEBSD-upgrade
+++ b/contrib/isc-dhcp/FREEBSD-upgrade
@@ -42,20 +42,26 @@ Local Changes:
client/clparse.c
r1.6 - prefer strlcpy to strcpy.
client/dhclient.8
+ r1.14 - interface polling
r1.8 - correct a man reference and a typo.
r1.6 - document -D option.
- remove dhcpd from SEE ALSO section.
client/dhclient.c
+ r1.26 - interface polling
r1.25 - correct release lease option
r1.19 - connect std{in,out,err}.
r1.13 - prefer strlcpy to strcpy.
r1.6 - quiet by default.
- document -D option.
client/dhclient.conf.5
- - Remove dhcpd from SEE ALSO section.
+ - Remove dhcpd from SEE ALSO section.
common/dhcp-options.5
r1.2 - note that hostname is only set if not already set.
- - Remove dhcpd from SEE ALSO section.
+ - Remove dhcpd from SEE ALSO section.
+ common/dispatch.c
+ r1.2 - polling mode
+ includes/dhcpd.h
+ r1.2 - polling mode
(see CVS logs for complete details)
murray@FreeBSD.org
diff --git a/contrib/isc-dhcp/client/dhclient.8 b/contrib/isc-dhcp/client/dhclient.8
index 0a99042..ee6e52d 100644
--- a/contrib/isc-dhcp/client/dhclient.8
+++ b/contrib/isc-dhcp/client/dhclient.8
@@ -74,6 +74,10 @@ server
relay
]
[
+.B -i
+interval
+]
+[
.B -n
]
[
@@ -190,6 +194,12 @@ sends can be set using the
flag, followed by the IP address to send. This is only useful for testing,
and should not be expected to work in any consistent or useful way.
.PP
+On FreeBSD, dhclient can be enabled to automatically handle the
+link status of the network card. Normally polling is done every
+five seconds. The polling interval can be set using the
+.B -i
+flag, followed by the numbers of seconds. Minimum is one second.
+.PP
The DHCP client will normally run in the foreground until it has
configured an interface, and then will revert to running in the
background. To run force dhclient to always run as a foreground
diff --git a/contrib/isc-dhcp/client/dhclient.c b/contrib/isc-dhcp/client/dhclient.c
index 4382b05..9ec549c 100644
--- a/contrib/isc-dhcp/client/dhclient.c
+++ b/contrib/isc-dhcp/client/dhclient.c
@@ -48,6 +48,13 @@ static char ocopyright[] =
#include "dhcpd.h"
#include "version.h"
+#ifdef __FreeBSD__
+#include <sys/ioctl.h>
+#include <net/if_media.h>
+#include <net80211/ieee80211_ioctl.h>
+#include <net80211/ieee80211.h>
+#endif
+
TIME cur_time;
TIME default_lease_time = 43200; /* 12 hours... */
TIME max_lease_time = 86400; /* 24 hours... */
@@ -85,6 +92,10 @@ int client_env_count=0;
int onetry=0;
int quiet=1;
int nowait=0;
+int doinitcheck=0;
+#ifdef ENABLE_POLLING_MODE
+int polling_interval = 5;
+#endif
static void usage PROTO ((void));
@@ -202,6 +213,19 @@ int main (argc, argv, envp)
} else if (!strcmp (argv [i], "-n")) {
/* do not start up any interfaces */
interfaces_requested = 1;
+#ifdef ENABLE_POLLING_MODE
+ } else if (!strcmp (argv [i], "-i")) {
+ if (++i == argc)
+ usage ();
+ polling_interval = (int)strtol(argv [i],
+ (char **)NULL, 10);
+ if (polling_interval <= 0) {
+ log_info ("Incorrect polling interval %d",
+ polling_interval);
+ log_info ("Using a default of 5 seconds");
+ polling_interval = 5;
+ }
+#endif
} else if (!strcmp (argv [i], "-w")) {
/* do not exit if there are no broadcast interfaces. */
persist = 1;
@@ -233,6 +257,8 @@ int main (argc, argv, envp)
log_fatal ("%s: interface name too long (max %ld)",
argv [i], (long)strlen (argv [i]));
strlcpy (tmp -> name, argv [i], IFNAMSIZ);
+ set_ieee802(tmp);
+ tmp->linkstatus = interface_active(tmp);
if (interfaces) {
interface_reference (&tmp -> next,
interfaces, MDL);
@@ -386,6 +412,7 @@ int main (argc, argv, envp)
INTERFACE_AUTOMATIC)) !=
INTERFACE_REQUESTED))
continue;
+ set_ieee802(ip);
script_init (ip -> client,
"PREINIT", (struct string_list *)0);
if (ip -> client -> alias)
@@ -428,8 +455,13 @@ int main (argc, argv, envp)
client -> state = S_INIT;
/* Set up a timeout to start the initialization
process. */
+#ifdef ENABLE_POLLING_MODE
add_timeout (cur_time + random () % 5,
+ state_link, client, 0, 0);
+#else
+ add_timeout(cur_time + random () % 5,
state_reboot, client, 0, 0);
+#endif
}
}
}
@@ -1353,6 +1385,9 @@ void send_discover (cpp)
int interval;
int increase = 1;
+ if (interface_active(client -> interface) == 0)
+ return;
+
/* Figure out how long it's been since we started transmitting. */
interval = cur_time - client -> first_sending;
@@ -1458,6 +1493,9 @@ void state_panic (cpp)
struct client_lease *loop;
struct client_lease *lp;
+ if (interface_active(client -> interface) == 0)
+ return;
+
loop = lp = client -> active;
log_info ("No DHCPOFFERS received.");
@@ -2771,7 +2809,8 @@ void client_location_changed ()
break;
}
client -> state = S_INIT;
- state_reboot (client);
+ if (interface_active(ip))
+ state_reboot(client);
}
}
}
@@ -2932,8 +2971,10 @@ isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
client -> state = S_INIT;
/* Set up a timeout to start the initialization
process. */
- add_timeout (cur_time + random () % 5,
- state_reboot, client, 0, 0);
+ if (interface_active(ip)) {
+ add_timeout(cur_time + random () % 5,
+ state_reboot, client, 0, 0);
+ }
}
}
return ISC_R_SUCCESS;
@@ -2997,7 +3038,8 @@ isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
break;
case server_awaken:
- state_reboot (client);
+ if (interface_active(ip))
+ state_reboot(client);
break;
}
}
@@ -3134,3 +3176,150 @@ isc_result_t client_dns_update (struct client_state *client, int addp, int ttl)
data_string_forget (&ddns_dhcid, MDL);
return rcode;
}
+
+/* Check to see if there's a wire plugged in */
+int
+interface_active(struct interface_info *ip) {
+#ifdef __FreeBSD__
+ struct ifmediareq ifmr;
+ int *media_list, i;
+ char *ifname;
+ int sock;
+
+ ifname = ip -> name;
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ log_fatal("Can't create interface_active socket");
+
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ (void) strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+
+ if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+ /*
+ * Interface doesn't support SIOCGIFMEDIA, presume okay
+ */
+ close(sock);
+ return (1);
+ }
+ close(sock);
+
+ if (ifmr.ifm_count == 0) {
+ /*
+ * this is unexpected (to me), but we'll just assume
+ * that this means interface does not support SIOCGIFMEDIA
+ */
+ log_fatal("%s: no media types?", ifname);
+ return (1);
+ }
+
+ if (ifmr.ifm_status & IFM_AVALID) {
+ if (ip->ieee802) {
+ if ((IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) &&
+ (ifmr.ifm_status & IFM_ACTIVE))
+ return (1);
+ } else {
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ return (1);
+ }
+ }
+
+ return (0);
+#else /* ifdef __FreeBSD__ */
+
+ return (1);
+#endif /* Other OSs */
+}
+
+#ifdef __FreeBSD__
+set_ieee802 (struct interface_info *ip) {
+
+ struct ieee80211req ireq;
+ u_int8_t data[32];
+ int associated = 0;
+ int *media_list, i;
+ char *ifname;
+ int sock;
+
+ ifname = ip -> name;
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ log_fatal("Can't create interface_active socket");
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, ifname, sizeof(ireq.i_name));
+ ireq.i_data = &data;
+ ireq.i_type = IEEE80211_IOC_SSID;
+ ireq.i_val = -1;
+ /*
+ * If we can't get the SSID,
+ * this isn't an 802.11 device.
+ */
+ if (ioctl(sock, SIOCG80211, &ireq) < 0)
+ ip->ieee802 = 0;
+ else {
+#ifdef DEBUG
+ printf("Device %s has 802.11\n", ifname);
+#endif
+ ip->ieee802 = 1;
+ }
+ close(sock);
+}
+#endif /* __FreeBSD__ */
+
+#ifdef ENABLE_POLLING_MODE
+/* Check the state of the NICs if we have link */
+void state_link (cpp)
+ void *cpp;
+{
+ struct interface_info *ip;
+ struct client_state *client;
+
+#ifdef DEBUG
+ printf("Polling interface status\n");
+#endif
+ for (ip = interfaces; ip; ip = ip -> next) {
+ if (ip->linkstatus == 0 || doinitcheck == 0) {
+ if (interface_active(ip)) {
+#ifdef DEBUG
+ printf("%s: Found Link on interface\n", ip->name);
+#endif
+ for (client = ip -> client;
+ client; client = client -> next) {
+ add_timeout(cur_time + random () % 5,
+ state_reboot, client, 0, 0);
+ }
+ ip->linkstatus = 1;
+ } else {
+#ifdef DEBUG
+ printf("%s: No Link on interface\n", ip->name);
+#endif
+ for (client = ip -> client;
+ client; client = client -> next) {
+ cancel_timeout(state_init, client);
+ cancel_timeout(send_discover, client);
+ cancel_timeout(send_request, client);
+ /*
+ * XXX without this, dhclient does
+ * not poll on a interface if there
+ * is no cable plugged in at startup
+ * time
+ */
+ if (client -> state == S_INIT) {
+ add_timeout(cur_time + polling_interval,
+ state_link, client, 0, 0);
+ }
+ }
+ ip->linkstatus = 0;
+ }
+ } else {
+ if (interface_active(ip) == 0) {
+#ifdef DEBUG
+ printf("%s: Lost Link on interface\n", ip->name);
+#endif
+ ip->linkstatus = 0;
+ }
+ }
+ }
+ doinitcheck = 1;
+}
+#endif /* ifdef ENABLE_POLLING_MODE */
diff --git a/contrib/isc-dhcp/common/dispatch.c b/contrib/isc-dhcp/common/dispatch.c
index bd87675..59160ff 100644
--- a/contrib/isc-dhcp/common/dispatch.c
+++ b/contrib/isc-dhcp/common/dispatch.c
@@ -44,6 +44,7 @@
#ifndef lint
static char copyright[] =
"$Id: dispatch.c,v 1.63.2.3 2002/11/17 02:26:57 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
+"$FreeBSD$\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -51,6 +52,10 @@ static char copyright[] =
struct timeout *timeouts;
static struct timeout *free_timeouts;
+#ifdef ENABLE_POLLING_MODE
+extern int polling_interval;
+#endif
+
void set_time (u_int32_t t)
{
/* Do any outstanding timeouts. */
@@ -95,11 +100,26 @@ struct timeval *process_outstanding_timeouts (struct timeval *tvp)
void dispatch ()
{
struct timeval tv, *tvp;
+#ifdef ENABLE_POLLING_MODE
+ struct timeval *tvp_new;
+#endif
isc_result_t status;
+ TIME cur_time;
+ tvp = NULL;
+#ifdef ENABLE_POLLING_MODE
+ tvp_new = NULL;
+#endif
/* Wait for a packet or a timeout... XXX */
do {
tvp = process_outstanding_timeouts (&tv);
+#ifdef ENABLE_POLLING_MODE
+ GET_TIME (&cur_time);
+ add_timeout(cur_time + polling_interval, state_link, 0, 0, 0);
+ tvp_new = process_outstanding_timeouts(&tv);
+ if (tvp != NULL && (tvp -> tv_sec > tvp_new -> tv_sec))
+ tvp = tvp_new;
+#endif /* ENABLE_POLLING_MODE */
status = omapi_one_dispatch (0, tvp);
} while (status == ISC_R_TIMEDOUT || status == ISC_R_SUCCESS);
log_fatal ("omapi_one_dispatch failed: %s -- exiting.",
diff --git a/contrib/isc-dhcp/includes/dhcpd.h b/contrib/isc-dhcp/includes/dhcpd.h
index 891678c..0c98e82 100644
--- a/contrib/isc-dhcp/includes/dhcpd.h
+++ b/contrib/isc-dhcp/includes/dhcpd.h
@@ -41,6 +41,10 @@
* ``http://www.nominum.com''.
*/
+#ifndef lint
+"$FreeBSD$\n";
+#endif /* not lint */
+
#ifndef __CYGWIN32__
#include <sys/types.h>
#include <netinet/in.h>
@@ -778,6 +782,8 @@ struct interface_info {
unsigned remote_id_len; /* Length of Remote ID. */
char name [IFNAMSIZ]; /* Its name... */
+ int linkstatus; /* Link status */
+ int ieee802; /* True if media is ieee802 */
int index; /* Its index. */
int rfdesc; /* Its read file descriptor. */
int wfdesc; /* Its write file descriptor, if
@@ -1853,6 +1859,9 @@ void send_release PROTO ((void *));
void send_decline PROTO ((void *));
void state_reboot PROTO ((void *));
+#ifdef ENABLE_POLLING_MODE
+void state_link PROTO (());
+#endif
void state_init PROTO ((void *));
void state_selecting PROTO ((void *));
void state_requesting PROTO ((void *));
OpenPOWER on IntegriCloud