P2PS: Extend add/del services logic to support ASP

In addition, add a new P2P_SERVICE_REP command that can be used to
replace existing ASP advertisements.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Krishna Vamsi 2014-12-09 19:32:50 +05:30 committed by Jouni Malinen
parent ea8e033e92
commit ae9d45f329
7 changed files with 378 additions and 17 deletions

View file

@ -4914,6 +4914,106 @@ static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd)
}
static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s,
u8 replace, char *cmd)
{
char *pos;
char *adv_str;
u32 auto_accept, adv_id, svc_state, config_methods;
char *svc_info = NULL;
pos = os_strchr(cmd, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
/* Auto-Accept value is mandatory, and must be one of the
* single values (0, 1, 2, 4) */
auto_accept = atoi(cmd);
switch (auto_accept) {
case P2PS_SETUP_NONE: /* No auto-accept */
case P2PS_SETUP_NEW:
case P2PS_SETUP_CLIENT:
case P2PS_SETUP_GROUP_OWNER:
break;
default:
return -1;
}
/* Advertisement ID is mandatory */
cmd = pos;
pos = os_strchr(cmd, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
/* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */
if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0)
return -1;
/* Only allow replacements if exist, and adds if not */
if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) {
if (!replace)
return -1;
} else {
if (replace)
return -1;
}
/* svc_state between 0 - 0xff is mandatory */
if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff)
return -1;
pos = os_strchr(pos, ' ');
if (pos == NULL)
return -1;
/* config_methods is mandatory */
pos++;
if (sscanf(pos, "%x", &config_methods) != 1)
return -1;
if (!(config_methods &
(WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS)))
return -1;
pos = os_strchr(pos, ' ');
if (pos == NULL)
return -1;
pos++;
adv_str = pos;
/* Advertisement string is mandatory */
if (!pos[0] || pos[0] == ' ')
return -1;
/* Terminate svc string */
pos = os_strchr(pos, ' ');
if (pos != NULL)
*pos++ = '\0';
/* Service and Response Information are optional */
if (pos && pos[0]) {
size_t len;
/* Note the bare ' included, which cannot exist legally
* in unescaped string. */
svc_info = os_strstr(pos, "svc_info='");
if (svc_info) {
svc_info += 9;
len = os_strlen(svc_info);
utf8_unescape(svc_info, len, svc_info, len);
}
}
return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str,
(u8) svc_state, (u16) config_methods,
svc_info);
}
static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos;
@ -4927,6 +5027,8 @@ static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd)
return p2p_ctrl_service_add_bonjour(wpa_s, pos);
if (os_strcmp(cmd, "upnp") == 0)
return p2p_ctrl_service_add_upnp(wpa_s, pos);
if (os_strcmp(cmd, "asp") == 0)
return p2p_ctrl_service_add_asp(wpa_s, 0, pos);
wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
return -1;
}
@ -4974,6 +5076,17 @@ static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd)
}
static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd)
{
u32 adv_id;
if (sscanf(cmd, "%x", &adv_id) != 1)
return -1;
return wpas_p2p_service_del_asp(wpa_s, adv_id);
}
static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos;
@ -4987,6 +5100,25 @@ static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd)
return p2p_ctrl_service_del_bonjour(wpa_s, pos);
if (os_strcmp(cmd, "upnp") == 0)
return p2p_ctrl_service_del_upnp(wpa_s, pos);
if (os_strcmp(cmd, "asp") == 0)
return p2p_ctrl_service_del_asp(wpa_s, pos);
wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
return -1;
}
static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos;
pos = os_strchr(cmd, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
if (os_strcmp(cmd, "asp") == 0)
return p2p_ctrl_service_add_asp(wpa_s, 1, pos);
wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd);
return -1;
}
@ -7735,6 +7867,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) {
if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) {
if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) {
if (p2p_ctrl_reject(wpa_s, buf + 11) < 0)
reply_len = -1;

View file

@ -2868,6 +2868,35 @@ void wpas_p2p_service_flush(struct wpa_supplicant *wpa_s)
}
int wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant *wpa_s, u32 adv_id)
{
if (adv_id == 0)
return 1;
if (p2p_service_p2ps_id(wpa_s->global->p2p, adv_id))
return 1;
return 0;
}
int wpas_p2p_service_del_asp(struct wpa_supplicant *wpa_s, u32 adv_id)
{
return p2p_service_del_asp(wpa_s->global->p2p, adv_id);
}
int wpas_p2p_service_add_asp(struct wpa_supplicant *wpa_s,
int auto_accept, u32 adv_id,
const char *adv_str, u8 svc_state,
u16 config_methods, const char *svc_info)
{
return p2p_service_add_asp(wpa_s->global->p2p, auto_accept, adv_id,
adv_str, svc_state, config_methods,
svc_info);
}
int wpas_p2p_service_add_bonjour(struct wpa_supplicant *wpa_s,
struct wpabuf *query, struct wpabuf *resp)
{

View file

@ -84,6 +84,11 @@ int wpas_p2p_service_add_upnp(struct wpa_supplicant *wpa_s, u8 version,
const char *service);
int wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version,
const char *service);
int wpas_p2p_service_add_asp(struct wpa_supplicant *wpa_s, int auto_accept,
u32 adv_id, const char *adv_str, u8 svc_state,
u16 config_methods, const char *svc_info);
int wpas_p2p_service_del_asp(struct wpa_supplicant *wpa_s, u32 adv_id);
int wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant *wpa_s, u32 adv_id);
int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,

View file

@ -1975,27 +1975,25 @@ static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char cmd[4096];
int res;
if (argc < 3) {
printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
return -1;
}
if (argc != 3 && argc != 4) {
printf("Invalid P2P_SERVICE_ADD command: needs three or four "
return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
}
static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
if (argc < 5 || argc > 6) {
printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
"arguments\n");
return -1;
}
if (argc == 4)
res = os_snprintf(cmd, sizeof(cmd),
"P2P_SERVICE_ADD %s %s %s %s",
argv[0], argv[1], argv[2], argv[3]);
else
res = os_snprintf(cmd, sizeof(cmd),
"P2P_SERVICE_ADD %s %s %s",
argv[0], argv[1], argv[2]);
if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
return wpa_ctrl_command(ctrl, cmd);
return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
}
@ -2918,8 +2916,12 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
"= remove all stored service entries" },
{ "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
cli_cmd_flag_none,
"<bonjour|upnp> <query|version> <response|service> = add a local "
"<bonjour|upnp|asp> <query|version> <response|service> = add a local "
"service" },
{ "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
cli_cmd_flag_none,
"asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
"local ASP service" },
{ "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
cli_cmd_flag_none,
"<bonjour|upnp> <query|version> [|service] = remove a local "