1d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/*
2d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * FST module - Control Interface implementation
3d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Copyright (c) 2014, Qualcomm Atheros, Inc.
4d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt *
5d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * See README for more details.
7d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */
8d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
9d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "utils/includes.h"
10d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "utils/common.h"
11d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "common/defs.h"
12d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "list.h"
13d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "fst/fst.h"
14d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "fst/fst_internal.h"
15d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "fst_ctrl_defs.h"
16d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "fst_ctrl_iface.h"
17d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
18d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
19d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic struct fst_group * get_fst_group_by_id(const char *id)
20d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
21d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
22d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
23d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	foreach_fst_group(g) {
24d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		const char *group_id = fst_group_get_id(g);
25d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
26d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (os_strncmp(group_id, id, os_strlen(group_id)) == 0)
27d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return g;
28d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
29d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
30d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return NULL;
31d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
32d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
33d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
34d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* notifications */
35d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic Boolean format_session_state_extra(const union fst_event_extra *extra,
36d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					  char *buffer, size_t size)
37d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
38d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int len;
39d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char reject_str[32] = FST_CTRL_PVAL_NONE;
40d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *initiator = FST_CTRL_PVAL_NONE;
41d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const struct fst_event_extra_session_state *ss;
42d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
43d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ss = &extra->session_state;
44d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (ss->new_state != FST_SESSION_STATE_INITIAL)
45d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return TRUE;
46d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
47d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	switch (ss->extra.to_initial.reason) {
48d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case REASON_REJECT:
49d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (ss->extra.to_initial.reject_code != WLAN_STATUS_SUCCESS)
50d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			os_snprintf(reject_str, sizeof(reject_str), "%u",
51d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    ss->extra.to_initial.reject_code);
52d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		/* no break */
53d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case REASON_TEARDOWN:
54d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case REASON_SWITCH:
55d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		switch (ss->extra.to_initial.initiator) {
56d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case FST_INITIATOR_LOCAL:
57d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			initiator = FST_CS_PVAL_INITIATOR_LOCAL;
58d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
59d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case FST_INITIATOR_REMOTE:
60d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			initiator = FST_CS_PVAL_INITIATOR_REMOTE;
61d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
62d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		default:
63d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
64d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
65d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
66d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	default:
67d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
68d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
69d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
70d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	len = os_snprintf(buffer, size,
71d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			  FST_CES_PNAME_REASON "=%s "
72d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			  FST_CES_PNAME_REJECT_CODE "=%s "
73d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			  FST_CES_PNAME_INITIATOR "=%s",
74d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			  fst_reason_name(ss->extra.to_initial.reason),
75d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			  reject_str, initiator);
76d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
77d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return !os_snprintf_error(size, len);
78d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
79d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
80d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
81d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void fst_ctrl_iface_notify(struct fst_iface *f, u32 session_id,
82d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  enum fst_event_type event_type,
83d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  const union fst_event_extra *extra)
84d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
85d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
86d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char extra_str[128] = "";
87d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const struct fst_event_extra_session_state *ss;
88d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const struct fst_event_extra_iface_state *is;
89d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const struct fst_event_extra_peer_state *ps;
90d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
91d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/*
92d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * FST can use any of interface objects as it only sends messages
93d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * on global Control Interface, so we just pick the 1st one.
94d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 */
95d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
96d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!f) {
97d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		foreach_fst_group(g) {
98d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			f = fst_group_first_iface(g);
99d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (f)
100d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				break;
101d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
102d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!f)
103d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return;
104d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
105d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
106d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	WPA_ASSERT(f->iface_obj.ctx);
107d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
108d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	switch (event_type) {
109d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case EVENT_FST_IFACE_STATE_CHANGED:
110d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!extra)
111d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return;
112d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		is = &extra->iface_state;
113d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_msg_global_only(f->iface_obj.ctx, MSG_INFO,
114d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CTRL_EVENT_IFACE " %s "
115d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CEI_PNAME_IFNAME "=%s "
116d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CEI_PNAME_GROUP "=%s",
117d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    is->attached ? FST_CEI_PNAME_ATTACHED :
118d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CEI_PNAME_DETACHED,
119d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    is->ifname, is->group_id);
120d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
121d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case EVENT_PEER_STATE_CHANGED:
122d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!extra)
123d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return;
124d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ps = &extra->peer_state;
125d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_msg_global_only(fst_iface_get_wpa_obj_ctx(f), MSG_INFO,
126d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CTRL_EVENT_PEER " %s "
127d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CEP_PNAME_IFNAME "=%s "
128d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CEP_PNAME_ADDR "=" MACSTR,
129d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    ps->connected ? FST_CEP_PNAME_CONNECTED :
130d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CEP_PNAME_DISCONNECTED,
131d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    ps->ifname, MAC2STR(ps->addr));
132d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
133d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case EVENT_FST_SESSION_STATE_CHANGED:
134d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!extra)
135d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return;
136d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!format_session_state_extra(extra, extra_str,
137d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						sizeof(extra_str))) {
138d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			fst_printf(MSG_ERROR,
139d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   "CTRL: Cannot format STATE_CHANGE extra");
140d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			extra_str[0] = 0;
141d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
142d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ss = &extra->session_state;
143d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_msg_global_only(fst_iface_get_wpa_obj_ctx(f), MSG_INFO,
144d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CTRL_EVENT_SESSION " "
145d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CES_PNAME_SESSION_ID "=%u "
146d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CES_PNAME_EVT_TYPE "=%s "
147d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CES_PNAME_OLD_STATE "=%s "
148d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CES_PNAME_NEW_STATE "=%s %s",
149d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    session_id,
150d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    fst_session_event_type_name(event_type),
151d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    fst_session_state_name(ss->old_state),
152d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    fst_session_state_name(ss->new_state),
153d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    extra_str);
154d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
155d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case EVENT_FST_ESTABLISHED:
156d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	case EVENT_FST_SETUP:
157d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_msg_global_only(fst_iface_get_wpa_obj_ctx(f), MSG_INFO,
158d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CTRL_EVENT_SESSION " "
159d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CES_PNAME_SESSION_ID "=%u "
160d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    FST_CES_PNAME_EVT_TYPE "=%s",
161d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    session_id,
162d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    fst_session_event_type_name(event_type));
163d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		break;
164d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
165d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
166d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
167d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
168d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* command processors */
169d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
170d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst session_get */
171d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_get(const char *session_id, char *buf, size_t buflen)
172d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
173d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
174d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_iface *new_iface, *old_iface;
175d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const u8 *old_peer_addr, *new_peer_addr;
176d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 id;
177d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
178d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	id = strtoul(session_id, NULL, 0);
179d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
180d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_get_by_id(id);
181d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
182d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
183d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
184d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
185d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
186d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	old_peer_addr = fst_session_get_peer_addr(s, TRUE);
187d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	new_peer_addr = fst_session_get_peer_addr(s, FALSE);
188d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	new_iface = fst_session_get_iface(s, FALSE);
189d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	old_iface = fst_session_get_iface(s, TRUE);
190d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
191d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen,
192d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CSG_PNAME_OLD_PEER_ADDR "=" MACSTR "\n"
193d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CSG_PNAME_NEW_PEER_ADDR "=" MACSTR "\n"
194d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CSG_PNAME_NEW_IFNAME "=%s\n"
195d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CSG_PNAME_OLD_IFNAME "=%s\n"
196d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CSG_PNAME_LLT "=%u\n"
197d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CSG_PNAME_STATE "=%s\n",
198d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   MAC2STR(old_peer_addr),
199d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   MAC2STR(new_peer_addr),
200d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   new_iface ? fst_iface_get_name(new_iface) :
201d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CTRL_PVAL_NONE,
202d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   old_iface ? fst_iface_get_name(old_iface) :
203d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   FST_CTRL_PVAL_NONE,
204d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   fst_session_get_llt(s),
205d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   fst_session_state_name(fst_session_get_state(s)));
206d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
207d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
208d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
209d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst session_set */
210d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_set(const char *session_id, char *buf, size_t buflen)
211d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
212d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
213d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *p, *q;
214d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 id;
215d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret;
216d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
217d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	id = strtoul(session_id, &p, 0);
218d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
219d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_get_by_id(id);
220d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
221d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
222d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
223d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
224d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
225d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (*p != ' ' || !(q = os_strchr(p + 1, '=')))
226d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
227d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	p++;
228d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
229d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (os_strncasecmp(p, FST_CSS_PNAME_OLD_IFNAME, q - p) == 0) {
230d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_session_set_str_ifname(s, q + 1, TRUE);
231d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_IFNAME, q - p) == 0) {
232d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_session_set_str_ifname(s, q + 1, FALSE);
233d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (os_strncasecmp(p, FST_CSS_PNAME_OLD_PEER_ADDR, q - p) == 0) {
234d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_session_set_str_peer_addr(s, q + 1, TRUE);
235d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_PEER_ADDR, q - p) == 0) {
236d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_session_set_str_peer_addr(s, q + 1, FALSE);
237d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (os_strncasecmp(p, FST_CSS_PNAME_LLT, q - p) == 0) {
238d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_session_set_str_llt(s, q + 1);
239d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else {
240d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_ERROR, "CTRL: Unknown parameter: %s", p);
241d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
242d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
243d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
244d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "%s\n", ret ? "FAIL" : "OK");
245d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
246d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
247d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
248d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst session_add/remove */
249d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_add(const char *group_id, char *buf, size_t buflen)
250d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
251d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
252d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
253d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
254d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	g = get_fst_group_by_id(group_id);
255d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!g) {
256d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
257d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   group_id);
258d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
259d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
260d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
261d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_create(g);
262d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
263d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_ERROR,
264d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "CTRL: Cannot create session for group '%s'",
265d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   group_id);
266d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
267d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
268d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
269d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "%u\n", fst_session_get_id(s));
270d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
271d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
272d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
273d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_remove(const char *session_id, char *buf, size_t buflen)
274d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
275d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
276d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
277d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 id;
278d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
279d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	id = strtoul(session_id, NULL, 0);
280d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
281d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_get_by_id(id);
282d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
283d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
284d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
285d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
286d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
287d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	g = fst_session_get_group(s);
288d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_session_reset(s);
289d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_session_delete(s);
290d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_group_delete_if_empty(g);
291d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
292d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "OK\n");
293d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
294d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
295d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
296d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst session_initiate */
297d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_initiate(const char *session_id, char *buf, size_t buflen)
298d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
299d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
300d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 id;
301d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
302d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	id = strtoul(session_id, NULL, 0);
303d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
304d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_get_by_id(id);
305d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
306d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
307d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
308d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
309d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
310d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_session_initiate_setup(s)) {
311d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot initiate session %u", id);
312d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
313d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
314d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
315d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "OK\n");
316d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
317d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
318d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
319d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst session_respond */
320d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_respond(const char *session_id, char *buf, size_t buflen)
321d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
322d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
323d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *p;
324d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 id;
325d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 status_code;
326d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
327d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	id = strtoul(session_id, &p, 0);
328d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
329d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_get_by_id(id);
330d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
331d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
332d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
333d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
334d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
335d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (*p != ' ')
336d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
337d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	p++;
338d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
339d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!os_strcasecmp(p, FST_CS_PVAL_RESPONSE_ACCEPT)) {
340d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		status_code = WLAN_STATUS_SUCCESS;
341d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strcasecmp(p, FST_CS_PVAL_RESPONSE_REJECT)) {
342d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		status_code = WLAN_STATUS_PENDING_ADMITTING_FST_SESSION;
343d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else {
344d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING,
345d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "CTRL: session %u: unknown response status: %s",
346d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   id, p);
347d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
348d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
349d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
350d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_session_respond(s, status_code)) {
351d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot respond to session %u",
352d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   id);
353d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
354d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
355d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
356d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_printf(MSG_INFO, "CTRL: session %u responded", id);
357d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
358d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "OK\n");
359d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
360d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
361d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
362d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst session_transfer */
363d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_transfer(const char *session_id, char *buf, size_t buflen)
364d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
365d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
366d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 id;
367d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
368d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	id = strtoul(session_id, NULL, 0);
369d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
370d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_get_by_id(id);
371d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
372d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
373d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
374d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
375d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
376d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_session_initiate_switch(s)) {
377d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING,
378d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   "CTRL: Cannot initiate ST for session %u", id);
379d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
380d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
381d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
382d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "OK\n");
383d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
384d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
385d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
386d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst session_teardown */
387d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int session_teardown(const char *session_id, char *buf, size_t buflen)
388d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
389d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_session *s;
390d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 id;
391d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
392d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	id = strtoul(session_id, NULL, 0);
393d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
394d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	s = fst_session_get_by_id(id);
395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!s) {
396d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
397d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
398d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
399d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
400d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_session_tear_down_setup(s)) {
401d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot tear down session %u",
402d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   id);
403d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
404d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
405d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
406d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "OK\n");
407d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
408d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
409d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
410d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_FST_TEST
411d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst test_request */
412d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int test_request(const char *request, char *buf, size_t buflen)
413d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
414d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *p = request;
415d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret;
416d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
417d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!os_strncasecmp(p, FST_CTR_SEND_SETUP_REQUEST,
418d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			    os_strlen(FST_CTR_SEND_SETUP_REQUEST))) {
419d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_test_req_send_fst_request(
420d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p + os_strlen(FST_CTR_SEND_SETUP_REQUEST));
421d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strncasecmp(p, FST_CTR_SEND_SETUP_RESPONSE,
422d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   os_strlen(FST_CTR_SEND_SETUP_RESPONSE))) {
423d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_test_req_send_fst_response(
424d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p + os_strlen(FST_CTR_SEND_SETUP_RESPONSE));
425d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strncasecmp(p, FST_CTR_SEND_ACK_REQUEST,
426d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   os_strlen(FST_CTR_SEND_ACK_REQUEST))) {
427d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_test_req_send_ack_request(
428d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p + os_strlen(FST_CTR_SEND_ACK_REQUEST));
429d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strncasecmp(p, FST_CTR_SEND_ACK_RESPONSE,
430d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   os_strlen(FST_CTR_SEND_ACK_RESPONSE))) {
431d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_test_req_send_ack_response(
432d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p + os_strlen(FST_CTR_SEND_ACK_RESPONSE));
433d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strncasecmp(p, FST_CTR_SEND_TEAR_DOWN,
434d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   os_strlen(FST_CTR_SEND_TEAR_DOWN))) {
435d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = fst_test_req_send_tear_down(
436d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p + os_strlen(FST_CTR_SEND_TEAR_DOWN));
437d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strncasecmp(p, FST_CTR_GET_FSTS_ID,
438d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   os_strlen(FST_CTR_GET_FSTS_ID))) {
439d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		u32 fsts_id = fst_test_req_get_fsts_id(
440d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p + os_strlen(FST_CTR_GET_FSTS_ID));
441d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (fsts_id != FST_FSTS_ID_NOT_FOUND)
442d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return os_snprintf(buf, buflen, "%u\n", fsts_id);
443d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
444d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strncasecmp(p, FST_CTR_GET_LOCAL_MBIES,
445d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   os_strlen(FST_CTR_GET_LOCAL_MBIES))) {
446d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return fst_test_req_get_local_mbies(
447d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p + os_strlen(FST_CTR_GET_LOCAL_MBIES), buf, buflen);
448d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else if (!os_strncasecmp(p, FST_CTR_IS_SUPPORTED,
449d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   os_strlen(FST_CTR_IS_SUPPORTED))) {
450d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = 0;
451d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} else {
452d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_ERROR, "CTRL: Unknown parameter: %s", p);
453d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
454d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
455d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
456d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "%s\n", ret ? "FAIL" : "OK");
457d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
458d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_FST_TEST */
459d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
460d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
461d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst list_sessions */
462d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstruct list_sessions_cb_ctx {
463d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *buf;
464d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	size_t buflen;
465d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	size_t reply_len;
466d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt};
467d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
468d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
469d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void list_session_enum_cb(struct fst_group *g, struct fst_session *s,
470d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				 void *ctx)
471d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
472d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct list_sessions_cb_ctx *c = ctx;
473d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret;
474d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
475d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ret = os_snprintf(c->buf, c->buflen, " %u", fst_session_get_id(s));
476d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
477d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	c->buf += ret;
478d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	c->buflen -= ret;
479d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	c->reply_len += ret;
480d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
481d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
482d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
483d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int list_sessions(const char *group_id, char *buf, size_t buflen)
484d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
485d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct list_sessions_cb_ctx ctx;
486d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
487d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
488d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	g = get_fst_group_by_id(group_id);
489d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!g) {
490d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
491d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   group_id);
492d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
493d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
494d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
495d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ctx.buf = buf;
496d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ctx.buflen = buflen;
497d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ctx.reply_len = 0;
498d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
499d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_session_enum(g, list_session_enum_cb, &ctx);
500d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
501d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ctx.reply_len += os_snprintf(buf + ctx.reply_len, ctx.buflen, "\n");
502d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
503d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ctx.reply_len;
504d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
505d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
506d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
507d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst iface_peers */
508d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int iface_peers(const char *group_id, char *buf, size_t buflen)
509d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
510d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *ifname;
511d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
512d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_iface *f;
513d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_get_peer_ctx *ctx;
514d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const u8 *addr;
515d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned found = 0;
516d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret = 0;
517d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
518d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	g = get_fst_group_by_id(group_id);
519d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!g) {
520d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
521d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   group_id);
522d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
523d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
524d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
525d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ifname = os_strchr(group_id, ' ');
526d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!ifname)
527d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
528d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ifname++;
529d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
530d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	foreach_fst_group_iface(g, f) {
531d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		const char *in = fst_iface_get_name(f);
532d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
533d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (os_strncmp(ifname, in, os_strlen(in)) == 0) {
534d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			found = 1;
535d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
536d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
537d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
538d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
539d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!found)
540d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
541d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
542d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	addr = fst_iface_get_peer_first(f, &ctx, FALSE);
543d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (; addr != NULL; addr = fst_iface_get_peer_next(f, &ctx, FALSE)) {
544d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		int res;
545d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
546d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		res = os_snprintf(buf + ret, buflen - ret, MACSTR "\n",
547d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  MAC2STR(addr));
548d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (os_snprintf_error(buflen - ret, res))
549d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
550d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret += res;
551d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
552d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
553d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ret;
554d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
555d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
556d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
557d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int get_peer_mbies(const char *params, char *buf, size_t buflen)
558d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
559d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *endp;
560d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char ifname[FST_MAX_INTERFACE_SIZE];
561d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 peer_addr[ETH_ALEN];
562d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
563d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_iface *iface = NULL;
564d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const struct wpabuf *mbies;
565d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
566d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_read_next_text_param(params, ifname, sizeof(ifname), &endp) ||
567d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    !*ifname)
568d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto problem;
569d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
570d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (isspace(*endp))
571d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		endp++;
572d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_read_peer_addr(endp, peer_addr))
573d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto problem;
574d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
575d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	foreach_fst_group(g) {
576d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		iface = fst_group_get_iface_by_name(g, ifname);
577d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (iface)
578d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
579d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
580d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!iface)
581d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto problem;
582d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
583d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	mbies = fst_iface_get_peer_mb_ie(iface, peer_addr);
584d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!mbies)
585d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		goto problem;
586d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
587d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return wpa_snprintf_hex(buf, buflen, wpabuf_head(mbies),
588d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				wpabuf_len(mbies));
589d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
590d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtproblem:
591d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(buf, buflen, "FAIL\n");
592d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
593d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
594d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
595d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst list_ifaces */
596d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int list_ifaces(const char *group_id, char *buf, size_t buflen)
597d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
598d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
599d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_iface *f;
600d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret = 0;
601d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
602d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	g = get_fst_group_by_id(group_id);
603d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!g) {
604d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
605d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   group_id);
606d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return os_snprintf(buf, buflen, "FAIL\n");
607d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
608d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
609d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	foreach_fst_group_iface(g, f) {
610d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		int res;
611d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		const u8 *iface_addr = fst_iface_get_addr(f);
612d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
613d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		res = os_snprintf(buf + ret, buflen - ret,
614d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  "%s|" MACSTR "|%u|%u\n",
615d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  fst_iface_get_name(f),
616d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  MAC2STR(iface_addr),
617d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  fst_iface_get_priority(f),
618d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  fst_iface_get_llt(f));
619d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (os_snprintf_error(buflen - ret, res))
620d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
621d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret += res;
622d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
623d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
624d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ret;
625d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
626d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
627d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
628d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst list_groups */
629d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int list_groups(const char *cmd, char *buf, size_t buflen)
630d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
631d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
632d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret = 0;
633d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
634d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	foreach_fst_group(g) {
635d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		int res;
636d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
637d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		res = os_snprintf(buf + ret, buflen - ret, "%s\n",
638d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				  fst_group_get_id(g));
639d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (os_snprintf_error(buflen - ret, res))
640d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
641d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret += res;
642d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
643d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
644d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ret;
645d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
646d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
647d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
648d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic const char * band_freq(enum mb_band_id band)
649d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
650d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	static const char *band_names[] = {
6511d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt		[MB_BAND_ID_WIFI_2_4GHZ] = "2.4GHZ",
6521d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt		[MB_BAND_ID_WIFI_5GHZ] = "5GHZ",
6531d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt		[MB_BAND_ID_WIFI_60GHZ] = "60GHZ",
654d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	};
655d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
656d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return fst_get_str_name(band, band_names, ARRAY_SIZE(band_names));
657d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
658d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
659d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
660d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int print_band(unsigned num, struct fst_iface *iface, const u8 *addr,
661d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		      char *buf, size_t buflen)
662d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
663d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const struct wpabuf *wpabuf;
664d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	enum hostapd_hw_mode hw_mode;
665d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u8 channel;
666d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret = 0;
667d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
668d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_iface_get_channel_info(iface, &hw_mode, &channel);
669d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
670d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ret += os_snprintf(buf + ret, buflen - ret, "band%u_frequency=%s\n",
671d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   num, band_freq(fst_hw_mode_to_band(hw_mode)));
672d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ret += os_snprintf(buf + ret, buflen - ret, "band%u_iface=%s\n",
673d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   num, fst_iface_get_name(iface));
674d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpabuf = fst_iface_get_peer_mb_ie(iface, addr);
675d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (wpabuf) {
676d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret += os_snprintf(buf + ret, buflen - ret, "band%u_mb_ies=",
677d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   num);
678d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret += wpa_snprintf_hex(buf + ret, buflen - ret,
679d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					wpabuf_head(wpabuf),
680d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					wpabuf_len(wpabuf));
681d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret += os_snprintf(buf + ret, buflen - ret, "\n");
682d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
683d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ret += os_snprintf(buf + ret, buflen - ret, "band%u_fst_group_id=%s\n",
684d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   num, fst_iface_get_group_id(iface));
685d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ret += os_snprintf(buf + ret, buflen - ret, "band%u_fst_priority=%u\n",
686d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   num, fst_iface_get_priority(iface));
687d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ret += os_snprintf(buf + ret, buflen - ret, "band%u_fst_llt=%u\n",
688d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   num, fst_iface_get_llt(iface));
689d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
690d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ret;
691d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
692d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
693d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
694d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void fst_ctrl_iface_on_iface_state_changed(struct fst_iface *i,
695d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						  Boolean attached)
696d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
697d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	union fst_event_extra extra;
698d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
699d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memset(&extra, 0, sizeof(extra));
700d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	extra.iface_state.attached = attached;
701d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_strlcpy(extra.iface_state.ifname, fst_iface_get_name(i),
702d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   sizeof(extra.iface_state.ifname));
703d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_strlcpy(extra.iface_state.group_id, fst_iface_get_group_id(i),
704d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		   sizeof(extra.iface_state.group_id));
705d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
706d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_ctrl_iface_notify(i, FST_INVALID_SESSION_ID,
707d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			      EVENT_FST_IFACE_STATE_CHANGED, &extra);
708d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
709d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
710d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
711d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int fst_ctrl_iface_on_iface_added(struct fst_iface *i)
712d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
713d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_ctrl_iface_on_iface_state_changed(i, TRUE);
714d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
715d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
716d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
717d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
718d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void fst_ctrl_iface_on_iface_removed(struct fst_iface *i)
719d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
720d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_ctrl_iface_on_iface_state_changed(i, FALSE);
721d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
722d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
723d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
724d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void fst_ctrl_iface_on_event(enum fst_event_type event_type,
725d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    struct fst_iface *i, struct fst_session *s,
726d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    const union fst_event_extra *extra)
727d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
728d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	u32 session_id = s ? fst_session_get_id(s) : FST_INVALID_SESSION_ID;
729d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
730d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	fst_ctrl_iface_notify(i, session_id, event_type, extra);
731d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
732d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
733d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
734d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic const struct fst_ctrl ctrl_cli = {
735d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.on_iface_added = fst_ctrl_iface_on_iface_added,
736d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.on_iface_removed =  fst_ctrl_iface_on_iface_removed,
737d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.on_event = fst_ctrl_iface_on_event,
738d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt};
739d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
740d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtconst struct fst_ctrl *fst_ctrl_cli = &ctrl_cli;
741d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
742d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
743d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_ctrl_iface_mb_info(const u8 *addr, char *buf, size_t buflen)
744d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
745d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
746d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_iface *f;
747d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned num = 0;
748d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret = 0;
749d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
750d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	foreach_fst_group(g) {
751d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		foreach_fst_group_iface(g, f) {
752d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt			if (fst_iface_is_connected(f, addr, TRUE)) {
753d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				ret += print_band(num++, f, addr,
754d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						  buf + ret, buflen - ret);
755d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			}
756d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
757d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
758d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
759d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ret;
760d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
761d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
762d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
763d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt/* fst ctrl processor */
764d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size)
765d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
766d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	static const struct fst_command {
767d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		const char *name;
768d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		unsigned has_param;
769d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		int (*process)(const char *group_id, char *buf, size_t buflen);
770d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	} commands[] = {
771d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_LIST_GROUPS, 0, list_groups},
772d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_LIST_IFACES, 1, list_ifaces},
773d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_IFACE_PEERS, 1, iface_peers},
774d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_GET_PEER_MBIES, 1, get_peer_mbies},
775d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_LIST_SESSIONS, 1, list_sessions},
776d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_ADD, 1, session_add},
777d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_REMOVE, 1, session_remove},
778d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_GET, 1, session_get},
779d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_SET, 1, session_set},
780d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_INITIATE, 1, session_initiate},
781d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_RESPOND, 1, session_respond},
782d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_TRANSFER, 1, session_transfer},
783d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_SESSION_TEARDOWN, 1, session_teardown},
784d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#ifdef CONFIG_FST_TEST
785d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ FST_CMD_TEST_REQUEST, 1, test_request },
786d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#endif /* CONFIG_FST_TEST */
787d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		{ NULL, 0, NULL }
788d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	};
789d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const struct fst_command *c;
790d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *p;
791d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *temp;
792d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	Boolean non_spaces_found;
793d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
794d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	for (c = commands; c->name; c++) {
795d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (os_strncasecmp(cmd, c->name, os_strlen(c->name)) != 0)
796d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			continue;
797d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		p = cmd + os_strlen(c->name);
798d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (c->has_param) {
799d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (!isspace(p[0]))
800d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				return os_snprintf(reply, reply_size, "FAIL\n");
801d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			p++;
802d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			temp = p;
803d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			non_spaces_found = FALSE;
804d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			while (*temp) {
805d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				if (!isspace(*temp)) {
806d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					non_spaces_found = TRUE;
807d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt					break;
808d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				}
809d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				temp++;
810d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			}
811d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (!non_spaces_found)
812d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				return os_snprintf(reply, reply_size, "FAIL\n");
813d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
814d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return c->process(p, reply, reply_size);
815d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
816d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
817d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return os_snprintf(reply, reply_size, "UNKNOWN FST COMMAND\n");
818d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
819d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
820d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
821d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_read_next_int_param(const char *params, Boolean *valid, char **endp)
822d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
823d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int ret = -1;
824d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *curp;
825d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
826d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	*valid = FALSE;
827d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	*endp = (char *) params;
828d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	curp = params;
829d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (*curp) {
830d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		ret = (int) strtol(curp, endp, 0);
831d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!**endp || isspace(**endp))
832d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*valid = TRUE;
833d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
834d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
835d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return ret;
836d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
837d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
838d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
839d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_read_next_text_param(const char *params, char *buf, size_t buflen,
840d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			     char **endp)
841d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
842d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	size_t max_chars_to_copy;
843d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *cur_dest;
844d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
845d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	*endp = (char *) params;
846d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (isspace(**endp))
847d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		(*endp)++;
848d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!**endp || buflen <= 1)
849d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -EINVAL;
850d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
851d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	max_chars_to_copy = buflen - 1;
852d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/* We need 1 byte for the terminating zero */
853d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	cur_dest = buf;
854d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (**endp && !isspace(**endp) && max_chars_to_copy > 0) {
855d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		*cur_dest = **endp;
856d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		(*endp)++;
857d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		cur_dest++;
858d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		max_chars_to_copy--;
859d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
860d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	*cur_dest = 0;
861d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
862d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
863d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
864d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
865d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
866d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_read_peer_addr(const char *mac, u8 *peer_addr)
867d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
868d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (hwaddr_aton(mac, peer_addr)) {
869d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "Bad peer_mac %s: invalid addr string",
870d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   mac);
871d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
872d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
873d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
874d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (is_zero_ether_addr(peer_addr) ||
875d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    is_multicast_ether_addr(peer_addr)) {
876d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		fst_printf(MSG_WARNING, "Bad peer_mac %s: not a unicast addr",
877d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			   mac);
878d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
879d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
880d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
881d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
882d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
883d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
884d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
885d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_parse_attach_command(const char *cmd, char *ifname, size_t ifname_size,
886d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			     struct fst_iface_cfg *cfg)
887d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
888d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *pos;
889d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *endp;
890d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	Boolean is_valid;
891d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	int val;
892d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
893d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (fst_read_next_text_param(cmd, ifname, ifname_size, &endp) ||
894d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    fst_read_next_text_param(endp, cfg->group_id, sizeof(cfg->group_id),
895d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				     &endp))
896d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -EINVAL;
897d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
898d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	cfg->llt = FST_DEFAULT_LLT_CFG_VALUE;
899d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	cfg->priority = 0;
900d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	pos = os_strstr(endp, FST_ATTACH_CMD_PNAME_LLT);
901d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (pos) {
902d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		pos += os_strlen(FST_ATTACH_CMD_PNAME_LLT);
903d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (*pos == '=') {
904d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			val = fst_read_next_int_param(pos + 1, &is_valid,
905d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						      &endp);
906d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (is_valid)
907d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				cfg->llt = val;
908d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
909d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
910d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	pos = os_strstr(endp, FST_ATTACH_CMD_PNAME_PRIORITY);
911d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (pos) {
912d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		pos += os_strlen(FST_ATTACH_CMD_PNAME_PRIORITY);
913d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (*pos == '=') {
914d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			val = fst_read_next_int_param(pos + 1, &is_valid,
915d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt						      &endp);
916d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (is_valid)
917d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				cfg->priority = (u8) val;
918d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
919d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
920d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
921d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
922d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
923d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
924d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
925d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_parse_detach_command(const char *cmd, char *ifname, size_t ifname_size)
926d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
927d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	char *endp;
928d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
929d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return fst_read_next_text_param(cmd, ifname, ifname_size, &endp);
930d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
931d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
932d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
933d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtint fst_iface_detach(const char *ifname)
934d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
935d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct fst_group *g;
936d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
937d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	foreach_fst_group(g) {
938d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		struct fst_iface *f;
939d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
940d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		f = fst_group_get_iface_by_name(g, ifname);
941d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (f) {
942d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			fst_detach(f);
943d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return 0;
944d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
945d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
946d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
947d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return -EINVAL;
948d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
949