[pkg-wpa-devel] Fwd: PATCH RFC: wpa_supplicant influencing device operstate

Reinhard Tartler siretart at tauware.de
Fri Mar 10 20:40:34 UTC 2006


FYI: I found this email from the hostap mailing list very interesting. I
think this is great news and a step in the right direction to modern
networking configuration!

regards,
	Reinhard

From: Stefan Rompf <stefan at loplof.de>
Newsgroups: gmane.linux.drivers.hostap
Subject: PATCH RFC: wpa_supplicant influencing device operstate
Date: Sat, 4 Mar 2006 00:04:54 +0100

--Boundary-00=_XuMCExQpBMlTz0O
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hi,

some weeks ago, there has been a quite heated discussion on linux-netdev about 
extending functionality of netif_carrier_on()/off(). In the end, a patch 
written by me has been applied for 2.6.17. For an overview, see the 
documentation at http://www.flamewarmaster.de/software/operstates.txt . The 
patch itself (applies to 2.6.14+) can be found on this site too. Main point 
concerning this list is that it allows an userspace supplicant to signal the 
kernel when the interface is ready for user traffic after authentication, and 
afterwards, kernel notifies other programs via the existing IFF_RUNNING 
interface.

The quagga routing daemon, vrrpd and my new dhcp client 
(http://www.flamewarmaster.de/software/dhcpclient/) can act on these 
messages.

I have attached a patch against wpa_supplicant 0.5.1 to this mail that 
implements signalling functionality in the WEXT driver. Note that I haven't 
tested how this affects drivers that rely on WEXT functionality - this is a 
very first version.

With this extension, I can start wpa_supplicant and my DHCP client in 
parallel. Whenever the supplicant has completed association, and WPA 
authentication if needed, the DHCP client will automatically update the 
interface IP configuration. Together with a graphical wpa_cli (will try 
wpa_gui), this increases usability of wireless LANs a lot. In the long run, 
I'd like this feature to be added to wpa_supplicant.

Thoughts?

Stefan

--Boundary-00=_XuMCExQpBMlTz0O
Content-Type: text/x-diff;
  charset="us-ascii";
  name="wpa_supplicant.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="wpa_supplicant.diff"

diff -x '*.o' -x '*.d' -x '*~' -x wpa_cli -x wpa_passphrase -x wpa_supplicant -upr wpa_supplicant-0.5.1.orig/driver.h wpa_supplicant-0.5.1/driver.h
--- wpa_supplicant-0.5.1.orig/driver.h	2005-10-15 17:36:32.000000000 +0200
+++ wpa_supplicant-0.5.1/driver.h	2006-03-03 20:03:44.000000000 +0100
@@ -554,6 +554,13 @@ struct wpa_driver_ops {
 	 */
 	int (*send_eapol)(void *priv, const u8 *dest, u16 proto,
 			  const u8 *data, size_t data_len);
+
+	/**
+	 * set_operstate - Sets device operating state to DORMANT or UP
+	 * @priv: private driver interface data
+	 * @state: 0 = dormant, 1 = up
+	 */
+	void (*set_operstate)(void *priv, int state); 
 };
 
 #endif /* DRIVER_H */
diff -x '*.o' -x '*.d' -x '*~' -x wpa_cli -x wpa_passphrase -x wpa_supplicant -upr wpa_supplicant-0.5.1.orig/driver_wext.c wpa_supplicant-0.5.1/driver_wext.c
--- wpa_supplicant-0.5.1.orig/driver_wext.c	2006-01-30 05:11:48.000000000 +0100
+++ wpa_supplicant-0.5.1/driver_wext.c	2006-03-03 23:48:09.000000000 +0100
@@ -47,11 +47,14 @@ struct wpa_driver_wext_data {
 	struct wpa_driver_capa capa;
 	int has_capability;
 	int we_version_compiled;
+	int operstate;
 };
 
 
 static int wpa_driver_wext_flush_pmkid(void *priv);
 static int wpa_driver_wext_get_range(void *priv);
+static void wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,
+					   char linkmode, char operstate);
 
 
 static int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
@@ -559,6 +562,15 @@ static void wpa_driver_wext_event_rtm_ne
 		return;
 	}
 
+	/* some drivers send the association event before the operup event - 
+	   in this case, lifting operstate in wpa_driver_wext_set_operstate()
+	   fails. This will hit us when wpa_supplicant doesn't need to do
+	   802.1X authentication */
+	if (drv->ifindex == ifi->ifi_index && drv->operstate == 1 &&
+	    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
+	    !(ifi->ifi_flags & IFF_RUNNING))
+		wpa_driver_wext_send_oper_ifla(drv, -1, IF_OPER_UP);
+
 	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
 
 	attrlen = h->nlmsg_len - nlmsg_len;
@@ -794,6 +806,8 @@ void * wpa_driver_wext_init(void *ctx, c
 		wpa_driver_wext_alternative_ifindex(drv, ifname2);
 	}
 
+	wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);
+
 	return drv;
 }
 
@@ -816,6 +830,8 @@ void wpa_driver_wext_deinit(void *priv)
 	 */
 	wpa_driver_wext_set_bssid(drv, (u8 *) "\x00\x00\x00\x00\x00\x00");
 
+	wpa_driver_wext_send_oper_ifla(priv, 0, IF_OPER_UP);
+
 	eloop_unregister_read_sock(drv->event_sock);
 
 	if (wpa_driver_wext_get_ifflags(drv, &flags) == 0)
@@ -1759,6 +1775,57 @@ int wpa_driver_wext_alternative_ifindex(
 }
 
 
+static void wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,
+					   char linkmode, char operstate) {
+	struct {
+		struct nlmsghdr hdr;
+		struct ifinfomsg ifinfo;
+		char opts[16];
+	} req;
+	struct rtattr *rta;
+	static int nl_seq;
+
+	req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.hdr.nlmsg_type = RTM_SETLINK;
+	req.hdr.nlmsg_flags = NLM_F_REQUEST;
+	req.hdr.nlmsg_seq = ++nl_seq;
+	req.hdr.nlmsg_pid = 0;
+
+	req.ifinfo.ifi_family = AF_UNSPEC;
+        req.ifinfo.ifi_type = 0;
+        req.ifinfo.ifi_index = drv->ifindex;
+        req.ifinfo.ifi_flags = 0;
+        req.ifinfo.ifi_change = 0;
+
+	if (linkmode != -1) {
+		rta = (struct rtattr *)((char *)&req + NLMSG_ALIGN(req.hdr.nlmsg_len));
+		rta->rta_type = IFLA_LINKMODE;
+		rta->rta_len = RTA_LENGTH(sizeof(char));
+		*((char *)RTA_DATA(rta)) = linkmode;
+		req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + RTA_LENGTH(sizeof(char));
+	}
+	if (operstate != -1) {
+		rta = (struct rtattr *)((char *)&req + NLMSG_ALIGN(req.hdr.nlmsg_len));
+		rta->rta_type = IFLA_OPERSTATE;
+		rta->rta_len = RTA_LENGTH(sizeof(char));
+		*((char *)RTA_DATA(rta)) = operstate;
+		req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + RTA_LENGTH(sizeof(char));
+	}
+
+	printf("Operstate: linkmode=%d, operstate=%d\n", linkmode, operstate);
+
+	(void)send(drv->event_sock, &req, req.hdr.nlmsg_len, 0);
+}
+
+
+static void wpa_driver_wext_set_operstate(void *priv, int state) {
+	struct wpa_driver_wext_data *drv = priv;
+
+	drv->operstate = state;
+	wpa_driver_wext_send_oper_ifla(drv, -1, state?IF_OPER_UP:IF_OPER_DORMANT);
+}
+
+
 const struct wpa_driver_ops wpa_driver_wext_ops = {
 	.name = "wext",
 	.desc = "Linux wireless extensions (generic)",
@@ -1780,4 +1847,5 @@ const struct wpa_driver_ops wpa_driver_w
 	.remove_pmkid = wpa_driver_wext_remove_pmkid,
 	.flush_pmkid = wpa_driver_wext_flush_pmkid,
 	.get_capa = wpa_driver_wext_get_capa,
+	.set_operstate = wpa_driver_wext_set_operstate,
 };
diff -x '*.o' -x '*.d' -x '*~' -x wpa_cli -x wpa_passphrase -x wpa_supplicant -upr wpa_supplicant-0.5.1.orig/priv_netlink.h wpa_supplicant-0.5.1/priv_netlink.h
--- wpa_supplicant-0.5.1.orig/priv_netlink.h	2005-06-18 19:39:36.000000000 +0200
+++ wpa_supplicant-0.5.1/priv_netlink.h	2006-03-03 23:26:45.000000000 +0100
@@ -20,18 +20,36 @@
  * library, etc..
  */
 
+#ifndef IFF_LOWER_UP
+#define IFF_LOWER_UP   0x10000         /* driver signals L1 up         */
+#endif
+#ifndef IFF_DORMANT
+#define IFF_DORMANT    0x20000         /* driver signals dormant       */
+#endif
+
 #ifndef IFLA_IFNAME
 #define IFLA_IFNAME 3
 #endif
 #ifndef IFLA_WIRELESS
 #define IFLA_WIRELESS 11
 #endif
+#ifndef IFLA_OPERSTATE
+#define IFLA_OPERSTATE 16
+#endif
+#ifndef IFLA_LINKMODE
+#define IFLA_LINKMODE 17
+#define IF_OPER_DORMANT 5
+#define IF_OPER_UP 6
+#endif
+
+#define NLM_F_REQUEST 1
 
 #define NETLINK_ROUTE 0
 #define RTMGRP_LINK 1
 #define RTM_BASE 0x10
 #define RTM_NEWLINK (RTM_BASE + 0)
 #define RTM_DELLINK (RTM_BASE + 1)
+#define RTM_SETLINK (RTM_BASE + 3)
 
 #define NLMSG_ALIGNTO 4
 #define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1))
@@ -46,6 +64,9 @@
 #define RTA_NEXT(rta,attrlen) \
 ((attrlen) -= RTA_ALIGN((rta)->rta_len), \
 (struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len)))
+#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
+#define RTA_DATA(rta)   ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
+
 
 
 struct sockaddr_nl
diff -x '*.o' -x '*.d' -x '*~' -x wpa_cli -x wpa_passphrase -x wpa_supplicant -upr wpa_supplicant-0.5.1.orig/wpa_supplicant.c wpa_supplicant-0.5.1/wpa_supplicant.c
--- wpa_supplicant-0.5.1.orig/wpa_supplicant.c	2006-01-30 05:24:58.000000000 +0100
+++ wpa_supplicant-0.5.1/wpa_supplicant.c	2006-03-03 20:20:15.000000000 +0100
@@ -706,9 +706,11 @@ void wpa_supplicant_set_state(struct wpa
 			MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ?
 			"(reauth)" : "(auth)");
 		wpa_s->reassociated_connection = 1;
+		wpa_drv_set_operstate(wpa_s, 1);
 	} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
 		   state == WPA_ASSOCIATED) {
 		wpa_s->new_connection = 1;
+		wpa_drv_set_operstate(wpa_s, 0);
 	}
 	wpa_s->wpa_state = state;
 }
diff -x '*.o' -x '*.d' -x '*~' -x wpa_cli -x wpa_passphrase -x wpa_supplicant -upr wpa_supplicant-0.5.1.orig/wpa_supplicant_i.h wpa_supplicant-0.5.1/wpa_supplicant_i.h
--- wpa_supplicant-0.5.1.orig/wpa_supplicant_i.h	2005-11-28 05:44:50.000000000 +0100
+++ wpa_supplicant-0.5.1/wpa_supplicant_i.h	2006-03-03 20:05:17.000000000 +0100
@@ -484,4 +484,10 @@ static inline int wpa_drv_send_eapol(str
 	return -1;
 }
 
+static inline void wpa_drv_set_operstate(struct wpa_supplicant *wpa_s,
+					 int state)
+{
+	if (wpa_s->driver->set_operstate)
+		wpa_s->driver->set_operstate(wpa_s->drv_priv, state);
+}
 #endif /* WPA_SUPPLICANT_I_H */

--Boundary-00=_XuMCExQpBMlTz0O
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
HostAP mailing list
HostAP at shmoo.com
http://lists.shmoo.com/mailman/listinfo/hostap

--Boundary-00=_XuMCExQpBMlTz0O--




More information about the Pkg-wpa-devel mailing list