Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 08 Oct 2002 09:52:24 -0400
From:      Hal Burch <hburch@lumeta.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/43826: dhclient on 'no carrier' interfaces takes too long
Message-ID:  <20021008135225.1152A3D4@hburch.corp.lumeta.com>

next in thread | raw e-mail | index | archive | help

>Number:         43826
>Category:       bin
>Synopsis:       dhclient on 'no carrier' interfaces takes too long
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Oct 08 07:00:17 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Hal Burch
>Release:        FreeBSD 4.6.2-RELEASE i386
>Organization:
Lumeta Corporation
>Environment:
System: FreeBSD hburch-lap.lumeta.com 4.6.2-RELEASE FreeBSD 4.6.2-RELEASE #0: Tue Oct 8 08:37:59 EDT 2002 root@hburch-lap.lumeta.com:/usr/src/sys/compile/LOCAL i386
>Description:
Running dhclient <interface> on an interface which is not attached (my
laptop with built-in Ethernet when travelling, for example) attempts
to sends DHCP requests and waits for responses.

dhclient should (IMO) notice that the status is no carrier and
immediately stop.

Note that this has been the behavior since I started using FreeBSD
most recently (4.3) and does not appear related to the ISC 3.0.1
import.
>How-To-Repeat:
Kill dhclients running, unplug your Ethernet, run dhclient <interface>,
and wait.
>Fix:
For specified interfaces in dhclient, check to make sure SIOCGIFMEDIA
does not return a valid non-active media status (code yanked from
ifconfig).  This is not optimal, as this will not affect running
dhclient without an interface list, but the standard rc files do not
do this, so boot-up is greatly improved.

I made diffs from the head of RELENG_4_6_2_RELEASE, although I am using
an older version.  Although I did not see anything that implied there
might be a conflict with the changes, I have not tested this combination.

diff -u -r /root/orig/client/dhclient.c /usr/src/contrib/isc-dhcp/client/dhclient.c
--- /root/orig/client/dhclient.c	Tue Oct  8 09:37:24 2002
+++ /usr/src/contrib/isc-dhcp/client/dhclient.c	Tue Oct  8 09:37:38 2002
@@ -228,6 +228,10 @@
 			    log_fatal ("%s: interface name too long (max %ld)",
 				       argv [i], (long)strlen (argv [i]));
  		    strlcpy (tmp -> name, argv [i], IFNAMSIZ);
+		    if (!interface_active(argv[i])) {
+			log_fatal("Interface %s is not attached properly (media is not active)", argv[i]);
+		    }
+
 		    if (interfaces) {
 			    interface_reference (&tmp -> next,
 						 interfaces, MDL);
diff -u -r /root/orig/common/discover.c /usr/src/contrib/isc-dhcp/common/discover.c
--- /root/orig/common/discover.c	Tue Oct  8 09:37:22 2002
+++ /usr/src/contrib/isc-dhcp/common/discover.c	Tue Oct  8 09:37:38 2002
@@ -48,6 +48,7 @@
 
 #include "dhcpd.h"
 #include <sys/ioctl.h>
+#include <net/if_media.h>
 
 struct interface_info *interfaces, *dummy_interfaces, *fallback_interface;
 int interfaces_invalidated;
@@ -123,6 +124,40 @@
 	struct interface_info *ip = (struct interface_info *)ipo;
 	ip -> rfdesc = ip -> wfdesc = -1;
 	return ISC_R_SUCCESS;
+}
+
+/* Check to see if there's a wire plugged in */
+int
+interface_active(const char *ifname) {
+	struct ifmediareq ifmr;
+	int *media_list, i;
+	int sock;
+
+	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
+		 */
+		return 1;
+	}
+
+	if (ifmr.ifm_count == 0) {
+		/*
+		 * this is unexpected (to me), but we'll just assume
+		 * that this means interface does not support SIOCGIFMEDIA
+		 */
+		return 1;
+	}
+
+	if (ifmr.ifm_status & IFM_AVALID)
+		return (ifmr.ifm_status & IFM_ACTIVE);
+	else
+		return 1;
 }
 
 /* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
diff -u -r /root/orig/includes/dhcpd.h /usr/src/contrib/isc-dhcp/includes/dhcpd.h
--- /root/orig/includes/dhcpd.h	Tue Oct  8 09:37:22 2002
+++ /usr/src/contrib/isc-dhcp/includes/dhcpd.h	Tue Oct  8 09:37:38 2002
@@ -1750,6 +1750,7 @@
 extern int interface_count;
 extern int interface_max;
 isc_result_t interface_initialize (omapi_object_t *, const char *, int);
+int interface_active PROTO ((const char *));
 void discover_interfaces PROTO ((int));
 int setup_fallback (struct interface_info **, const char *, int);
 int if_readsocket PROTO ((omapi_object_t *));
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021008135225.1152A3D4>