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:
Jouni Malinen 2010-07-10 10:19:34 -07:00 committed by Jouni Malinen
parent 6c6915f3db
commit 72044390f3
15 changed files with 289 additions and 5 deletions

View file

@ -1612,6 +1612,7 @@ static int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid,
u8 *lpos;
size_t tmplen;
int res;
u8 group_capab;
if (p2p_ie == NULL)
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;
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) &&
(p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED))
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 "
"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(?) */
}

View file

@ -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);
/**
* 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_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);
/**
* 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 */

View file

@ -158,6 +158,8 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
group_capab = 0;
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_go_intent(buf, (p2p->go_intent << 1) |
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);
p2p_buf_add_status(buf, status);
group_capab = 0;
if (peer && (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP))
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
if (peer && peer->go_state == LOCAL_GO) {
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_go_intent(buf, (p2p->go_intent << 1) | tie_breaker);
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);
p2p_buf_add_status(buf, status);
group_capab = 0;
if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP)
group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
if (peer->go_state == LOCAL_GO) {
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);
if (go || resp_chan == NULL)
p2p_buf_add_operating_channel(buf, p2p->cfg->country,

View file

@ -145,6 +145,8 @@ static void p2p_group_add_common_ies(struct p2p_group *group,
group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
if (group->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);
}

View file

@ -365,6 +365,8 @@ struct p2p_data {
unsigned int ext_listen_interval_usec;
u8 peer_filter[ETH_ALEN];
int cross_connect;
};
/**

View file

@ -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)
{
struct p2p_message msg;