char *sock_name;
int fd;
+ void *ctx;
+
const struct wpa_driver_ops *driver;
void *drv_priv;
void *drv_global_priv;
struct sockaddr_un l2_addr;
};
+struct wpa_priv_global {
+ struct wpa_priv_interface *interfaces;
+};
+
static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
struct sockaddr_un *from)
if (iface->driver->init2) {
if (iface->driver->global_init) {
- iface->drv_global_priv = iface->driver->global_init();
+ iface->drv_global_priv =
+ iface->driver->global_init(iface->ctx);
if (!iface->drv_global_priv) {
wpa_printf(MSG_INFO,
"Failed to initialize driver global context");
}
+static void wpa_priv_cmd_authenticate(struct wpa_priv_interface *iface,
+ void *buf, size_t len)
+{
+ struct wpa_driver_auth_params params;
+ struct privsep_cmd_authenticate *auth;
+ int res, i;
+
+ if (iface->drv_priv == NULL || iface->driver->authenticate == NULL)
+ return;
+
+ if (len < sizeof(*auth)) {
+ wpa_printf(MSG_DEBUG, "Invalid authentication request");
+ return;
+ }
+
+ auth = buf;
+ if (sizeof(*auth) + auth->ie_len + auth->sae_data_len > len) {
+ wpa_printf(MSG_DEBUG, "Authentication request overflow");
+ return;
+ }
+
+ os_memset(¶ms, 0, sizeof(params));
+ params.freq = auth->freq;
+ params.bssid = auth->bssid;
+ params.ssid = auth->ssid;
+ if (auth->ssid_len > SSID_MAX_LEN)
+ return;
+ params.ssid_len = auth->ssid_len;
+ params.auth_alg = auth->auth_alg;
+ for (i = 0; i < 4; i++) {
+ if (auth->wep_key_len[i]) {
+ params.wep_key[i] = auth->wep_key[i];
+ params.wep_key_len[i] = auth->wep_key_len[i];
+ }
+ }
+ params.wep_tx_keyidx = auth->wep_tx_keyidx;
+ params.local_state_change = auth->local_state_change;
+ params.p2p = auth->p2p;
+ if (auth->ie_len) {
+ params.ie = (u8 *) (auth + 1);
+ params.ie_len = auth->ie_len;
+ }
+ if (auth->sae_data_len) {
+ params.sae_data = ((u8 *) (auth + 1)) + auth->ie_len;
+ params.sae_data_len = auth->sae_data_len;
+ }
+
+ res = iface->driver->authenticate(iface->drv_priv, ¶ms);
+ wpa_printf(MSG_DEBUG, "drv->authenticate: res=%d", res);
+}
+
+
static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
void *buf, size_t len)
{
pos[cmd_len] = '\0';
wpa_priv_cmd_set_country(iface, pos);
break;
+ case PRIVSEP_CMD_AUTHENTICATE:
+ wpa_priv_cmd_authenticate(iface, cmd_buf, cmd_len);
+ break;
}
}
static struct wpa_priv_interface *
-wpa_priv_interface_init(const char *dir, const char *params)
+wpa_priv_interface_init(void *ctx, const char *dir, const char *params)
{
struct wpa_priv_interface *iface;
char *pos;
if (iface == NULL)
return NULL;
iface->fd = -1;
+ iface->ctx = ctx;
len = pos - params;
iface->driver_name = dup_binstr(params, len);
}
+static void wpa_priv_send_auth(struct wpa_priv_interface *iface,
+ union wpa_event_data *data)
+{
+ size_t buflen = sizeof(struct privsep_event_auth) + data->auth.ies_len;
+ struct privsep_event_auth *auth;
+ u8 *buf, *pos;
+
+ buf = os_malloc(buflen);
+ if (buf == NULL)
+ return;
+
+ auth = (struct privsep_event_auth *) buf;
+ pos = (u8 *) (auth + 1);
+
+ os_memcpy(auth->peer, data->auth.peer, ETH_ALEN);
+ os_memcpy(auth->bssid, data->auth.bssid, ETH_ALEN);
+ auth->auth_type = data->auth.auth_type;
+ auth->auth_transaction = data->auth.auth_transaction;
+ auth->status_code = data->auth.status_code;
+ if (data->auth.ies) {
+ os_memcpy(pos, data->auth.ies, data->auth.ies_len);
+ auth->ies_len = data->auth.ies_len;
+ }
+
+ wpa_priv_send_event(iface, PRIVSEP_EVENT_AUTH, buf, buflen);
+
+ os_free(buf);
+}
+
+
static void wpa_priv_send_assoc(struct wpa_priv_interface *iface, int event,
union wpa_event_data *data)
{
case EVENT_FT_RESPONSE:
wpa_priv_send_ft_response(iface, data);
break;
+ case EVENT_AUTH:
+ wpa_priv_send_auth(iface, data);
+ break;
default:
wpa_printf(MSG_DEBUG, "Unsupported driver event %d (%s) - TODO",
event, event_to_string(event));
}
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data)
+{
+ struct wpa_priv_global *global = ctx;
+ struct wpa_priv_interface *iface;
+
+ if (event != EVENT_INTERFACE_STATUS)
+ return;
+
+ for (iface = global->interfaces; iface; iface = iface->next) {
+ if (os_strcmp(iface->ifname, data->interface_status.ifname) ==
+ 0)
+ break;
+ }
+ if (iface && iface->driver->get_ifindex) {
+ unsigned int ifindex;
+
+ ifindex = iface->driver->get_ifindex(iface->drv_priv);
+ if (ifindex != data->interface_status.ifindex) {
+ wpa_printf(MSG_DEBUG,
+ "%s: interface status ifindex %d mismatch (%d)",
+ iface->ifname, ifindex,
+ data->interface_status.ifindex);
+ return;
+ }
+ }
+ if (iface)
+ wpa_supplicant_event(iface, event, data);
+}
+
+
void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len)
{
static void usage(void)
{
printf("wpa_priv v" VERSION_STR "\n"
- "Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> and "
+ "Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi> and "
"contributors\n"
"\n"
"usage:\n"
char *pid_file = NULL;
int daemonize = 0;
char *ctrl_dir = "/var/run/wpa_priv";
- struct wpa_priv_interface *interfaces = NULL, *iface;
+ struct wpa_priv_global global;
+ struct wpa_priv_interface *iface;
if (os_program_init())
return -1;
wpa_priv_fd_workaround();
+ os_memset(&global, 0, sizeof(global));
+ global.interfaces = NULL;
+
for (;;) {
c = getopt(argc, argv, "Bc:dP:");
if (c < 0)
for (i = optind; i < argc; i++) {
wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]);
- iface = wpa_priv_interface_init(ctrl_dir, argv[i]);
+ iface = wpa_priv_interface_init(&global, ctrl_dir, argv[i]);
if (iface == NULL)
goto out;
- iface->next = interfaces;
- interfaces = iface;
+ iface->next = global.interfaces;
+ global.interfaces = iface;
}
- if (daemonize && os_daemonize(pid_file))
+ if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
goto out;
eloop_register_signal_terminate(wpa_priv_terminate, NULL);
ret = 0;
out:
- iface = interfaces;
+ iface = global.interfaces;
while (iface) {
struct wpa_priv_interface *prev = iface;
iface = iface->next;