TDLS: Declare tdls_testing as extern in a header file
[mech_eap.git] / wpa_supplicant / wpa_priv.c
index a7aa430..511df4f 100644 (file)
@@ -29,6 +29,8 @@ struct wpa_priv_interface {
        char *sock_name;
        int fd;
 
+       void *ctx;
+
        const struct wpa_driver_ops *driver;
        void *drv_priv;
        void *drv_global_priv;
@@ -40,6 +42,10 @@ struct wpa_priv_interface {
        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)
@@ -65,7 +71,8 @@ static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
 
        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");
@@ -195,6 +202,58 @@ static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface,
 }
 
 
+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(&params, 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, &params);
+       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)
 {
@@ -330,6 +389,10 @@ static void wpa_priv_cmd_get_capa(struct wpa_priv_interface *iface,
            iface->driver->get_capa(iface->drv_priv, &capa) < 0)
                goto fail;
 
+       /* For now, no support for passing extended_capa pointers */
+       capa.extended_capa = NULL;
+       capa.extended_capa_mask = NULL;
+       capa.extended_capa_len = 0;
        sendto(iface->fd, &capa, sizeof(capa), 0, (struct sockaddr *) from,
               sizeof(*from));
        return;
@@ -553,6 +616,9 @@ static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
                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;
        }
 }
 
@@ -579,7 +645,7 @@ static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
 
 
 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;
@@ -595,6 +661,7 @@ wpa_priv_interface_init(const char *dir, const char *params)
        if (iface == NULL)
                return NULL;
        iface->fd = -1;
+       iface->ctx = ctx;
 
        len = pos - params;
        iface->driver_name = dup_binstr(params, len);
@@ -722,6 +789,36 @@ static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event,
 }
 
 
+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)
 {
@@ -875,6 +972,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                                    &data->michael_mic_failure.unicast,
                                    sizeof(int));
                break;
+       case EVENT_SCAN_STARTED:
+               wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_STARTED, NULL,
+                                   0);
+               break;
        case EVENT_SCAN_RESULTS:
                wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_RESULTS, NULL,
                                    0);
@@ -898,14 +999,48 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
        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 - TODO",
-                          event);
+               wpa_printf(MSG_DEBUG, "Unsupported driver event %d (%s) - TODO",
+                          event, event_to_string(event));
                break;
        }
 }
 
 
+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)
 {
@@ -964,7 +1099,7 @@ static void wpa_priv_fd_workaround(void)
 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"
@@ -981,13 +1116,17 @@ int main(int argc, char *argv[])
        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)
@@ -1025,14 +1164,14 @@ int main(int argc, char *argv[])
 
        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);
@@ -1041,7 +1180,7 @@ int main(int argc, char *argv[])
        ret = 0;
 
 out:
-       iface = interfaces;
+       iface = global.interfaces;
        while (iface) {
                struct wpa_priv_interface *prev = iface;
                iface = iface->next;