P2P: Add support for cross connection
If enabled, cross connection allows GO to forward IPv4 packets using masquerading NAT from the P2P clients in the group to an uplink WLAN connection. This is disabled by default and can be enabled with "wpa_cli p2p_set cross_connect 1" on the P2P device interface.
This commit is contained in:
parent
6c6915f3db
commit
72044390f3
15 changed files with 289 additions and 5 deletions
|
@ -101,6 +101,8 @@ extern "C" {
|
||||||
#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE "
|
#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE "
|
||||||
#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED "
|
#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED "
|
||||||
#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED "
|
#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED "
|
||||||
|
#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE "
|
||||||
|
#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE "
|
||||||
/* parameters: <peer address> <PIN> */
|
/* parameters: <peer address> <PIN> */
|
||||||
#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN "
|
#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN "
|
||||||
/* parameters: <peer address> */
|
/* parameters: <peer address> */
|
||||||
|
|
|
@ -1612,6 +1612,7 @@ static int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
|
||||||
u8 *lpos;
|
u8 *lpos;
|
||||||
size_t tmplen;
|
size_t tmplen;
|
||||||
int res;
|
int res;
|
||||||
|
u8 group_capab;
|
||||||
|
|
||||||
if (p2p_ie == NULL)
|
if (p2p_ie == NULL)
|
||||||
return 0; /* WLAN AP is not a P2P manager */
|
return 0; /* WLAN AP is not a P2P manager */
|
||||||
|
@ -1627,7 +1628,15 @@ static int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
lpos = p2p_buf_add_ie_hdr(tmp);
|
lpos = p2p_buf_add_ie_hdr(tmp);
|
||||||
p2p_buf_add_capability(tmp, p2p->dev_capab, 0);
|
group_capab = 0;
|
||||||
|
if (p2p->num_groups > 0) {
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
|
||||||
|
if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
|
||||||
|
(p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
|
||||||
|
p2p->cross_connect)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
|
}
|
||||||
|
p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab);
|
||||||
if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
|
if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
|
||||||
(p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
|
(p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
|
||||||
p2p_buf_add_p2p_interface(tmp, p2p);
|
p2p_buf_add_p2p_interface(tmp, p2p);
|
||||||
|
@ -2960,3 +2969,14 @@ void p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
|
||||||
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer "
|
||||||
"filter for " MACSTR, MAC2STR(p2p->peer_filter));
|
"filter for " MACSTR, MAC2STR(p2p->peer_filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p2p_set_cross_connect(struct p2p_data *p2p, int enabled)
|
||||||
|
{
|
||||||
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s",
|
||||||
|
enabled ? "enabled" : "disabled");
|
||||||
|
if (p2p->cross_connect == enabled)
|
||||||
|
return;
|
||||||
|
p2p->cross_connect = enabled;
|
||||||
|
/* TODO: may need to tear down any action group where we are GO(?) */
|
||||||
|
}
|
||||||
|
|
|
@ -1170,6 +1170,13 @@ int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params);
|
||||||
*/
|
*/
|
||||||
u8 p2p_get_group_capab(const struct wpabuf *p2p_ie);
|
u8 p2p_get_group_capab(const struct wpabuf *p2p_ie);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_get_cross_connect_disallowed - Does WLAN AP disallows cross connection
|
||||||
|
* @p2p_ie: P2P IE(s) contents
|
||||||
|
* Returns: 0 if cross connection is allow, 1 if not
|
||||||
|
*/
|
||||||
|
int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* p2p_get_go_dev_addr - Get P2P Device Address from P2P IE data
|
* p2p_get_go_dev_addr - Get P2P Device Address from P2P IE data
|
||||||
* @p2p_ie: P2P IE(s) contents
|
* @p2p_ie: P2P IE(s) contents
|
||||||
|
@ -1216,4 +1223,11 @@ int p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
|
||||||
|
|
||||||
void p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr);
|
void p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2p_set_cross_connect - Set cross connection capability
|
||||||
|
* @p2p: P2P module context from p2p_init()
|
||||||
|
* @enabled: Whether cross connection will be enabled
|
||||||
|
*/
|
||||||
|
void p2p_set_cross_connect(struct p2p_data *p2p, int enabled);
|
||||||
|
|
||||||
#endif /* P2P_H */
|
#endif /* P2P_H */
|
||||||
|
|
|
@ -158,6 +158,8 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
|
||||||
group_capab = 0;
|
group_capab = 0;
|
||||||
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
||||||
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
||||||
|
if (p2p->cross_connect)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
p2p_buf_add_capability(buf, p2p->dev_capab, group_capab);
|
p2p_buf_add_capability(buf, p2p->dev_capab, group_capab);
|
||||||
p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) |
|
p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) |
|
||||||
p2p->next_tie_breaker);
|
p2p->next_tie_breaker);
|
||||||
|
@ -242,8 +244,12 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
|
||||||
len = p2p_buf_add_ie_hdr(buf);
|
len = p2p_buf_add_ie_hdr(buf);
|
||||||
p2p_buf_add_status(buf, status);
|
p2p_buf_add_status(buf, status);
|
||||||
group_capab = 0;
|
group_capab = 0;
|
||||||
if (peer && (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP))
|
if (peer && peer->go_state == LOCAL_GO) {
|
||||||
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
||||||
|
if (p2p->cross_connect)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
|
}
|
||||||
p2p_buf_add_capability(buf, p2p->dev_capab, group_capab);
|
p2p_buf_add_capability(buf, p2p->dev_capab, group_capab);
|
||||||
p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker);
|
p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker);
|
||||||
p2p_buf_add_config_timeout(buf, 100, 20);
|
p2p_buf_add_config_timeout(buf, 100, 20);
|
||||||
|
@ -631,8 +637,12 @@ static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p,
|
||||||
len = p2p_buf_add_ie_hdr(buf);
|
len = p2p_buf_add_ie_hdr(buf);
|
||||||
p2p_buf_add_status(buf, status);
|
p2p_buf_add_status(buf, status);
|
||||||
group_capab = 0;
|
group_capab = 0;
|
||||||
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
if (peer->go_state == LOCAL_GO) {
|
||||||
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
|
||||||
|
if (p2p->cross_connect)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
|
}
|
||||||
p2p_buf_add_capability(buf, p2p->dev_capab, group_capab);
|
p2p_buf_add_capability(buf, p2p->dev_capab, group_capab);
|
||||||
if (go || resp_chan == NULL)
|
if (go || resp_chan == NULL)
|
||||||
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
|
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
|
||||||
|
|
|
@ -145,6 +145,8 @@ static void p2p_group_add_common_ies(struct p2p_group *group,
|
||||||
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
|
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
|
||||||
if (group->group_formation)
|
if (group->group_formation)
|
||||||
group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION;
|
group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION;
|
||||||
|
if (group->p2p->cross_connect)
|
||||||
|
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
|
||||||
p2p_buf_add_capability(ie, dev_capab, group_capab);
|
p2p_buf_add_capability(ie, dev_capab, group_capab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -365,6 +365,8 @@ struct p2p_data {
|
||||||
unsigned int ext_listen_interval_usec;
|
unsigned int ext_listen_interval_usec;
|
||||||
|
|
||||||
u8 peer_filter[ETH_ALEN];
|
u8 peer_filter[ETH_ALEN];
|
||||||
|
|
||||||
|
int cross_connect;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -650,6 +650,21 @@ int p2p_attr_text(struct wpabuf *data, char *buf, char *end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie)
|
||||||
|
{
|
||||||
|
struct p2p_message msg;
|
||||||
|
|
||||||
|
os_memset(&msg, 0, sizeof(msg));
|
||||||
|
if (p2p_parse_p2p_ie(p2p_ie, &msg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!msg.manageability)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return !(msg.capability[0] & P2P_MAN_CROSS_CONNECTIION_PERMITTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 p2p_get_group_capab(const struct wpabuf *p2p_ie)
|
u8 p2p_get_group_capab(const struct wpabuf *p2p_ie)
|
||||||
{
|
{
|
||||||
struct p2p_message msg;
|
struct p2p_message msg;
|
||||||
|
|
|
@ -2476,6 +2476,9 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (os_strcmp(cmd, "cross_connect") == 0)
|
||||||
|
return wpas_p2p_set_cross_connect(wpa_s, atoi(param));
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
|
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
|
||||||
cmd);
|
cmd);
|
||||||
|
|
||||||
|
|
|
@ -54,3 +54,24 @@ if [ "$CMD" = "P2P-GROUP-REMOVED" ]; then
|
||||||
ifconfig $GIFNAME 0.0.0.0
|
ifconfig $GIFNAME 0.0.0.0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$CMD" = "P2P-CROSS-CONNECT-ENABLE" ]; then
|
||||||
|
GIFNAME=$3
|
||||||
|
UPLINK=$4
|
||||||
|
# enable NAT/masquarade $GIFNAME -> $UPLINK
|
||||||
|
iptables -P FORWARD DROP
|
||||||
|
iptables -t nat -A POSTROUTING -o $UPLINK -j MASQUERADE
|
||||||
|
iptables -A FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
|
iptables -A FORWARD -i $GIFNAME -o $UPLINK -j ACCEPT
|
||||||
|
sysctl net.ipv4.ip_forward=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$CMD" = "P2P-CROSS-CONNECT-DISABLE" ]; then
|
||||||
|
GIFNAME=$3
|
||||||
|
UPLINK=$4
|
||||||
|
# disable NAT/masquarade $GIFNAME -> $UPLINK
|
||||||
|
sysctl net.ipv4.ip_forward=0
|
||||||
|
iptables -t nat -D POSTROUTING -o $UPLINK -j MASQUERADE
|
||||||
|
iptables -D FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
|
iptables -D FORWARD -i $GIFNAME -o $UPLINK -j ACCEPT
|
||||||
|
fi
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "dbus/dbus_new.h"
|
#include "dbus/dbus_new.h"
|
||||||
#include "driver_i.h"
|
#include "driver_i.h"
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
#include "p2p_supplicant.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
|
||||||
int wpas_notify_supplicant_initialized(struct wpa_global *global)
|
int wpas_notify_supplicant_initialized(struct wpa_global *global)
|
||||||
|
@ -81,6 +82,13 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
/* notify the new DBus API */
|
/* notify the new DBus API */
|
||||||
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE);
|
wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE);
|
||||||
|
|
||||||
|
#ifdef CONFIG_P2P
|
||||||
|
if (new_state == WPA_COMPLETED)
|
||||||
|
wpas_p2p_notif_connected(wpa_s);
|
||||||
|
else if (new_state < WPA_ASSOCIATED)
|
||||||
|
wpas_p2p_notif_disconnected(wpa_s);
|
||||||
|
#endif /* CONFIG_P2P */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
|
||||||
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
|
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
|
||||||
const u8 *dev_addr, enum p2p_wps_method wps_method);
|
const u8 *dev_addr, enum p2p_wps_method wps_method);
|
||||||
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
|
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
|
||||||
|
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
|
||||||
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
|
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
|
||||||
|
@ -201,6 +202,12 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s)
|
||||||
gtype = "client";
|
gtype = "client";
|
||||||
} else
|
} else
|
||||||
gtype = "GO";
|
gtype = "GO";
|
||||||
|
if (wpa_s->cross_connect_in_use) {
|
||||||
|
wpa_s->cross_connect_in_use = 0;
|
||||||
|
wpa_msg(wpa_s->parent, MSG_INFO,
|
||||||
|
P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
|
||||||
|
wpa_s->ifname, wpa_s->cross_connect_uplink);
|
||||||
|
}
|
||||||
wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_REMOVED "%s %s",
|
wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_REMOVED "%s %s",
|
||||||
wpa_s->ifname, gtype);
|
wpa_s->ifname, gtype);
|
||||||
if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
|
if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
|
||||||
|
@ -441,6 +448,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
|
||||||
"%s GO ssid=\"%s\" psk=%s go_dev_addr=" MACSTR "%s",
|
"%s GO ssid=\"%s\" psk=%s go_dev_addr=" MACSTR "%s",
|
||||||
wpa_s->ifname, ssid_txt, psk, MAC2STR(go_dev_addr),
|
wpa_s->ifname, ssid_txt, psk, MAC2STR(go_dev_addr),
|
||||||
persistent ? " [PERSISTENT]" : "");
|
persistent ? " [PERSISTENT]" : "");
|
||||||
|
wpas_p2p_cross_connect_setup(wpa_s);
|
||||||
} else {
|
} else {
|
||||||
wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
|
wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
|
||||||
"%s GO ssid=\"%s\" passphrase=\"%s\" go_dev_addr="
|
"%s GO ssid=\"%s\" passphrase=\"%s\" go_dev_addr="
|
||||||
|
@ -449,6 +457,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
|
||||||
ssid && ssid->passphrase ? ssid->passphrase : "",
|
ssid && ssid->passphrase ? ssid->passphrase : "",
|
||||||
MAC2STR(go_dev_addr),
|
MAC2STR(go_dev_addr),
|
||||||
persistent ? " [PERSISTENT]" : "");
|
persistent ? " [PERSISTENT]" : "");
|
||||||
|
wpas_p2p_cross_connect_setup(wpa_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (persistent)
|
if (persistent)
|
||||||
|
@ -717,6 +726,7 @@ static void p2p_go_configured(void *ctx, void *data)
|
||||||
wpas_p2p_store_persistent_group(
|
wpas_p2p_store_persistent_group(
|
||||||
wpa_s->parent, ssid,
|
wpa_s->parent, ssid,
|
||||||
wpa_s->parent->own_addr);
|
wpa_s->parent->own_addr);
|
||||||
|
wpas_p2p_cross_connect_setup(wpa_s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3307,3 +3317,135 @@ int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
|
||||||
return hostapd_p2p_set_noa(wpa_s->ap_iface->bss[0], count, start,
|
return hostapd_p2p_set_noa(wpa_s->ap_iface->bss[0], count, start,
|
||||||
duration);
|
duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled)
|
||||||
|
{
|
||||||
|
if (wpa_s->global->p2p_disabled)
|
||||||
|
return -1;
|
||||||
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpa_s->global->cross_connection = enabled;
|
||||||
|
p2p_set_cross_connect(wpa_s->global->p2p, enabled);
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
struct wpa_supplicant *iface;
|
||||||
|
|
||||||
|
for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
|
||||||
|
{
|
||||||
|
if (iface->cross_connect_enabled == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iface->cross_connect_enabled = 0;
|
||||||
|
iface->cross_connect_in_use = 0;
|
||||||
|
wpa_msg(iface->parent, MSG_INFO,
|
||||||
|
P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
|
||||||
|
iface->ifname, iface->cross_connect_uplink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_p2p_enable_cross_connect(struct wpa_supplicant *uplink)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *iface;
|
||||||
|
|
||||||
|
if (!uplink->global->cross_connection)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (iface = uplink->global->ifaces; iface; iface = iface->next) {
|
||||||
|
if (!iface->cross_connect_enabled)
|
||||||
|
continue;
|
||||||
|
if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
|
||||||
|
0)
|
||||||
|
continue;
|
||||||
|
if (iface->ap_iface == NULL)
|
||||||
|
continue;
|
||||||
|
if (iface->cross_connect_in_use)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iface->cross_connect_in_use = 1;
|
||||||
|
wpa_msg(iface->parent, MSG_INFO,
|
||||||
|
P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
|
||||||
|
iface->ifname, iface->cross_connect_uplink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_p2p_disable_cross_connect(struct wpa_supplicant *uplink)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *iface;
|
||||||
|
|
||||||
|
for (iface = uplink->global->ifaces; iface; iface = iface->next) {
|
||||||
|
if (!iface->cross_connect_enabled)
|
||||||
|
continue;
|
||||||
|
if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
|
||||||
|
0)
|
||||||
|
continue;
|
||||||
|
if (!iface->cross_connect_in_use)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wpa_msg(iface->parent, MSG_INFO,
|
||||||
|
P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
|
||||||
|
iface->ifname, iface->cross_connect_uplink);
|
||||||
|
iface->cross_connect_in_use = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (wpa_s->ap_iface || wpa_s->current_ssid == NULL ||
|
||||||
|
wpa_s->current_ssid->mode != WPAS_MODE_INFRA ||
|
||||||
|
wpa_s->cross_connect_disallowed)
|
||||||
|
wpas_p2p_disable_cross_connect(wpa_s);
|
||||||
|
else
|
||||||
|
wpas_p2p_enable_cross_connect(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
wpas_p2p_disable_cross_connect(wpa_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *iface;
|
||||||
|
|
||||||
|
if (!wpa_s->global->cross_connection)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
|
||||||
|
if (iface == wpa_s)
|
||||||
|
continue;
|
||||||
|
if (iface->drv_flags &
|
||||||
|
WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)
|
||||||
|
continue;
|
||||||
|
if (iface->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wpa_s->cross_connect_enabled = 1;
|
||||||
|
os_strlcpy(wpa_s->cross_connect_uplink, iface->ifname,
|
||||||
|
sizeof(wpa_s->cross_connect_uplink));
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Enable cross connection from "
|
||||||
|
"%s to %s whenever uplink is available",
|
||||||
|
wpa_s->ifname, wpa_s->cross_connect_uplink);
|
||||||
|
|
||||||
|
if (iface->ap_iface || iface->current_ssid == NULL ||
|
||||||
|
iface->current_ssid->mode != WPAS_MODE_INFRA ||
|
||||||
|
iface->cross_connect_disallowed ||
|
||||||
|
iface->wpa_state != WPA_COMPLETED)
|
||||||
|
break;
|
||||||
|
|
||||||
|
wpa_s->cross_connect_in_use = 1;
|
||||||
|
wpa_msg(wpa_s->parent, MSG_INFO,
|
||||||
|
P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
|
||||||
|
wpa_s->ifname, wpa_s->cross_connect_uplink);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -108,5 +108,8 @@ void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
void wpas_p2p_update_config(struct wpa_supplicant *wpa_s);
|
void wpas_p2p_update_config(struct wpa_supplicant *wpa_s);
|
||||||
int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
|
int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
|
||||||
int duration);
|
int duration);
|
||||||
|
int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled);
|
||||||
|
void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s);
|
||||||
|
void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
#endif /* P2P_SUPPLICANT_H */
|
#endif /* P2P_SUPPLICANT_H */
|
||||||
|
|
|
@ -2548,6 +2548,10 @@ static void wpa_cli_action_process(const char *msg)
|
||||||
wpa_cli_exec(action_file, ctrl_ifname, pos);
|
wpa_cli_exec(action_file, ctrl_ifname, pos);
|
||||||
} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
|
} else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
|
||||||
wpa_cli_exec(action_file, ctrl_ifname, pos);
|
wpa_cli_exec(action_file, ctrl_ifname, pos);
|
||||||
|
} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
|
||||||
|
wpa_cli_exec(action_file, ctrl_ifname, pos);
|
||||||
|
} else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
|
||||||
|
wpa_cli_exec(action_file, ctrl_ifname, pos);
|
||||||
} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
|
} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
|
||||||
printf("wpa_supplicant is terminating - stop monitoring\n");
|
printf("wpa_supplicant is terminating - stop monitoring\n");
|
||||||
wpa_cli_quit = 1;
|
wpa_cli_quit = 1;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
#include "mlme.h"
|
#include "mlme.h"
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "p2p/p2p.h"
|
||||||
#include "blacklist.h"
|
#include "blacklist.h"
|
||||||
#include "wpas_glue.h"
|
#include "wpas_glue.h"
|
||||||
#include "wps_supplicant.h"
|
#include "wps_supplicant.h"
|
||||||
|
@ -1169,6 +1170,21 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
||||||
if (res >= 0)
|
if (res >= 0)
|
||||||
wpa_ie_len += res;
|
wpa_ie_len += res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wpa_s->cross_connect_disallowed = 0;
|
||||||
|
if (bss) {
|
||||||
|
struct wpabuf *p2p;
|
||||||
|
p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
|
||||||
|
if (p2p) {
|
||||||
|
wpa_s->cross_connect_disallowed =
|
||||||
|
p2p_get_cross_connect_disallowed(p2p);
|
||||||
|
wpabuf_free(p2p);
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: WLAN AP %s cross "
|
||||||
|
"connection",
|
||||||
|
wpa_s->cross_connect_disallowed ?
|
||||||
|
"disallows" : "allows");
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
|
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
|
||||||
|
|
|
@ -214,6 +214,7 @@ struct wpa_global {
|
||||||
struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */
|
struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */
|
||||||
struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
|
struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
|
||||||
int p2p_disabled;
|
int p2p_disabled;
|
||||||
|
int cross_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -486,6 +487,27 @@ struct wpa_supplicant {
|
||||||
int pending_join_wps_method;
|
int pending_join_wps_method;
|
||||||
unsigned int roc_waiting_drv_freq;
|
unsigned int roc_waiting_drv_freq;
|
||||||
int force_long_sd;
|
int force_long_sd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether cross connection is disallowed by the AP to which this
|
||||||
|
* interface is associated (only valid if there is an association).
|
||||||
|
*/
|
||||||
|
int cross_connect_disallowed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether this P2P group is configured to use cross connection (only
|
||||||
|
* valid if this is P2P GO interface). The actual cross connect packet
|
||||||
|
* forwarding may not be configured depending on the uplink status.
|
||||||
|
*/
|
||||||
|
int cross_connect_enabled;
|
||||||
|
|
||||||
|
/* Whether cross connection forwarding is in use at the moment. */
|
||||||
|
int cross_connect_in_use;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Uplink interface name for cross connection
|
||||||
|
*/
|
||||||
|
char cross_connect_uplink[100];
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
struct wpa_ssid *bgscan_ssid;
|
struct wpa_ssid *bgscan_ssid;
|
||||||
|
|
Loading…
Reference in a new issue