P2PS: ASP provisioning commands to control interface
authorKrishna Vamsi <vamsin@qti.qualcomm.com>
Wed, 10 Dec 2014 09:34:32 +0000 (15:04 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 2 Feb 2015 23:35:07 +0000 (01:35 +0200)
This adds new wpa_supplicant control interface commands
P2P_ASP_PROVISION and P2P_ASP_PROVISION_RESP.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c

index 6eb7590..eb2f20e 100644 (file)
@@ -4549,6 +4549,153 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
 }
 
 
+static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd)
+{
+       struct p2ps_provision *p2ps_prov;
+       char *pos;
+       size_t info_len = 0;
+       char *info = NULL;
+       u8 role = P2PS_SETUP_NONE;
+       long long unsigned val;
+
+       pos = os_strstr(cmd, "info=");
+       if (pos) {
+               pos += 5;
+               info_len = os_strlen(pos);
+
+               if (info_len) {
+                       info = os_malloc(info_len + 1);
+                       if (info) {
+                               info_len = utf8_unescape(pos, info_len,
+                                                        info, info_len + 1);
+                       } else
+                               info_len = 0;
+               }
+       }
+
+       p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1);
+       if (p2ps_prov == NULL) {
+               os_free(info);
+               return NULL;
+       }
+
+       if (info) {
+               os_memcpy(p2ps_prov->info, info, info_len);
+               p2ps_prov->info[info_len] = '\0';
+               os_free(info);
+       }
+
+       pos = os_strstr(cmd, "status=");
+       if (pos)
+               p2ps_prov->status = atoi(pos + 7);
+       else
+               p2ps_prov->status = -1;
+
+       pos = os_strstr(cmd, "adv_id=");
+       if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL)
+               goto invalid_args;
+       p2ps_prov->adv_id = val;
+
+       pos = os_strstr(cmd, "method=");
+       if (pos)
+               p2ps_prov->method = strtol(pos + 7, NULL, 16);
+       else
+               p2ps_prov->method = 0;
+
+       pos = os_strstr(cmd, "session=");
+       if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL)
+               goto invalid_args;
+       p2ps_prov->session_id = val;
+
+       pos = os_strstr(cmd, "adv_mac=");
+       if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac))
+               goto invalid_args;
+
+       pos = os_strstr(cmd, "session_mac=");
+       if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac))
+               goto invalid_args;
+
+       /* force conncap with tstCap (no sanity checks) */
+       pos = os_strstr(cmd, "tstCap=");
+       if (pos) {
+               role = strtol(pos + 7, NULL, 16);
+       } else {
+               pos = os_strstr(cmd, "role=");
+               if (pos) {
+                       role = strtol(pos + 5, NULL, 16);
+                       if (role != P2PS_SETUP_CLIENT &&
+                           role != P2PS_SETUP_GROUP_OWNER)
+                               role = P2PS_SETUP_NONE;
+               }
+       }
+       p2ps_prov->role = role;
+
+       return p2ps_prov;
+
+invalid_args:
+       os_free(p2ps_prov);
+       return NULL;
+}
+
+
+static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd)
+{
+       u8 addr[ETH_ALEN];
+       struct p2ps_provision *p2ps_prov;
+       char *pos;
+
+       /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */
+
+       wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
+
+       if (hwaddr_aton(cmd, addr))
+               return -1;
+
+       pos = cmd + 17;
+       if (*pos != ' ')
+               return -1;
+
+       p2ps_prov = p2p_parse_asp_provision_cmd(pos);
+       if (!p2ps_prov)
+               return -1;
+
+       if (p2ps_prov->status < 0) {
+               os_free(p2ps_prov);
+               return -1;
+       }
+
+       return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
+                                 p2ps_prov);
+}
+
+
+static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
+{
+       u8 addr[ETH_ALEN];
+       struct p2ps_provision *p2ps_prov;
+       char *pos;
+
+       /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap>
+        *        session=<ses_id> mac=<ses_mac> [info=<infodata>]
+        */
+
+       wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
+       if (hwaddr_aton(cmd, addr))
+               return -1;
+
+       pos = cmd + 17;
+       if (*pos != ' ')
+               return -1;
+
+       p2ps_prov = p2p_parse_asp_provision_cmd(pos);
+       if (!p2ps_prov)
+               return -1;
+
+       return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP,
+                                 p2ps_prov);
+}
+
+
 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
                            char *buf, size_t buflen)
 {
@@ -7856,6 +8003,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                        reply_len = -1;
        } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) {
                wpas_p2p_stop_find(wpa_s);
+       } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) {
+               if (p2p_ctrl_asp_provision(wpa_s, buf + 18))
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) {
+               if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23))
+                       reply_len = -1;
        } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) {
                reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply,
                                             reply_size);
index fdadffa..2f06c35 100644 (file)
@@ -1825,6 +1825,20 @@ static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
 }
 
 
+static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
+                                        char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
+}
+
+
+static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
+                                             char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
+}
+
+
 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
                                   char *argv[])
 {
@@ -2878,6 +2892,12 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
          "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
        { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
          "= stop P2P Devices search" },
+       { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
+         cli_cmd_flag_none,
+         "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
+       { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
+         cli_cmd_flag_none,
+         "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
        { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
          cli_cmd_flag_none,
          "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },