PATCH RFC: wpa_supplicant influencing device operstate
Pedro Ramalhais
ramalhais
Thu Mar 9 17:57:51 PST 2006
Stefan Rompf wrote:
> 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
>
>
> ------------------------------------------------------------------------
>
> 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 */
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> HostAP mailing list
> HostAP at shmoo.com
> http://lists.shmoo.com/mailman/listinfo/hostap
I think those are great news.
Maybe someone might want to look into adding it to the wired driver too.
I'm assuming that using wpa_supplicant for 802.1X via wired works.
Thanks for your effort!
--
Pedro Ramalhais
More information about the Hostap
mailing list