Subject: proposal: API for Host AP Daemons
To: None <>
From: David Young <>
List: tech-net
Date: 09/15/2002 19:19:11
In this e-mail I motivate an API for Host AP daemons, and I propose an
API for discussion.

Right now, all Host AP functions are implemented in the NetBSD
kernel. Many of the functions belong in the kernel, however, it is
useful for a user-level Host AP Daemon to provide certain AP functions.
For example, a daemon can implement policies such as MAC filters
or 802.11i/802.1x authentication. Also, a daemon can implement an
Inter-Access Point Protocol for coordinating hand-off over an ethernet
or the Internet. (Just think: the first AP with a standards-compliant
IAPP could run NetBSD, provided 802.11f ever emerges from committee. =)

It is not sufficient for a Host AP Daemon to listen for 802.11 Mgmt
frames with BPF and to answer them, because it will duplicate answers
sent by the Host AP code in the kernel. Instead, the AP daemon must
intervene in the operation of the Host AP code. To provide the hooks
for a daemon to intervene, I propose a new pseudo-character device,
hostap. Hostap resembles bpf in that you use ioctl's to associate it
with an 802.11 interface and to find out the minimum buffer length. An AP
daemon receives buffers from hostap indicating 802.11 Mgmt requests. It
writes back 802.11 Mgmt responses and other, asynchronous commands (e.g.,
disassociate a station).

There are two types of message sent by the kernel to a Host AP Daemon,
requests and indications.  Requests indicate 802.11 Management requests
such as (Re)Associate or Authenticate, which the kernel will not answer
without the intervention of the Host AP Daemon. Indications tell, for
example, that a STA has disassociated or deauthenticated; no Host AP
daemon intervention is necessary after an indication.  Messages sent by
the kernel to the daemon are labeled by ascending sequence numbers.

There are two types of message sent by a Host AP Daemon to the kernel,
responses and commands. A daemon may send a command at any time. A daemon
may command, for example, that a station be disassociated. A response,
on the other hand, may only be sent in answer to a request sent by
the kernel.  Host AP Daemon interventions take the form of responses.

Responses must carry the sequence number of the request they answer. Once
a daemon sends a response with sequence number N, it loses its opportunity
to answer any prior request, i.e., requests with sequence numbers N-1,
N-2, .... When a daemon gets far enough behind sending responses that the
kernel buffer for pending requests is at capacity, no new request will
be buffered until a request is answered. During conditions of overflow,
the kernel answers 802.11 Mgmt frames with error status codes.

Many requests are sent with an Association ID (AID).  The kernel is
responsible for assigning AIDs. For (Re)Association requests, the
kernel assigns a tentative AID. When a daemon answers with a positive
(Re)Association response, the AID is assigned. A daemon may refer to
stations by their AIDs for the purposes of certain commands. The kernel
will name stations in indications using their AID. A Host AP Daemon will
typically keep a table mapping AID to STA information (MAC, data rates,
authentication tokens, ...).

/*** here are the ioctl's

  HIOCSETIF (struct ifreq)
    set interface
  HIOCGETIF (struct ifreq)
    get interface
  HIOCGBLEN (u_int)
    get maximum buffer length
    empty kernel message buffer
  HIOCGSTATS (struct hostap_stat)
    statistics: total messages read/written, total requests/responses

	struct hostap_stat {
		u_int hs_from_kernel;
		u_int hs_drop; /* mgmt messages dropped due to buffer overflows
		u_int hs_requests;
		u_int hs_to_kernel;
		u_int hs_responses;

/*** here are type codes for the commands, indications, requests,
 *** and responses.

/* commands to the kernel */
#define HAP_DEAUTH_CMD		1
#define HAP_TIMEOUT_CMD		2	/* set an inactivity timeout for a STA

/* indications from the kernel */
#define HAP_DEAUTH_IND		4
#define HAP_TIMEOUT_IND		5	/* no activity from a STA in its
					 * timeout interval

/* requests from kernel */
#define HAP_ASSOC_REQ		6	/* a STA asks to associate */
#define HAP_REASSOC_REQ		7	/* a STA asks to reassociate */
#define HAP_PROBE_REQ		8	/* a STA probes */
#define HAP_AUTH_REQ		9	/* a STA asks to authenticate */

/* responses to the kernel */
#define HAP_ASSOC_RESP		10
#define HAP_PROBE_RESP		12
#define HAP_AUTH_RESP		13

/*** here is the format for the frames sent to/from the kernel

struct ieee80211_hostap_msg {
	u_short			i_msglen; /* so you can skip messages */
	u_char			i_type;   /* one of the type codes above */
	u_long			i_seq;    /* sequence number */
	struct timeval		i_tstamp; /* when a kernel message was sent */

	u_int8_t		i_dstaddr[IEEE80211_ADDR_LEN];
	u_int8_t		i_srcaddr[IEEE80211_ADDR_LEN];
	u_int8_t		i_bssid[IEEE80211_ADDR_LEN];
	union {
		struct {
			u_int16_t	i_capinfo; /* capability info */
			u_int16_t	i_lintval; /* listen interval */
			u_int8_t	i_curap[IEEE80211_ADDR_LEN];
			u_int8_t	i_ssidlen;
			u_int8_t	i_ssid[IEEE80211_NWID_LEN];
			u_int8_t	i_nrates;
			u_int8_t	i_rates[IEEE80211_RATE_SIZE];
			u_int16_t	i_asid; /* tentative Association ID */
		} asreq;
		struct {
			u_int16_t	i_capinfo;
			u_int16_t	i_status;
			u_int8_t	i_nrates;
			u_int8_t	i_rates[IEEE80211_RATE_SIZE];
		} asresp;
		struct {
			u_int16_t	i_asid;
			struct timeval	i_timeout;
		} timeout;
		struct {
			u_int16_t	i_asid;
			u_int16_t	i_reason;
		} disas;
		struct {
			u_int16_t	i_asid;
			u_int16_t	i_reason;
		} deauth;
		struct {
			u_int16_t	i_asid;
			/* TBD */
		} authreq;
		struct {
			u_int16_t	i_asid;
			/* TBD */
		} authresp;
		struct {
			/* TBD */
		} probereq;
		struct {
			/* TBD */
		} proberesp;
	} i_un;

#define i_asreq		i_un.asreq
#define i_reasreq	i_un.asreq
#define i_asresp	i_un.asresp
#define i_reasresp	i_un.asresp
#define i_authreq	i_un.authreq
#define i_authresp	i_un.authresp
#define i_probereq	i_un.probereq
#define i_proberesp	i_un.proberesp
#define i_disas		i_un.disas
#define i_deauth	i_un.deauth
#define i_timeout	i_un.timeout

Outstanding issues

  The kernel<->daemon message format needs to be completed.

  There should be an ioctl or message type through which the kernel
  provides STA statistics (RSSI, packets RX'd/TX'd, etc.)

  Maybe events such as frames arriving from a disassociated STA should
  be indicated, for diagnostic purposes.

  There should be ioctl's or message types for control of the Wireless
  Distribution System (WDS), on hardware where that is applicable.
  Possibly that control belongs with the bridge framework.

David Young             OJC Technologies      Engineering from the Right Brain
                        Urbana, IL * (217) 278-3933