Accumulative patch from commit b57b560034f1bb1ad3a3892228940dde97323c0e
b57b560 wpa_supplicant: Default to nl80211 instead of wext
ee28f08 hostapd: Add more messages for error paths
61d2ce2 hostapd: Reject configuration file without interface parameter
a8a7890 Clear extra_blacklist_count on FLUSH command
c646862 WPS ER: Allow UPnP interface to be forced
728d971 Use status code 17 (unable to handle new STA) on max-STA limitation
5e24dc8 Add dup_binstr() to help common binary string tasks
8b44ad7 Use os_zalloc() instead of os_malloc() + os_memset()
2c48211 FT RRB: Validate os_malloc() return value before using it
7ca902b Make vlan_file optional if dynamic_vlan is used
bdb112d Add bitfield routines
04382f7 NFC: Add no waiting and no multiple operations options for scripts
fe90496 WPS: Fix AP auto configuration on config token generation
28fcfb6 NFC: Increase wpa_cli command buffer size
8f7a6dd WPS NFC: Allow Device Password ID override for selected registrar
aaecb69 WPS: Use generic MAC Address attribute builder
9ccd916 P2P: Clean up channel--frequency conversion functions
e864c0a Use a common frequency to channel conversion function
02db75b FT: Reset FT flag upon STA deauthentication
7800d45 P2P: Set P2P_DEV_PEER_WAITING_RESPONSE from TX status callback
d78d3c6 EAP peer: Add check before calling getSessionId method
dd57970 Disable network temporarily on repeated connection failures
Change-Id: If8078d5c1ff40ea806e844543cf6f2bf9d24b7ac
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 5e3caf1..07fd11d 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -469,7 +469,7 @@
if (!sta) {
sta = ap_sta_add(hapd, rx_auth->peer);
if (sta == NULL) {
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto fail;
}
}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 7bef55f..2e570c0 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -645,7 +645,7 @@
sta = ap_sta_add(hapd, mgmt->sa);
if (!sta) {
- resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto fail;
}
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index a832a73..a28c0f8 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -399,15 +399,13 @@
/* Save station identity for future RADIUS packets */
os_free(sm->identity);
- sm->identity = os_malloc(identity_len + 1);
+ sm->identity = (u8 *) dup_binstr(identity, identity_len);
if (sm->identity == NULL) {
sm->identity_len = 0;
return;
}
- os_memcpy(sm->identity, identity, identity_len);
sm->identity_len = identity_len;
- sm->identity[identity_len] = '\0';
hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity);
sm->dot1xAuthEapolRespIdFramesRx++;
@@ -1272,13 +1270,10 @@
NULL) < 0)
return;
- identity = os_malloc(len + 1);
+ identity = (u8 *) dup_binstr(buf, len);
if (identity == NULL)
return;
- os_memcpy(identity, buf, len);
- identity[len] = '\0';
-
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with "
"User-Name from Access-Accept '%s'",
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 7b1a9e6..6390e8b 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -837,6 +837,27 @@
hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+ if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED &&
+ !hapd->conf->vlan) {
+ /* dynamic vlans enabled but no (or empty) vlan_file given */
+ struct hostapd_vlan *vlan;
+ vlan = os_zalloc(sizeof(*vlan));
+ if (vlan == NULL) {
+ wpa_printf(MSG_ERROR, "Out of memory while assigning "
+ "VLAN interfaces");
+ return -1;
+ }
+
+ vlan->vlan_id = VLAN_ID_WILDCARD;
+ os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
+ hapd->conf->iface);
+ if (hapd->conf->vlan_tail)
+ hapd->conf->vlan_tail->next = vlan;
+ else
+ hapd->conf->vlan = vlan;
+ hapd->conf->vlan_tail = vlan;
+ }
+
if (vlan_dynamic_add(hapd, hapd->conf->vlan))
return -1;
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index ccb3f82..791b48d 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -1166,6 +1166,8 @@
/* RRB - Forward action frame to the target AP */
frame = os_malloc(sizeof(*frame) + len);
+ if (frame == NULL)
+ return -1;
frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
frame->packet_type = FT_PACKET_REQUEST;
frame->action_length = host_to_le16(len);
@@ -1216,6 +1218,8 @@
rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len;
frame = os_malloc(sizeof(*frame) + rlen);
+ if (frame == NULL)
+ return -1;
frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
frame->packet_type = FT_PACKET_RESPONSE;
frame->action_length = host_to_le16(rlen);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 98fadda..407b066 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1,6 +1,6 @@
/*
* IEEE 802.11 Common routines
- * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,6 +9,7 @@
#include "includes.h"
#include "common.h"
+#include "defs.h"
#include "ieee802_11_defs.h"
#include "ieee802_11_common.h"
@@ -486,3 +487,28 @@
return 0;
}
+
+
+enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
+{
+ enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
+
+ if (freq >= 2412 && freq <= 2472) {
+ mode = HOSTAPD_MODE_IEEE80211G;
+ *channel = (freq - 2407) / 5;
+ } else if (freq == 2484) {
+ mode = HOSTAPD_MODE_IEEE80211B;
+ *channel = 14;
+ } else if (freq >= 4900 && freq < 5000) {
+ mode = HOSTAPD_MODE_IEEE80211A;
+ *channel = (freq - 4000) / 5;
+ } else if (freq >= 5000 && freq < 5900) {
+ mode = HOSTAPD_MODE_IEEE80211A;
+ *channel = (freq - 5000) / 5;
+ } else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
+ mode = HOSTAPD_MODE_IEEE80211AD;
+ *channel = (freq - 56160) / 2160;
+ }
+
+ return mode;
+}
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 55fa49d..7f59cf2 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -99,5 +99,6 @@
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
const char *name, const char *val);
+enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
#endif /* IEEE802_11_COMMON_H */
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 7af3317..4656c1b 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -2110,14 +2110,8 @@
dlen = dpos - desc;
else
dlen = os_strlen(desc);
- drv->adapter_desc = os_malloc(dlen + 1);
- if (drv->adapter_desc) {
- os_memcpy(drv->adapter_desc, desc, dlen);
- drv->adapter_desc[dlen] = '\0';
- }
-
+ drv->adapter_desc = dup_binstr(desc, dlen);
os_free(b);
-
if (drv->adapter_desc == NULL)
return -1;
@@ -2284,14 +2278,8 @@
} else {
dlen = os_strlen(desc[i]);
}
- drv->adapter_desc = os_malloc(dlen + 1);
- if (drv->adapter_desc) {
- os_memcpy(drv->adapter_desc, desc[i], dlen);
- drv->adapter_desc[dlen] = '\0';
- }
-
+ drv->adapter_desc = dup_binstr(desc[i], dlen);
os_free(names);
-
if (drv->adapter_desc == NULL)
return -1;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 0b5a7dc..6125015 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5121,35 +5121,11 @@
struct hostapd_channel_data *chan,
struct nlattr *tb_freq[])
{
- enum hostapd_hw_mode m;
-
+ u8 channel;
chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
chan->flag = 0;
-
- if (chan->freq < 4000)
- m = HOSTAPD_MODE_IEEE80211B;
- else if (chan->freq > 50000)
- m = HOSTAPD_MODE_IEEE80211AD;
- else
- m = HOSTAPD_MODE_IEEE80211A;
-
- switch (m) {
- case HOSTAPD_MODE_IEEE80211AD:
- chan->chan = (chan->freq - 56160) / 2160;
- break;
- case HOSTAPD_MODE_IEEE80211A:
- chan->chan = chan->freq / 5 - 1000;
- break;
- case HOSTAPD_MODE_IEEE80211B:
- case HOSTAPD_MODE_IEEE80211G:
- if (chan->freq == 2484)
- chan->chan = 14;
- else
- chan->chan = (chan->freq - 2407) / 5;
- break;
- default:
- break;
- }
+ if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
+ chan->chan = channel;
if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
chan->flag |= HOSTAPD_CHAN_DISABLED;
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 9733e01..1401050 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -502,11 +502,9 @@
"IWEVCUSTOM length");
return;
}
- buf = os_malloc(iwe->u.data.length + 1);
+ buf = dup_binstr(custom, iwe->u.data.length);
if (buf == NULL)
return;
- os_memcpy(buf, custom, iwe->u.data.length);
- buf[iwe->u.data.length] = '\0';
wpa_driver_wext_event_wireless_custom(drv->ctx, buf);
os_free(buf);
break;
diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
index 1d0ff6e..04eb4fd 100644
--- a/src/drivers/drivers.c
+++ b/src/drivers/drivers.c
@@ -50,12 +50,12 @@
struct wpa_driver_ops *wpa_drivers[] =
{
-#ifdef CONFIG_DRIVER_WEXT
- &wpa_driver_wext_ops,
-#endif /* CONFIG_DRIVER_WEXT */
#ifdef CONFIG_DRIVER_NL80211
&wpa_driver_nl80211_ops,
#endif /* CONFIG_DRIVER_NL80211 */
+#ifdef CONFIG_DRIVER_WEXT
+ &wpa_driver_wext_ops,
+#endif /* CONFIG_DRIVER_WEXT */
#ifdef CONFIG_DRIVER_HOSTAP
&wpa_driver_hostap_ops,
#endif /* CONFIG_DRIVER_HOSTAP */
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 4df8853..c0d7078 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -406,9 +406,11 @@
sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
&sm->eapKeyDataLen);
os_free(sm->eapSessionId);
- sm->eapSessionId = sm->m->getSessionId(sm, sm->eap_method_priv,
- &sm->eapSessionIdLen);
- if (sm->eapSessionId) {
+ sm->eapSessionId = NULL;
+ if (sm->m->getSessionId) {
+ sm->eapSessionId = sm->m->getSessionId(
+ sm, sm->eap_method_priv,
+ &sm->eapSessionIdLen);
wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
sm->eapSessionId, sm->eapSessionIdLen);
}
diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c
index fb6c282..f9aa742 100644
--- a/src/eap_peer/eap_mschapv2.c
+++ b/src/eap_peer/eap_mschapv2.c
@@ -644,10 +644,8 @@
* must allocate a large enough temporary buffer to create that since
* the received message does not include nul termination.
*/
- buf = os_malloc(len + 1);
+ buf = dup_binstr(msdata, len);
if (buf) {
- os_memcpy(buf, msdata, len);
- buf[len] = '\0';
retry = eap_mschapv2_failure_txt(sm, data, buf);
os_free(buf);
}
diff --git a/src/eap_peer/tncc.c b/src/eap_peer/tncc.c
index f5edfd5..a3ec395 100644
--- a/src/eap_peer/tncc.c
+++ b/src/eap_peer/tncc.c
@@ -741,12 +741,10 @@
enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
int recommendation_msg = 0;
- buf = os_malloc(len + 1);
+ buf = dup_binstr(msg, len);
if (buf == NULL)
return TNCCS_PROCESS_ERROR;
- os_memcpy(buf, msg, len);
- buf[len] = '\0';
start = os_strstr(buf, "<TNCCS-Batch ");
end = os_strstr(buf, "</TNCCS-Batch>");
if (start == NULL || end == NULL || start > end) {
diff --git a/src/eap_server/eap_sim_db.c b/src/eap_server/eap_sim_db.c
index 257013e..1b9d701 100644
--- a/src/eap_server/eap_sim_db.c
+++ b/src/eap_server/eap_sim_db.c
@@ -1480,7 +1480,6 @@
*/
char * sim_get_username(const u8 *identity, size_t identity_len)
{
- char *username;
size_t pos;
if (identity == NULL)
@@ -1491,11 +1490,5 @@
break;
}
- username = os_malloc(pos + 1);
- if (username == NULL)
- return NULL;
- os_memcpy(username, identity, pos);
- username[pos] = '\0';
-
- return username;
+ return dup_binstr(identity, pos);
}
diff --git a/src/eap_server/tncs.c b/src/eap_server/tncs.c
index 5e332ae..e429f1e 100644
--- a/src/eap_server/tncs.c
+++ b/src/eap_server/tncs.c
@@ -851,12 +851,10 @@
unsigned char *decoded;
size_t decoded_len;
- buf = os_malloc(len + 1);
+ buf = dup_binstr(msg, len);
if (buf == NULL)
return TNCCS_PROCESS_ERROR;
- os_memcpy(buf, msg, len);
- buf[len] = '\0';
start = os_strstr(buf, "<TNCCS-Batch ");
end = os_strstr(buf, "</TNCCS-Batch>");
if (start == NULL || end == NULL || start > end) {
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 00fbb90..cbd039a 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -268,8 +268,7 @@
"P2P: Starting short listen state (state=%s)",
p2p_state_txt(p2p->state));
- freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
- p2p->cfg->channel);
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
if (freq < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Unknown regulatory class/channel");
@@ -319,8 +318,7 @@
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Going to listen(only) state");
- freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class,
- p2p->cfg->channel);
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
if (freq < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Unknown regulatory class/channel");
@@ -914,7 +912,7 @@
channel = c->reg_class[cl].channel[ch];
}
- freq = p2p_channel_to_freq(p2p->cfg->country, reg_class, channel);
+ freq = p2p_channel_to_freq(reg_class, channel);
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Next progressive search "
"channel: reg_class %u channel %u -> %d MHz",
reg_class, channel, freq);
@@ -1243,8 +1241,7 @@
u8 op_class, op_channel;
unsigned int freq = force_freq ? force_freq : pref_freq;
- if (p2p_freq_to_channel(p2p->cfg->country, freq,
- &op_class, &op_channel) < 0) {
+ if (p2p_freq_to_channel(freq, &op_class, &op_channel) < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Unsupported frequency %u MHz", freq);
return -1;
@@ -1280,24 +1277,24 @@
if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 &&
p2p_supported_freq(p2p, p2p->best_freq_overall) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
- &op_class, &op_channel) == 0) {
+ p2p_freq_to_channel(p2p->best_freq_overall, &op_class, &op_channel)
+ == 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best "
"overall channel as operating channel preference");
p2p->op_reg_class = op_class;
p2p->op_channel = op_channel;
} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 &&
p2p_supported_freq(p2p, p2p->best_freq_5) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
- &op_class, &op_channel) == 0) {
+ p2p_freq_to_channel(p2p->best_freq_5, &op_class, &op_channel)
+ == 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 5 GHz "
"channel as operating channel preference");
p2p->op_reg_class = op_class;
p2p->op_channel = op_channel;
} else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_24 > 0 &&
p2p_supported_freq(p2p, p2p->best_freq_24) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
- &op_class, &op_channel) == 0) {
+ p2p_freq_to_channel(p2p->best_freq_24, &op_class,
+ &op_channel) == 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Select best 2.4 "
"GHz channel as operating channel preference");
p2p->op_reg_class = op_class;
@@ -1546,8 +1543,7 @@
if (msg->listen_channel) {
int freq;
- freq = p2p_channel_to_freq((char *) msg->listen_channel,
- msg->listen_channel[3],
+ freq = p2p_channel_to_freq(msg->listen_channel[3],
msg->listen_channel[4]);
if (freq < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
@@ -1646,8 +1642,7 @@
if (go) {
/* Setup AP mode for WPS provisioning */
- res.freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->op_reg_class,
+ res.freq = p2p_channel_to_freq(p2p->op_reg_class,
p2p->op_channel);
os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len);
res.ssid_len = p2p->ssid_len;
@@ -1671,8 +1666,7 @@
int freq;
if (freqs + 1 == P2P_MAX_CHANNELS)
break;
- freq = p2p_channel_to_freq(peer->country, c->reg_class,
- c->channel[j]);
+ freq = p2p_channel_to_freq(c->reg_class, c->channel[j]);
if (freq < 0)
continue;
res.freq_list[freqs++] = freq;
@@ -1902,8 +1896,7 @@
if (msg.listen_channel) {
os_memcpy(dev->country, msg.listen_channel, 3);
- dev->listen_freq = p2p_channel_to_freq(dev->country,
- msg.listen_channel[3],
+ dev->listen_freq = p2p_channel_to_freq(msg.listen_channel[3],
msg.listen_channel[4]);
}
@@ -3099,7 +3092,8 @@
}
-static void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success)
+static void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success,
+ const u8 *addr)
{
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: GO Negotiation Response (failure) TX callback: "
@@ -3107,6 +3101,12 @@
if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
p2p_go_neg_failed(p2p, p2p->go_neg_peer,
p2p->go_neg_peer->status);
+ } else if (success) {
+ struct p2p_device *dev;
+ dev = p2p_get_device(p2p, addr);
+ if (dev &&
+ dev->status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
+ dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
}
}
@@ -3186,7 +3186,7 @@
p2p_go_neg_resp_cb(p2p, success);
break;
case P2P_PENDING_GO_NEG_RESPONSE_FAILURE:
- p2p_go_neg_resp_failure_cb(p2p, success);
+ p2p_go_neg_resp_failure_cb(p2p, success, dst);
break;
case P2P_PENDING_GO_NEG_CONFIRM:
p2p_go_neg_conf_cb(p2p, result);
@@ -4155,7 +4155,7 @@
int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel)
{
- if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0)
+ if (p2p_channel_to_freq(reg_class, channel) < 0)
return -1;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: "
@@ -4185,8 +4185,7 @@
int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel,
int cfg_op_channel)
{
- if (p2p_channel_to_freq(p2p->cfg->country, op_reg_class, op_channel)
- < 0)
+ if (p2p_channel_to_freq(op_reg_class, op_channel) < 0)
return -1;
wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, "P2P: Set Operating channel: "
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index c143ef4..c7cf205 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -351,7 +351,7 @@
unsigned int i;
if (p2p->own_freq_preference > 0 &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->own_freq_preference,
+ p2p_freq_to_channel(p2p->own_freq_preference,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick own channel "
@@ -363,7 +363,7 @@
}
if (p2p->best_freq_overall > 0 &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall,
+ p2p_freq_to_channel(p2p->best_freq_overall,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best overall "
@@ -375,12 +375,11 @@
}
/* First, try to pick the best channel from another band */
- freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class,
- p2p->op_channel);
+ freq = p2p_channel_to_freq(p2p->op_reg_class, p2p->op_channel);
if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 &&
!p2p_channels_includes(intersection, p2p->op_reg_class,
p2p->op_channel) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5,
+ p2p_freq_to_channel(p2p->best_freq_5,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 5 GHz "
@@ -394,7 +393,7 @@
if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 &&
!p2p_channels_includes(intersection, p2p->op_reg_class,
p2p->op_channel) &&
- p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24,
+ p2p_freq_to_channel(p2p->best_freq_24,
&op_reg_class, &op_channel) == 0 &&
p2p_channels_includes(intersection, op_reg_class, op_channel)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 2.4 GHz "
@@ -619,8 +618,6 @@
"P2P: Not ready for GO negotiation with " MACSTR,
MAC2STR(sa));
status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
- if (dev)
- dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa,
msg.dev_password_id);
} else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) {
@@ -736,9 +733,7 @@
goto fail;
dev->go_state = go ? LOCAL_GO : REMOTE_GO;
- dev->oper_freq = p2p_channel_to_freq((const char *)
- msg.operating_channel,
- msg.operating_channel[3],
+ dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
msg.operating_channel[4]);
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
"channel preference: %d MHz", dev->oper_freq);
@@ -773,8 +768,7 @@
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
@@ -1050,9 +1044,7 @@
}
if (msg.operating_channel) {
- dev->oper_freq = p2p_channel_to_freq((const char *)
- msg.operating_channel,
- msg.operating_channel[3],
+ dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
msg.operating_channel[4]);
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
"channel preference: %d MHz", dev->oper_freq);
@@ -1231,9 +1223,7 @@
#ifdef ANDROID_P2P
if (msg.operating_channel) {
- dev->oper_freq = p2p_channel_to_freq((const char *)
- msg.operating_channel,
- msg.operating_channel[3],
+ dev->oper_freq = p2p_channel_to_freq(msg.operating_channel[3],
msg.operating_channel[4]);
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
"channel preference: %d MHz", dev->oper_freq);
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 008f3f0..81a0b27 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -570,9 +570,8 @@
/* p2p_utils.c */
int p2p_random(char *buf, size_t len);
-int p2p_channel_to_freq(const char *country, int reg_class, int channel);
-int p2p_freq_to_channel(const char *country, unsigned int freq, u8 *reg_class,
- u8 *channel);
+int p2p_channel_to_freq(int op_class, int channel);
+int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel);
void p2p_channels_intersect(const struct p2p_channels *a,
const struct p2p_channels *b,
struct p2p_channels *res);
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 3beefd2..05822c6 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -238,8 +238,7 @@
if (op_freq) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Invitation "
"processing forced frequency %d MHz", op_freq);
- if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
- ®_class, &channel) < 0) {
+ if (p2p_freq_to_channel(op_freq, ®_class, &channel) < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Unknown forced freq %d MHz from "
"invitation_process()", op_freq);
@@ -278,7 +277,6 @@
if (msg.operating_channel) {
int req_freq;
req_freq = p2p_channel_to_freq(
- (const char *) msg.operating_channel,
msg.operating_channel[3],
msg.operating_channel[4]);
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer "
@@ -326,8 +324,7 @@
}
}
- op_freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->op_reg_class,
+ op_freq = p2p_channel_to_freq(p2p->op_reg_class,
p2p->op_channel);
if (op_freq < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
@@ -362,8 +359,7 @@
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index a1268e4..3bbce16 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -217,8 +217,7 @@
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c
index bf75605..d8daa59 100644
--- a/src/p2p/p2p_sd.c
+++ b/src/p2p/p2p_sd.c
@@ -290,8 +290,7 @@
if (rx_freq > 0)
freq = rx_freq;
else
- freq = p2p_channel_to_freq(p2p->cfg->country,
- p2p->cfg->reg_class,
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0)
return;
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index 37b9361..69bd14b 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -46,11 +46,17 @@
}
-static int p2p_channel_to_freq_j4(int reg_class, int channel)
+/**
+ * p2p_channel_to_freq - Convert channel info to frequency
+ * @op_class: Operating class
+ * @channel: Channel number
+ * Returns: Frequency in MHz or -1 if the specified channel is unknown
+ */
+int p2p_channel_to_freq(int op_class, int channel)
{
- /* Table J-4 in P802.11REVmb/D4.0 - Global operating classes */
- /* TODO: more regulatory classes */
- switch (reg_class) {
+ /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
+ /* TODO: more operating classes */
+ switch (op_class) {
case 81:
/* channels 1..13 */
if (channel < 1 || channel > 13)
@@ -94,75 +100,34 @@
/**
- * p2p_channel_to_freq - Convert channel info to frequency
- * @country: Country code
- * @reg_class: Regulatory class
- * @channel: Channel number
- * Returns: Frequency in MHz or -1 if the specified channel is unknown
- */
-int p2p_channel_to_freq(const char *country, int reg_class, int channel)
-{
- if (country[2] == 0x04)
- return p2p_channel_to_freq_j4(reg_class, channel);
-
- /* These are mainly for backwards compatibility; to be removed */
- switch (reg_class) {
- case 1: /* US/1, EU/1, JP/1 = 5 GHz, channels 36,40,44,48 */
- if (channel < 36 || channel > 48)
- return -1;
- return 5000 + 5 * channel;
- case 3: /* US/3 = 5 GHz, channels 149,153,157,161 */
- case 5: /* US/5 = 5 GHz, channels 149,153,157,161 */
- if (channel < 149 || channel > 161)
- return -1;
- return 5000 + 5 * channel;
- case 4: /* EU/4 = 2.407 GHz, channels 1..13 */
- case 12: /* US/12 = 2.407 GHz, channels 1..11 */
- case 30: /* JP/30 = 2.407 GHz, channels 1..13 */
- if (channel < 1 || channel > 13)
- return -1;
- return 2407 + 5 * channel;
- case 31: /* JP/31 = 2.414 GHz, channel 14 */
- if (channel != 14)
- return -1;
- return 2414 + 5 * channel;
- }
-
- return -1;
-}
-
-
-/**
* p2p_freq_to_channel - Convert frequency into channel info
- * @country: Country code
- * @reg_class: Buffer for returning regulatory class
+ * @op_class: Buffer for returning operating class
* @channel: Buffer for returning channel number
* Returns: 0 on success, -1 if the specified frequency is unknown
*/
-int p2p_freq_to_channel(const char *country, unsigned int freq, u8 *reg_class,
- u8 *channel)
+int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel)
{
/* TODO: more operating classes */
if (freq >= 2412 && freq <= 2472) {
- *reg_class = 81; /* 2.407 GHz, channels 1..13 */
+ *op_class = 81; /* 2.407 GHz, channels 1..13 */
*channel = (freq - 2407) / 5;
return 0;
}
if (freq == 2484) {
- *reg_class = 82; /* channel 14 */
+ *op_class = 82; /* channel 14 */
*channel = 14;
return 0;
}
if (freq >= 5180 && freq <= 5240) {
- *reg_class = 115; /* 5 GHz, channels 36..48 */
+ *op_class = 115; /* 5 GHz, channels 36..48 */
*channel = (freq - 5000) / 5;
return 0;
}
if (freq >= 5745 && freq <= 5805) {
- *reg_class = 124; /* 5 GHz, channels 149..161 */
+ *op_class = 124; /* 5 GHz, channels 149..161 */
*channel = (freq - 5000) / 5;
return 0;
}
@@ -261,9 +226,8 @@
for (i = 0; i < channels->reg_classes; i++) {
const struct p2p_reg_class *reg = &channels->reg_class[i];
for (j = 0; j < reg->channels; j++) {
- if (p2p_channel_to_freq_j4(reg->reg_class,
- reg->channel[j]) ==
- (int) freq)
+ if (p2p_channel_to_freq(reg->reg_class,
+ reg->channel[j]) == (int) freq)
return 1;
}
}
@@ -274,8 +238,7 @@
int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq)
{
u8 op_reg_class, op_channel;
- if (p2p_freq_to_channel(p2p->cfg->country, freq,
- &op_reg_class, &op_channel) < 0)
+ if (p2p_freq_to_channel(freq, &op_reg_class, &op_channel) < 0)
return 0;
return p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
op_channel);
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index dbb493e..d4533a8 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -315,6 +315,7 @@
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len);
int wpa_ft_is_completed(struct wpa_sm *sm);
+void wpa_reset_ft_completed(struct wpa_sm *sm);
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
size_t ies_len, const u8 *src_addr);
int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
@@ -346,6 +347,10 @@
return 0;
}
+static inline void wpa_reset_ft_completed(struct wpa_sm *sm)
+{
+}
+
static inline int
wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
const u8 *src_addr)
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 4b08a62..6b7fa91 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -534,6 +534,13 @@
}
+void wpa_reset_ft_completed(struct wpa_sm *sm)
+{
+ if (sm != NULL)
+ sm->ft_completed = 0;
+}
+
+
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
size_t gtk_elem_len)
{
diff --git a/src/tls/x509v3.c b/src/tls/x509v3.c
index 87c5178..06540bf 100644
--- a/src/tls/x509v3.c
+++ b/src/tls/x509v3.c
@@ -443,17 +443,16 @@
return -1;
}
- val = os_malloc(hdr.length + 1);
+ val = dup_binstr(hdr.payload, hdr.length);
if (val == NULL) {
x509_free_name(name);
return -1;
}
- os_memcpy(val, hdr.payload, hdr.length);
- val[hdr.length] = '\0';
if (os_strlen(val) != hdr.length) {
wpa_printf(MSG_INFO, "X509: Reject certificate with "
"embedded NUL byte in a string (%s[NUL])",
val);
+ os_free(val);
x509_free_name(name);
return -1;
}
diff --git a/src/utils/Makefile b/src/utils/Makefile
index 0f1f191..940b4d8 100644
--- a/src/utils/Makefile
+++ b/src/utils/Makefile
@@ -14,6 +14,7 @@
LIB_OBJS= \
base64.o \
+ bitfield.o \
common.o \
ip_addr.o \
radiotap.o \
diff --git a/src/utils/bitfield.c b/src/utils/bitfield.c
new file mode 100644
index 0000000..f90e4be
--- /dev/null
+++ b/src/utils/bitfield.c
@@ -0,0 +1,89 @@
+/*
+ * Bitfield
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "bitfield.h"
+
+
+struct bitfield {
+ u8 *bits;
+ size_t max_bits;
+};
+
+
+struct bitfield * bitfield_alloc(size_t max_bits)
+{
+ struct bitfield *bf;
+
+ bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8);
+ if (bf == NULL)
+ return NULL;
+ bf->bits = (u8 *) (bf + 1);
+ bf->max_bits = max_bits;
+ return bf;
+}
+
+
+void bitfield_free(struct bitfield *bf)
+{
+ os_free(bf);
+}
+
+
+void bitfield_set(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return;
+ bf->bits[bit / 8] |= BIT(bit % 8);
+}
+
+
+void bitfield_clear(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return;
+ bf->bits[bit / 8] &= ~BIT(bit % 8);
+}
+
+
+int bitfield_is_set(struct bitfield *bf, size_t bit)
+{
+ if (bit >= bf->max_bits)
+ return 0;
+ return !!(bf->bits[bit / 8] & BIT(bit % 8));
+}
+
+
+static int first_zero(u8 val)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (!(val & 0x01))
+ return i;
+ val >>= 1;
+ }
+ return -1;
+}
+
+
+int bitfield_get_first_zero(struct bitfield *bf)
+{
+ size_t i;
+ for (i = 0; i <= (bf->max_bits + 7) / 8; i++) {
+ if (bf->bits[i] != 0xff)
+ break;
+ }
+ if (i > (bf->max_bits + 7) / 8)
+ return -1;
+ i = i * 8 + first_zero(bf->bits[i]);
+ if (i >= bf->max_bits)
+ return -1;
+ return i;
+}
diff --git a/src/utils/bitfield.h b/src/utils/bitfield.h
new file mode 100644
index 0000000..7050a20
--- /dev/null
+++ b/src/utils/bitfield.h
@@ -0,0 +1,21 @@
+/*
+ * Bitfield
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BITFIELD_H
+#define BITFIELD_H
+
+struct bitfield;
+
+struct bitfield * bitfield_alloc(size_t max_bits);
+void bitfield_free(struct bitfield *bf);
+void bitfield_set(struct bitfield *bf, size_t bit);
+void bitfield_clear(struct bitfield *bf, size_t bit);
+int bitfield_is_set(struct bitfield *bf, size_t bit);
+int bitfield_get_first_zero(struct bitfield *bf);
+
+#endif /* BITFIELD_H */
diff --git a/src/utils/common.c b/src/utils/common.c
index e636984..bf326cd 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -517,11 +517,9 @@
if (pos == NULL || pos[1] != '\0')
return NULL;
*len = pos - value;
- str = os_malloc(*len + 1);
+ str = dup_binstr(value, *len);
if (str == NULL)
return NULL;
- os_memcpy(str, value, *len);
- str[*len] = '\0';
return str;
} else if (*value == 'P' && value[1] == '"') {
const char *pos;
@@ -532,11 +530,9 @@
if (pos == NULL || pos[1] != '\0')
return NULL;
tlen = pos - value;
- tstr = os_malloc(tlen + 1);
+ tstr = dup_binstr(value, tlen);
if (tstr == NULL)
return NULL;
- os_memcpy(tstr, value, tlen);
- tstr[tlen] = '\0';
str = os_malloc(tlen + 1);
if (str == NULL) {
@@ -610,3 +606,19 @@
return len;
}
+
+
+char * dup_binstr(const void *src, size_t len)
+{
+ char *res;
+
+ if (src == NULL)
+ return NULL;
+ res = os_malloc(len + 1);
+ if (res == NULL)
+ return NULL;
+ os_memcpy(res, src, len);
+ res[len] = '\0';
+
+ return res;
+}
diff --git a/src/utils/common.h b/src/utils/common.h
index a859042..e4f7031 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -487,6 +487,7 @@
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len);
+char * dup_binstr(const void *src, size_t len);
static inline int is_zero_ether_addr(const u8 *a)
{
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index edcc18c..ac9bb1e 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -417,3 +417,14 @@
return ie;
}
+
+
+int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr)
+{
+ wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")",
+ MAC2STR(addr));
+ wpabuf_put_be16(msg, ATTR_MAC_ADDR);
+ wpabuf_put_be16(msg, ETH_ALEN);
+ wpabuf_put_data(msg, addr, ETH_ALEN);
+ return 0;
+}
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index 0897b7b..4e4da5e 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -343,10 +343,36 @@
if (wps_build_version(plain) ||
wps_build_cred(&data, plain) ||
wps_build_wfa_ext(plain, 0, NULL, 0)) {
+ os_free(data.new_psk);
wpabuf_free(plain);
return NULL;
}
+ if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk &&
+ wps->ap) {
+ struct wps_credential cred;
+
+ wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based "
+ "on credential token generation");
+
+ os_memset(&cred, 0, sizeof(cred));
+ os_memcpy(cred.ssid, wps->ssid, wps->ssid_len);
+ cred.ssid_len = wps->ssid_len;
+ cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK;
+ cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES;
+ os_memcpy(cred.key, data.new_psk, data.new_psk_len);
+ cred.key_len = data.new_psk_len;
+
+ wps->wps_state = WPS_STATE_CONFIGURED;
+ wpa_hexdump_ascii_key(MSG_DEBUG,
+ "WPS: Generated random passphrase",
+ data.new_psk, data.new_psk_len);
+ if (wps->cred_cb)
+ wps->cred_cb(wps->cb_ctx, &cred);
+ }
+
+ os_free(data.new_psk);
+
return plain;
}
diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c
index 3c94a43..7a7c099 100644
--- a/src/wps/wps_dev_attr.c
+++ b/src/wps/wps_dev_attr.c
@@ -257,11 +257,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
os_free(dev->manufacturer);
- dev->manufacturer = os_malloc(str_len + 1);
+ dev->manufacturer = dup_binstr(str, str_len);
if (dev->manufacturer == NULL)
return -1;
- os_memcpy(dev->manufacturer, str, str_len);
- dev->manufacturer[str_len] = '\0';
return 0;
}
@@ -278,11 +276,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
os_free(dev->model_name);
- dev->model_name = os_malloc(str_len + 1);
+ dev->model_name = dup_binstr(str, str_len);
if (dev->model_name == NULL)
return -1;
- os_memcpy(dev->model_name, str, str_len);
- dev->model_name[str_len] = '\0';
return 0;
}
@@ -299,11 +295,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
os_free(dev->model_number);
- dev->model_number = os_malloc(str_len + 1);
+ dev->model_number = dup_binstr(str, str_len);
if (dev->model_number == NULL)
return -1;
- os_memcpy(dev->model_number, str, str_len);
- dev->model_number[str_len] = '\0';
return 0;
}
@@ -320,11 +314,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
os_free(dev->serial_number);
- dev->serial_number = os_malloc(str_len + 1);
+ dev->serial_number = dup_binstr(str, str_len);
if (dev->serial_number == NULL)
return -1;
- os_memcpy(dev->serial_number, str, str_len);
- dev->serial_number[str_len] = '\0';
return 0;
}
@@ -341,11 +333,9 @@
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
os_free(dev->device_name);
- dev->device_name = os_malloc(str_len + 1);
+ dev->device_name = dup_binstr(str, str_len);
if (dev->device_name == NULL)
return -1;
- os_memcpy(dev->device_name, str, str_len);
- dev->device_name[str_len] = '\0';
return 0;
}
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index 9c0cebb..1af43c2 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -16,16 +16,6 @@
#include "wps_dev_attr.h"
-static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg)
-{
- wpa_printf(MSG_DEBUG, "WPS: * MAC Address");
- wpabuf_put_be16(msg, ATTR_MAC_ADDR);
- wpabuf_put_be16(msg, ETH_ALEN);
- wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN);
- return 0;
-}
-
-
static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg)
{
u8 state;
@@ -149,7 +139,7 @@
if (wps_build_version(msg) ||
wps_build_msg_type(msg, WPS_M1) ||
wps_build_uuid_e(msg, wps->uuid_e) ||
- wps_build_mac_addr(wps, msg) ||
+ wps_build_mac_addr(msg, wps->mac_addr_e) ||
wps_build_enrollee_nonce(wps, msg) ||
wps_build_public_key(wps, msg) ||
wps_build_auth_type_flags(wps, msg) ||
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 14c1b77..5694997 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -796,52 +796,31 @@
if (attr->manufacturer) {
os_free(sta->manufacturer);
- sta->manufacturer = os_malloc(attr->manufacturer_len + 1);
- if (sta->manufacturer) {
- os_memcpy(sta->manufacturer, attr->manufacturer,
- attr->manufacturer_len);
- sta->manufacturer[attr->manufacturer_len] = '\0';
- }
+ sta->manufacturer = dup_binstr(attr->manufacturer,
+ attr->manufacturer_len);
}
if (attr->model_name) {
os_free(sta->model_name);
- sta->model_name = os_malloc(attr->model_name_len + 1);
- if (sta->model_name) {
- os_memcpy(sta->model_name, attr->model_name,
- attr->model_name_len);
- sta->model_name[attr->model_name_len] = '\0';
- }
+ sta->model_name = dup_binstr(attr->model_name,
+ attr->model_name_len);
}
if (attr->model_number) {
os_free(sta->model_number);
- sta->model_number = os_malloc(attr->model_number_len + 1);
- if (sta->model_number) {
- os_memcpy(sta->model_number, attr->model_number,
- attr->model_number_len);
- sta->model_number[attr->model_number_len] = '\0';
- }
+ sta->model_number = dup_binstr(attr->model_number,
+ attr->model_number_len);
}
if (attr->serial_number) {
os_free(sta->serial_number);
- sta->serial_number = os_malloc(attr->serial_number_len + 1);
- if (sta->serial_number) {
- os_memcpy(sta->serial_number, attr->serial_number,
- attr->serial_number_len);
- sta->serial_number[attr->serial_number_len] = '\0';
- }
+ sta->serial_number = dup_binstr(attr->serial_number,
+ attr->serial_number_len);
}
if (attr->dev_name) {
os_free(sta->dev_name);
- sta->dev_name = os_malloc(attr->dev_name_len + 1);
- if (sta->dev_name) {
- os_memcpy(sta->dev_name, attr->dev_name,
- attr->dev_name_len);
- sta->dev_name[attr->dev_name_len] = '\0';
- }
+ sta->dev_name = dup_binstr(attr->dev_name, attr->dev_name_len);
}
eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
@@ -1292,6 +1271,22 @@
/* Limit event_id to < 32 bits to avoid issues with atoi() */
er->event_id &= 0x0fffffff;
+ if (filter && os_strncmp(filter, "ifname=", 7) == 0) {
+ const char *pos, *end;
+ pos = filter + 7;
+ end = os_strchr(pos, ' ');
+ if (end) {
+ size_t len = end - pos;
+ os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ?
+ len + 1 : sizeof(er->ifname));
+ filter = end + 1;
+ } else {
+ os_strlcpy(er->ifname, pos, sizeof(er->ifname));
+ filter = NULL;
+ }
+ er->forced_ifname = 1;
+ }
+
if (filter) {
if (inet_aton(filter, &er->filter_addr) == 0) {
wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter "
@@ -1302,10 +1297,10 @@
wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections "
"with %s", filter);
}
- if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text,
+ if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text,
er->mac_addr)) {
wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
- "for %s. Does it have IP address?", ifname);
+ "for %s. Does it have IP address?", er->ifname);
wps_er_deinit(er, NULL, NULL);
return NULL;
}
diff --git a/src/wps/wps_er.h b/src/wps/wps_er.h
index 6119647..4b48ff6 100644
--- a/src/wps/wps_er.h
+++ b/src/wps/wps_er.h
@@ -76,6 +76,7 @@
struct wps_er {
struct wps_context *wps;
char ifname[17];
+ int forced_ifname;
u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */
char *ip_addr_text; /* IP address of network i.f. we use */
unsigned ip_addr; /* IP address of network i.f. we use (host order) */
diff --git a/src/wps/wps_er_ssdp.c b/src/wps/wps_er_ssdp.c
index f9f6e6c..e381fec 100644
--- a/src/wps/wps_er_ssdp.c
+++ b/src/wps/wps_er_ssdp.c
@@ -166,7 +166,9 @@
return -1;
}
- er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr);
+ er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr,
+ er->forced_ifname ?
+ er->ifname : NULL);
if (er->multicast_sd < 0) {
wpa_printf(MSG_INFO, "WPS ER: Failed to open multicast socket "
"for SSDP");
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 6efc3bf..413379b 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -169,6 +169,7 @@
const struct wpabuf *pubkey, const u8 *dev_pw,
size_t dev_pw_len);
struct wpabuf * wps_ie_encapsulate(struct wpabuf *data);
+int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr);
/* wps_attr_process.c */
int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
@@ -196,7 +197,8 @@
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg);
int wps_device_store(struct wps_registrar *reg,
struct wps_device_data *dev, const u8 *uuid);
-void wps_registrar_selected_registrar_changed(struct wps_registrar *reg);
+void wps_registrar_selected_registrar_changed(struct wps_registrar *reg,
+ u16 dev_pw_id);
const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count);
int wps_registrar_pbc_overlap(struct wps_registrar *reg,
const u8 *addr, const u8 *uuid_e);
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 86ef022..d182f14 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -771,7 +771,7 @@
else
wps_registrar_add_authorized_mac(
reg, (u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
wps_registrar_set_selected_timeout,
@@ -793,7 +793,7 @@
addr = pin->enrollee_addr;
wps_registrar_remove_authorized_mac(reg, addr);
wps_remove_pin(pin);
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -956,7 +956,7 @@
os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
wps_registrar_remove_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -1004,7 +1004,7 @@
os_memset(reg->p2p_dev_addr, 0, ETH_ALEN);
wps_registrar_add_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
@@ -1027,7 +1027,7 @@
wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar");
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
reg->selected_registrar = 0;
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -1531,18 +1531,6 @@
}
-static int wps_build_cred_mac_addr(struct wpabuf *msg,
- const struct wps_credential *cred)
-{
- wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")",
- MAC2STR(cred->mac_addr));
- wpabuf_put_be16(msg, ATTR_MAC_ADDR);
- wpabuf_put_be16(msg, ETH_ALEN);
- wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN);
- return 0;
-}
-
-
static int wps_build_credential(struct wpabuf *msg,
const struct wps_credential *cred)
{
@@ -1551,7 +1539,7 @@
wps_build_cred_auth_type(msg, cred) ||
wps_build_cred_encr_type(msg, cred) ||
wps_build_cred_network_key(msg, cred) ||
- wps_build_cred_mac_addr(msg, cred))
+ wps_build_mac_addr(msg, cred->mac_addr))
return -1;
return 0;
}
@@ -3296,7 +3284,7 @@
"unselect internal Registrar");
reg->selected_registrar = 0;
reg->pbc = 0;
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -3368,7 +3356,8 @@
* This function is called when selected registrar state changes, e.g., when an
* AP receives a SetSelectedRegistrar UPnP message.
*/
-void wps_registrar_selected_registrar_changed(struct wps_registrar *reg)
+void wps_registrar_selected_registrar_changed(struct wps_registrar *reg,
+ u16 dev_pw_id)
{
wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed");
@@ -3392,7 +3381,8 @@
reg->sel_reg_dev_password_id_override =
DEV_PW_PUSHBUTTON;
wps_set_pushbutton(&methods, reg->wps->config_methods);
- }
+ } else if (dev_pw_id)
+ reg->sel_reg_dev_password_id_override = dev_pw_id;
wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected "
"(pbc=%d)", reg->pbc);
reg->sel_reg_config_methods_override = methods;
@@ -3514,12 +3504,15 @@
reg->pbc = 0;
wps_registrar_add_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, pw_id);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
wps_registrar_set_selected_timeout,
reg, NULL);
+ wpa_printf(MSG_DEBUG, "WPS: Added NFC Device Password %u to Registrar",
+ pw_id);
+
return 0;
}
@@ -3561,7 +3554,7 @@
{
wps_registrar_remove_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
#endif /* CONFIG_WPS_NFC */
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index 09a46a2..af63e4d 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -322,11 +322,9 @@
url_len -= 7;
/* Make a copy of the string to allow modification during parsing */
- scratch_mem = os_malloc(url_len + 1);
+ scratch_mem = dup_binstr(url, url_len);
if (scratch_mem == NULL)
goto fail;
- os_memcpy(scratch_mem, url, url_len);
- scratch_mem[url_len] = '\0';
wpa_printf(MSG_DEBUG, "WPS UPnP: Adding URL '%s'", scratch_mem);
host = scratch_mem;
path = os_strchr(host, '/');
diff --git a/src/wps/wps_upnp_ap.c b/src/wps/wps_upnp_ap.c
index 54ed98f..4f1dd8f 100644
--- a/src/wps/wps_upnp_ap.c
+++ b/src/wps/wps_upnp_ap.c
@@ -22,7 +22,7 @@
struct wps_registrar *reg = timeout_ctx;
wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar from ER timed out");
s->selected_registrar = 0;
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
@@ -71,7 +71,7 @@
upnp_er_set_selected_timeout, s, reg);
}
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
return 0;
}
@@ -83,5 +83,5 @@
s->selected_registrar = 0;
eloop_cancel_timeout(upnp_er_set_selected_timeout, s, reg);
if (reg)
- wps_registrar_selected_registrar_changed(reg);
+ wps_registrar_selected_registrar_changed(reg, 0);
}
diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h
index 7f3c561..5c39f7e 100644
--- a/src/wps/wps_upnp_i.h
+++ b/src/wps/wps_upnp_i.h
@@ -171,7 +171,7 @@
int ssdp_listener_start(struct upnp_wps_device_sm *sm);
int ssdp_listener_open(void);
int add_ssdp_network(const char *net_if);
-int ssdp_open_multicast_sock(u32 ip_addr);
+int ssdp_open_multicast_sock(u32 ip_addr, const char *forced_ifname);
int ssdp_open_multicast(struct upnp_wps_device_sm *sm);
/* wps_upnp_web.c */
diff --git a/src/wps/wps_upnp_ssdp.c b/src/wps/wps_upnp_ssdp.c
index 17a8207..416961c 100644
--- a/src/wps/wps_upnp_ssdp.c
+++ b/src/wps/wps_upnp_ssdp.c
@@ -3,7 +3,7 @@
* Copyright (c) 2000-2003 Intel Corporation
* Copyright (c) 2006-2007 Sony Corporation
* Copyright (c) 2008-2009 Atheros Communications
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi>
*
* See wps_upnp.c for more details on licensing and code history.
*/
@@ -13,6 +13,9 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/route.h>
+#ifdef __linux__
+#include <net/if.h>
+#endif /* __linux__ */
#include "common.h"
#include "uuid.h"
@@ -854,7 +857,7 @@
}
-int ssdp_open_multicast_sock(u32 ip_addr)
+int ssdp_open_multicast_sock(u32 ip_addr, const char *forced_ifname)
{
int sd;
/* per UPnP-arch-DeviceArchitecture, 1. Discovery, keep IP packet
@@ -865,6 +868,22 @@
if (sd < 0)
return -1;
+ if (forced_ifname) {
+#ifdef __linux__
+ struct ifreq req;
+ os_memset(&req, 0, sizeof(req));
+ os_strlcpy(req.ifr_name, forced_ifname, sizeof(req.ifr_name));
+ if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, &req,
+ sizeof(req)) < 0) {
+ wpa_printf(MSG_INFO, "WPS UPnP: Failed to bind "
+ "multicast socket to ifname %s: %s",
+ forced_ifname, strerror(errno));
+ close(sd);
+ return -1;
+ }
+#endif /* __linux__ */
+ }
+
#if 0 /* maybe ok if we sometimes block on writes */
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) {
close(sd);
@@ -924,7 +943,7 @@
*/
int ssdp_open_multicast(struct upnp_wps_device_sm *sm)
{
- sm->multicast_sd = ssdp_open_multicast_sock(sm->ip_addr);
+ sm->multicast_sd = ssdp_open_multicast_sock(sm->ip_addr, NULL);
if (sm->multicast_sd < 0)
return -1;
return 0;
diff --git a/src/wps/wps_upnp_web.c b/src/wps/wps_upnp_web.c
index ce0bede..11386d8 100644
--- a/src/wps/wps_upnp_web.c
+++ b/src/wps/wps_upnp_web.c
@@ -996,13 +996,11 @@
h++;
len = end - h;
os_free(callback_urls);
- callback_urls = os_malloc(len + 1);
+ callback_urls = dup_binstr(h, len);
if (callback_urls == NULL) {
ret = HTTP_INTERNAL_SERVER_ERROR;
goto error;
}
- os_memcpy(callback_urls, h, len);
- callback_urls[len] = 0;
continue;
}
/* SID is only for renewal */