Fix capwap protocol and optional wireless information header.
Complete IEEE802.11 frames tunnel WTP side. Now WTP can send data packets to the AC.
This commit is contained in:
parent
67daa8dcbb
commit
089a044f3f
@ -12,6 +12,7 @@ application: {
|
||||
binding = "802.11";
|
||||
|
||||
tunnelmode: {
|
||||
dataframe = "usermode";
|
||||
nativeframe = false;
|
||||
ethframe = false;
|
||||
localbridging = true;
|
||||
|
@ -202,7 +202,7 @@ void capwap_header_init(struct capwap_header_data* data, unsigned short radioid,
|
||||
}
|
||||
|
||||
/* */
|
||||
void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, char* macaddress) {
|
||||
void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, const uint8_t* macaddress) {
|
||||
struct capwap_header* header;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
@ -288,6 +288,7 @@ void capwap_header_set_wireless_information(struct capwap_header_data* data, voi
|
||||
|
||||
/* Remove old wireless information */
|
||||
if (IS_FLAG_W_HEADER(header)) {
|
||||
SET_FLAG_W_HEADER(header, 0);
|
||||
SET_HLEN_HEADER(header, size);
|
||||
}
|
||||
|
||||
@ -308,6 +309,7 @@ void capwap_header_set_wireless_information(struct capwap_header_data* data, voi
|
||||
|
||||
/* Update size */
|
||||
size += lengthpadded;
|
||||
SET_FLAG_W_HEADER(header, 1);
|
||||
SET_HLEN_HEADER(header, size);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ struct capwap_header_data {
|
||||
};
|
||||
|
||||
void capwap_header_init(struct capwap_header_data* data, unsigned short radioid, unsigned short binding);
|
||||
void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, char* macaddress);
|
||||
void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, const uint8_t* macaddress);
|
||||
void capwap_header_set_wireless_information(struct capwap_header_data* data, void* buffer, unsigned char length);
|
||||
void capwap_header_set_keepalive_flag(struct capwap_header_data* data, int enable);
|
||||
void capwap_header_set_nativeframe_flag(struct capwap_header_data* data, int enable);
|
||||
|
@ -71,20 +71,27 @@ struct capwap_header {
|
||||
/* Mac Address */
|
||||
struct capwap_mac_address {
|
||||
uint8_t length;
|
||||
int8_t address[0];
|
||||
uint8_t address[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Wireless Information */
|
||||
struct capwap_wireless_information {
|
||||
uint8_t length;
|
||||
int8_t data[0];
|
||||
uint8_t data[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* IEEE802.11 Wireless Information */
|
||||
struct capwap_ieee80211_frame_info {
|
||||
uint8_t rssi;
|
||||
uint8_t snr;
|
||||
uint16_t rate;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Message element */
|
||||
struct capwap_message_element {
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
int8_t data[0];
|
||||
uint8_t data[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Control Message Type */
|
||||
@ -132,7 +139,7 @@ struct capwap_control_message {
|
||||
uint8_t seq;
|
||||
uint16_t length;
|
||||
uint8_t flags;
|
||||
int8_t elements[0];
|
||||
uint8_t elements[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Data Message Keep-Alive*/
|
||||
@ -140,11 +147,11 @@ struct capwap_control_message {
|
||||
|
||||
struct capwap_data_message {
|
||||
uint16_t length;
|
||||
int8_t elements[0];
|
||||
uint8_t elements[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
/* Capwap dtls header helper */
|
||||
#define GET_DTLS_BODY(x) (void*)(((int8_t*)(x)) + sizeof(struct capwap_dtls_header))
|
||||
#define GET_DTLS_BODY(x) (void*)(((uint8_t*)(x)) + sizeof(struct capwap_dtls_header))
|
||||
|
||||
/* Capwap header helper */
|
||||
#define GET_VERSION_HEADER(x) ((x)->preamble.version)
|
||||
@ -182,9 +189,9 @@ struct capwap_data_message {
|
||||
#define GET_FRAGMENT_OFFSET_HEADER(x) (ntohs((x)->frag_off) & FRAGMENT_OFFSET_MASK)
|
||||
#define SET_FRAGMENT_OFFSET_HEADER(x, y) ((x)->frag_off &= ~FRAGMENT_OFFSET_MASK, (x)->frag_off |= htons((uint16_t)(y) & FRAGMENT_OFFSET_MASK))
|
||||
|
||||
#define GET_RADIO_MAC_ADDRESS_STRUCT(x) ((struct capwap_mac_address*)(((int8_t*)(x)) + sizeof(struct capwap_header)))
|
||||
#define GET_WIRELESS_INFORMATION_STRUCT(x) ((struct capwap_wireless_information*)(((int8_t*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0)))
|
||||
#define GET_PAYLOAD_HEADER(x) ((void*)(((int8_t*)(x)) + GET_HLEN_HEADER(x) * 4))
|
||||
#define GET_RADIO_MAC_ADDRESS_STRUCT(x) ((struct capwap_mac_address*)(((uint8_t*)(x)) + sizeof(struct capwap_header)))
|
||||
#define GET_WIRELESS_INFORMATION_STRUCT(x) ((struct capwap_wireless_information*)(((uint8_t*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0)))
|
||||
#define GET_PAYLOAD_HEADER(x) ((void*)(((uint8_t*)(x)) + GET_HLEN_HEADER(x) * 4))
|
||||
|
||||
#define IS_SEQUENCE_SMALLER(s1, s2) (((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0)
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/err.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include "nlsmartcapwap.h"
|
||||
#include "netlinkapp.h"
|
||||
|
||||
@ -13,6 +14,7 @@ struct nlsmartcapwap_device {
|
||||
struct list_head list;
|
||||
struct ieee80211_pcktunnel pcktunnel_handler;
|
||||
|
||||
u32 usermodeid;
|
||||
u32 ifindex;
|
||||
u32 flags;
|
||||
};
|
||||
@ -46,49 +48,56 @@ static struct genl_family nlsmartcapwap_family = {
|
||||
|
||||
/* */
|
||||
static int nlsmartcapwap_handler(u32 ifindex, struct sk_buff* skb, int sig_dbm, unsigned char rate, void* data) {
|
||||
int result = 0;
|
||||
int frame8023 = 0;
|
||||
struct nlsmartcapwap_device* nldev = (struct nlsmartcapwap_device*)data;
|
||||
struct ieee80211_hdr* hdr = (struct ieee80211_hdr*)skb->data;
|
||||
|
||||
/* Check source network */
|
||||
if (ifindex == nldev->ifindex) {
|
||||
if (nldev->flags & SMARTCAPWAP_FLAGS_SEND_USERSPACE) {
|
||||
void* msg;
|
||||
struct sk_buff* sk_msg;
|
||||
/* IEEE802.11 Data Packet */
|
||||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
if ((nldev->flags & SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME) && ieee80211_is_data_present(hdr->frame_control)) {
|
||||
result = -1;
|
||||
}
|
||||
|
||||
/* Alloc message */
|
||||
sk_msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||
if (sk_msg) {
|
||||
/* Set command */
|
||||
msg = genlmsg_put(sk_msg, 0, 0, &nlsmartcapwap_family, 0, NLSMARTCAPWAP_CMD_FRAME);
|
||||
if (msg) {
|
||||
/* Set params */
|
||||
if (nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_IFINDEX, nldev->ifindex) ||
|
||||
nla_put(sk_msg, NLSMARTCAPWAP_ATTR_FRAME, skb->len, skb->data) ||
|
||||
(sig_dbm && nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM, (u32)sig_dbm)) ||
|
||||
(rate && nla_put_u8(sk_msg, NLSMARTCAPWAP_ATTR_RX_RATE, (u8)rate))) {
|
||||
/* Convert IEEE802.11 to IEEE802.3 */
|
||||
if (nldev->flags & SMARTCAPWAP_FLAGS_TUNNEL_8023) {
|
||||
frame8023 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Abort message */
|
||||
genlmsg_cancel(sk_msg, msg);
|
||||
nlmsg_free(sk_msg);
|
||||
} else {
|
||||
/* Send message */
|
||||
genlmsg_end(sk_msg, msg);
|
||||
genlmsg_unicast(&init_net, sk_msg, nlsmartcapwap_usermodeid);
|
||||
}
|
||||
} else {
|
||||
/* */
|
||||
if (nldev->flags & SMARTCAPWAP_FLAGS_SEND_USERSPACE) {
|
||||
void* msg;
|
||||
struct sk_buff* sk_msg;
|
||||
|
||||
/* Alloc message */
|
||||
sk_msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||
if (sk_msg) {
|
||||
/* Set command */
|
||||
msg = genlmsg_put(sk_msg, 0, 0, &nlsmartcapwap_family, 0, NLSMARTCAPWAP_CMD_FRAME);
|
||||
if (msg) {
|
||||
/* Set params */
|
||||
if (nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_IFINDEX, nldev->ifindex) ||
|
||||
nla_put(sk_msg, NLSMARTCAPWAP_ATTR_FRAME, skb->len, skb->data) ||
|
||||
(frame8023 && nla_put_flag(sk_msg, NLSMARTCAPWAP_ATTR_8023_FRAME)) ||
|
||||
(sig_dbm && nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM, (u32)sig_dbm)) ||
|
||||
(rate && nla_put_u8(sk_msg, NLSMARTCAPWAP_ATTR_RX_RATE, (u8)rate))) {
|
||||
|
||||
/* Abort message */
|
||||
genlmsg_cancel(sk_msg, msg);
|
||||
nlmsg_free(sk_msg);
|
||||
} else {
|
||||
/* Send message */
|
||||
genlmsg_end(sk_msg, msg);
|
||||
genlmsg_unicast(&init_net, sk_msg, nldev->usermodeid);
|
||||
}
|
||||
} else {
|
||||
nlmsg_free(sk_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if block all IEEE802.11 Data Packet */
|
||||
if ((nldev->flags & SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME) &&
|
||||
((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -254,6 +263,9 @@ static int nlsmartcapwap_join_mac80211_device(struct sk_buff* skb, struct genl_i
|
||||
nldev->pcktunnel_handler.subtype_mask[2] = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK]);
|
||||
}
|
||||
|
||||
/* */
|
||||
nldev->usermodeid = genl_info_snd_portid(info);
|
||||
|
||||
/* Connect device to mac80211 */
|
||||
ret = ieee80211_pcktunnel_register(ifindex, &nldev->pcktunnel_handler);
|
||||
if (ret) {
|
||||
@ -289,6 +301,7 @@ static const struct nla_policy nlsmartcapwap_policy[NLSMARTCAPWAP_ATTR_MAX + 1]
|
||||
[NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK] = { .type = NLA_U16 },
|
||||
[NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK] = { .type = NLA_U16 },
|
||||
[NLSMARTCAPWAP_ATTR_FRAME] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN },
|
||||
[NLSMARTCAPWAP_ATTR_8023_FRAME] = { .type = NLA_FLAG },
|
||||
[NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM] = { .type = NLA_U32 },
|
||||
[NLSMARTCAPWAP_ATTR_RX_RATE] = { .type = NLA_U8 },
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
/* */
|
||||
#define SMARTCAPWAP_FLAGS_SEND_USERSPACE 0x00000001
|
||||
#define SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME 0x00000002
|
||||
#define SMARTCAPWAP_FLAGS_TUNNEL_8023 0x00000004
|
||||
|
||||
/* */
|
||||
enum nlsmartcapwap_attrs {
|
||||
@ -21,6 +22,7 @@ enum nlsmartcapwap_attrs {
|
||||
NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK,
|
||||
|
||||
NLSMARTCAPWAP_ATTR_FRAME,
|
||||
NLSMARTCAPWAP_ATTR_8023_FRAME,
|
||||
NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM,
|
||||
NLSMARTCAPWAP_ATTR_RX_RATE,
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
#include "capwap.h"
|
||||
#include "wtp.h"
|
||||
#include "capwap_list.h"
|
||||
#include "capwap_element.h"
|
||||
#include "capwap_network.h"
|
||||
#include "wifi_drivers.h"
|
||||
#include "wtp.h"
|
||||
#include "wtp_radio.h"
|
||||
|
||||
/* Declare enable wifi driver */
|
||||
@ -316,7 +314,7 @@ static void wifi_wlan_send_mgmt_deauthentication(struct wifi_wlan* wlan, const u
|
||||
capwap_logging_info("Sent IEEE802.11 Deuthentication to %s station", stationaddress);
|
||||
|
||||
/* Forwards the station deauthentication also to AC */
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, (struct ieee80211_header_mgmt*)g_bufferIEEE80211, responselength);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)g_bufferIEEE80211, responselength, 1, 0, 0, 0);
|
||||
} else {
|
||||
capwap_logging_warning("Unable to send IEEE802.11 Deuthentication to %s station", stationaddress);
|
||||
}
|
||||
@ -421,7 +419,7 @@ static void wifi_wlan_receive_station_mgmt_probe_request(struct wifi_wlan* wlan,
|
||||
if (!wlan->device->instance->ops->wlan_sendframe(wlan, g_bufferIEEE80211, responselength, wlan->device->currentfrequency.frequency, 0, 0, 0, nowaitack)) {
|
||||
/* If enable Split Mac send the probe request message to AC */
|
||||
if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate);
|
||||
}
|
||||
} else {
|
||||
capwap_logging_warning("Unable to send IEEE802.11 Probe Response");
|
||||
@ -585,10 +583,10 @@ static void wifi_wlan_receive_station_mgmt_authentication(struct wifi_wlan* wlan
|
||||
capwap_logging_info("Sent IEEE802.11 Authentication Response to %s station with %d status code", stationaddress, (int)responsestatuscode);
|
||||
|
||||
/* Notify authentication request message also to AC */
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate);
|
||||
|
||||
/* Forwards the authentication response message also to AC */
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, (struct ieee80211_header_mgmt*)g_bufferIEEE80211, responselength);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)g_bufferIEEE80211, responselength, 1, 0, 0, 0);
|
||||
} else if (station) {
|
||||
capwap_logging_warning("Unable to send IEEE802.11 Authentication Response to %s station", stationaddress);
|
||||
wifi_station_delete(station);
|
||||
@ -598,7 +596,7 @@ static void wifi_wlan_receive_station_mgmt_authentication(struct wifi_wlan* wlan
|
||||
wifi_station_delete(station);
|
||||
}
|
||||
} else if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -684,10 +682,10 @@ static void wifi_wlan_receive_station_mgmt_association_request(struct wifi_wlan*
|
||||
capwap_logging_info("Sent IEEE802.11 Association Response to %s station with %d status code", station->addrtext, (int)resultstatuscode);
|
||||
|
||||
/* Notify association request message also to AC */
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate);
|
||||
|
||||
/* Forwards the association response message also to AC */
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, (struct ieee80211_header_mgmt*)g_bufferIEEE80211, responselength);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)g_bufferIEEE80211, responselength, 1, 0, 0, 0);
|
||||
} else {
|
||||
capwap_logging_warning("Unable to send IEEE802.11 Association Response to %s station", station->addrtext);
|
||||
wifi_wlan_deauthentication_station(wlan, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID, 0);
|
||||
@ -697,7 +695,7 @@ static void wifi_wlan_receive_station_mgmt_association_request(struct wifi_wlan*
|
||||
wifi_wlan_deauthentication_station(wlan, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID, 0);
|
||||
}
|
||||
} else if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate);
|
||||
|
||||
/* Station information */
|
||||
station->capability = __le16_to_cpu(frame->associationresponse.capability);
|
||||
@ -731,7 +729,7 @@ static void wifi_wlan_receive_station_mgmt_disassociation(struct wifi_wlan* wlan
|
||||
/* TODO */
|
||||
|
||||
/* Notify disassociation message also to AC */
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate);
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -752,7 +750,7 @@ static void wifi_wlan_receive_station_mgmt_deauthentication(struct wifi_wlan* wl
|
||||
}
|
||||
|
||||
/* Notify deauthentication message also to AC */
|
||||
wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length);
|
||||
wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate);
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -1580,6 +1578,9 @@ void wifi_wlan_receive_station_frame(struct wifi_wlan* wlan, const struct ieee80
|
||||
uint16_t framecontrol_type;
|
||||
uint16_t framecontrol_subtype;
|
||||
|
||||
ASSERT(wlan != NULL);
|
||||
ASSERT(wlan->handle != NULL);
|
||||
|
||||
/* Check frame */
|
||||
if (!frame || (length < sizeof(struct ieee80211_header))) {
|
||||
return;
|
||||
@ -1602,6 +1603,9 @@ void wifi_wlan_receive_station_ackframe(struct wifi_wlan* wlan, const struct iee
|
||||
uint16_t framecontrol_type;
|
||||
uint16_t framecontrol_subtype;
|
||||
|
||||
ASSERT(wlan != NULL);
|
||||
ASSERT(wlan->handle != NULL);
|
||||
|
||||
/* Check frame */
|
||||
if (!frame || (length < sizeof(struct ieee80211_header))) {
|
||||
return;
|
||||
@ -1625,6 +1629,9 @@ void wifi_wlan_receive_ac_frame(struct wifi_wlan* wlan, struct ieee80211_header*
|
||||
uint16_t framecontrol_type;
|
||||
uint16_t framecontrol_subtype;
|
||||
|
||||
ASSERT(wlan != NULL);
|
||||
ASSERT(wlan->handle != NULL);
|
||||
|
||||
/* Check frame */
|
||||
if (!frame || (length < sizeof(struct ieee80211_header))) {
|
||||
return;
|
||||
@ -1647,6 +1654,19 @@ void wifi_wlan_receive_ac_frame(struct wifi_wlan* wlan, struct ieee80211_header*
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_wlan_send_frame(struct wifi_wlan* wlan, const uint8_t* data, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate) {
|
||||
ASSERT(wlan != NULL);
|
||||
ASSERT(wlan->handle != NULL);
|
||||
|
||||
if (!data || (length <= 0) || !wlan->send_frame) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
return wlan->send_frame(wlan->send_frame_to_ac_cbparam, data, length, nativeframe, rssi, snr, rate, wlan->address, MACADDRESS_EUI48_LENGTH);
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_station_authorize(struct wifi_wlan* wlan, struct station_add_params* params) {
|
||||
int result;
|
||||
|
@ -87,7 +87,7 @@ struct device_setconfiguration_params {
|
||||
};
|
||||
|
||||
/* */
|
||||
typedef void (*send_frame_to_ac)(void* param, const struct ieee80211_header_mgmt* mgmt, int mgmtlength);
|
||||
typedef int (*send_frame_to_ac)(void* param, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype);
|
||||
|
||||
struct wlan_startap_params {
|
||||
send_frame_to_ac send_frame;
|
||||
@ -409,6 +409,7 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params
|
||||
void wifi_wlan_stopap(struct wifi_wlan* wlan);
|
||||
int wifi_wlan_getbssid(struct wifi_wlan* wlan, uint8_t* bssid);
|
||||
uint16_t wifi_wlan_check_capability(struct wifi_wlan* wlan, uint16_t capability);
|
||||
int wifi_wlan_send_frame(struct wifi_wlan* wlan, const uint8_t* data, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate);
|
||||
void wifi_wlan_destroy(struct wifi_wlan* wlan);
|
||||
|
||||
/* WLAN packet management */
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include "capwap.h"
|
||||
#include "wtp.h"
|
||||
#include "capwap_array.h"
|
||||
#include "capwap_list.h"
|
||||
#include "capwap_element.h"
|
||||
#include "capwap_network.h"
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
#include <netlink/genl/ctrl.h>
|
||||
@ -371,11 +370,9 @@ static int nl80211_wlan_event(struct wifi_wlan* wlan, struct genlmsghdr* gnlh, s
|
||||
if (tb_msg[NL80211_ATTR_FRAME]) {
|
||||
uint32_t frequency = (tb_msg[NL80211_ATTR_WIPHY_FREQ] ? nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]) : 0);
|
||||
uint8_t rssi = (tb_msg[NL80211_ATTR_RX_SIGNAL_DBM] ? (uint8_t)nla_get_u32(tb_msg[NL80211_ATTR_RX_SIGNAL_DBM]) : 0);
|
||||
uint8_t snr = 0;
|
||||
uint16_t rate = 0;
|
||||
|
||||
/* */
|
||||
wifi_wlan_receive_station_frame(wlan, (struct ieee80211_header*)nla_data(tb_msg[NL80211_ATTR_FRAME]), nla_len(tb_msg[NL80211_ATTR_FRAME]), frequency, rssi, snr, rate);
|
||||
wifi_wlan_receive_station_frame(wlan, (struct ieee80211_header*)nla_data(tb_msg[NL80211_ATTR_FRAME]), nla_len(tb_msg[NL80211_ATTR_FRAME]), frequency, rssi, 0, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -799,15 +796,26 @@ static int nl80211_wlan_startap(struct wifi_wlan* wlan) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
if (wlan->tunnelmode != CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL) {
|
||||
/* Join interface to kernel module */
|
||||
if ((g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_KERNELMODE) || (g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_USERMODE)) {
|
||||
uint32_t mode = ((g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_KERNELMODE) ? WTP_KMOD_MODE_TUNNEL_KERNELMODE : WTP_KMOD_MODE_TUNNEL_USERMODE);
|
||||
uint32_t flags = ((wlan->tunnelmode == CAPWAP_ADD_WLAN_TUNNELMODE_80211) ? WTP_KMOD_FLAGS_TUNNEL_NATIVE : WTP_KMOD_FLAGS_TUNNEL_8023);
|
||||
|
||||
if (!wtp_kmod_join_mac80211_device(wlan, mode, flags)) {
|
||||
capwap_logging_info("Joined in kernel mode the interface %d", wlan->virtindex);
|
||||
}
|
||||
} else {
|
||||
capwap_logging_warning("Tunneling is not supported for interface %d", wlan->virtindex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable operation status */
|
||||
wlan->flags |= WIFI_WLAN_OPERSTATE_RUNNING;
|
||||
netlink_set_link_status(wlanhandle->devicehandle->globalhandle->netlinkhandle, wlan->virtindex, -1, IF_OPER_UP);
|
||||
|
||||
/* */
|
||||
if (!wtp_kmod_join_mac80211_device(wlan->virtindex)) {
|
||||
capwap_logging_info("Joined in kernel mode the interface %d", wlan->virtindex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -822,6 +830,14 @@ static void nl80211_wlan_stopap(struct wifi_wlan* wlan) {
|
||||
/* */
|
||||
wlanhandle = (struct nl80211_wlan_handle*)wlan->handle;
|
||||
|
||||
/* */
|
||||
if (wlan->tunnelmode != CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL) {
|
||||
/* Leave interface from kernel module */
|
||||
if ((g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_KERNELMODE) || (g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_USERMODE)) {
|
||||
wtp_kmod_leave_mac80211_device(wlan);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
if (wlan->flags & WIFI_WLAN_SET_BEACON) {
|
||||
msg = nlmsg_alloc();
|
||||
|
@ -62,6 +62,7 @@ static int wtp_init(void) {
|
||||
|
||||
g_wtp.mactype.type = CAPWAP_LOCALMAC;
|
||||
g_wtp.mactunnel.mode = CAPWAP_WTP_LOCAL_BRIDGING;
|
||||
g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_KERNELMODE;
|
||||
|
||||
/* DTLS */
|
||||
g_wtp.validdtlsdatapolicy = CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED;
|
||||
@ -650,6 +651,19 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||
g_wtp.mactunnel.mode |= CAPWAP_WTP_LOCAL_BRIDGING;
|
||||
}
|
||||
}
|
||||
|
||||
if (config_lookup_string(config, "application.tunnelmode.dataframe", &configString) == CONFIG_TRUE) {
|
||||
if (!strcmp(configString, "none")) {
|
||||
g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_NONE;
|
||||
} else if (!strcmp(configString, "kernelmode")) {
|
||||
g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_KERNELMODE;
|
||||
} else if (!strcmp(configString, "usermode")) {
|
||||
g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_USERMODE;
|
||||
} else {
|
||||
capwap_logging_error("Invalid configuration file, unknown application.tunnelmode.dataframe value");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set mactype of WTP */
|
||||
|
@ -42,6 +42,10 @@
|
||||
|
||||
#define WTP_INIT_REMOTE_SEQUENCE 0xff
|
||||
|
||||
#define WTP_TUNNEL_DATA_FRAME_NONE 0x00000000
|
||||
#define WTP_TUNNEL_DATA_FRAME_KERNELMODE 0x00000001
|
||||
#define WTP_TUNNEL_DATA_FRAME_USERMODE 0x00000002
|
||||
|
||||
/* */
|
||||
struct wtp_fds {
|
||||
int fdstotalcount;
|
||||
@ -109,6 +113,8 @@ struct wtp_t {
|
||||
struct capwap_statisticstimer_element statisticstimer;
|
||||
struct capwap_wtprebootstat_element rebootstat;
|
||||
|
||||
int tunneldataframe;
|
||||
|
||||
struct capwap_packet_rxmng* rxmngctrlpacket;
|
||||
struct capwap_packet_rxmng* rxmngdatapacket;
|
||||
|
||||
|
@ -69,6 +69,6 @@ void wtp_dfa_state_reset(void);
|
||||
|
||||
/* */
|
||||
void wtp_ieee80211_packet(uint8_t radioid, const struct ieee80211_header* header, int length);
|
||||
void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe);
|
||||
int wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype);
|
||||
|
||||
#endif /* __WTP_DFA_HEADER__ */
|
||||
|
@ -251,22 +251,45 @@ static void send_data_keepalive_request() {
|
||||
}
|
||||
|
||||
/* */
|
||||
void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe) {
|
||||
int wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype) {
|
||||
int result;
|
||||
struct capwap_list* txfragpacket;
|
||||
struct capwap_header_data capwapheader;
|
||||
struct capwap_packet_txmng* txmngpacket;
|
||||
|
||||
ASSERT(IS_VALID_RADIOID(radioid));
|
||||
ASSERT(IS_VALID_WLANID(wlanid));
|
||||
ASSERT(frame != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
/* Check for IEEE 802.3 frame */
|
||||
if (!nativeframe && (!bssaddress || (bssaddresstype == MACADDRESS_NONE_LENGTH))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Build packet */
|
||||
capwap_header_init(&capwapheader, radioid, g_wtp.binding);
|
||||
capwap_header_set_nativeframe_flag(&capwapheader, (leavenativeframe ? 1: 0));
|
||||
capwap_header_set_nativeframe_flag(&capwapheader, (nativeframe ? 1: 0));
|
||||
|
||||
/* Set radio macaddress */
|
||||
if (!nativeframe) {
|
||||
capwap_header_set_radio_macaddress(&capwapheader, bssaddresstype, bssaddress);
|
||||
}
|
||||
|
||||
/* Set wireless information */
|
||||
if (rssi || snr || rate) {
|
||||
struct capwap_ieee80211_frame_info frameinfo;
|
||||
|
||||
frameinfo.rssi = rssi;
|
||||
frameinfo.snr = snr;
|
||||
frameinfo.rate = htons(rate);
|
||||
capwap_header_set_wireless_information(&capwapheader, &frameinfo, sizeof(struct capwap_ieee80211_frame_info));
|
||||
}
|
||||
|
||||
txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, g_wtp.mtu);
|
||||
|
||||
/* */
|
||||
if (leavenativeframe) {
|
||||
capwap_packet_txmng_add_data(txmngpacket, data, (unsigned short)length);
|
||||
} else {
|
||||
/* TODO */
|
||||
}
|
||||
capwap_packet_txmng_add_data(txmngpacket, frame, (unsigned short)length);
|
||||
|
||||
/* Data message complete, get fragment packets into local list */
|
||||
txfragpacket = capwap_list_create();
|
||||
@ -275,13 +298,17 @@ void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data,
|
||||
g_wtp.fragmentid++;
|
||||
}
|
||||
|
||||
if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txfragpacket, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress)) {
|
||||
/* */
|
||||
result = capwap_crypt_sendto_fragmentpacket(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txfragpacket, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress);
|
||||
if (!result) {
|
||||
capwap_logging_debug("Warning: error to send data packet");
|
||||
}
|
||||
|
||||
/* Free packets manager */
|
||||
capwap_list_free(txfragpacket);
|
||||
capwap_packet_txmng_free(txmngpacket);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
@ -81,6 +81,33 @@ static int wtp_kmod_ack_handler(struct nl_msg* msg, void* arg) {
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int wtp_kmod_event_handler(struct genlmsghdr* gnlh, struct nlattr** tb_msg, void* data) {
|
||||
switch (gnlh->cmd) {
|
||||
case NLSMARTCAPWAP_CMD_FRAME: {
|
||||
struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)data;
|
||||
|
||||
if (tb_msg[NLSMARTCAPWAP_ATTR_FRAME]) {
|
||||
uint32_t sig_dbm = (tb_msg[NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM] ? nla_get_u32(tb_msg[NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM]) : 0);
|
||||
uint16_t rate = (tb_msg[NLSMARTCAPWAP_ATTR_RX_RATE] ? ((uint16_t)nla_get_u8(tb_msg[NLSMARTCAPWAP_ATTR_RX_RATE])) * 5 : 0); /* Convert rate 500Kbps to 100Kbps */
|
||||
int nativeframe = (tb_msg[SMARTCAPWAP_FLAGS_TUNNEL_8023] ? 0 : 1);
|
||||
|
||||
/* Forwards the frame to AC */
|
||||
wifi_wlan_send_frame(interface->wlan, (uint8_t*)nla_data(tb_msg[NLSMARTCAPWAP_ATTR_FRAME]), nla_len(tb_msg[NLSMARTCAPWAP_ATTR_FRAME]), nativeframe, (uint8_t)sig_dbm, 0, rate);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
capwap_logging_debug("*** wtp_kmod_event_handler: %d", (int)gnlh->cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int wtp_kmod_valid_handler(struct nl_msg* msg, void* data) {
|
||||
struct nlattr* tb_msg[NLSMARTCAPWAP_ATTR_MAX + 1];
|
||||
@ -88,7 +115,7 @@ static int wtp_kmod_valid_handler(struct nl_msg* msg, void* data) {
|
||||
|
||||
nla_parse(tb_msg, NLSMARTCAPWAP_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
|
||||
|
||||
return NL_SKIP;
|
||||
return wtp_kmod_event_handler(gnlh, tb_msg, data);
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -177,12 +204,122 @@ static void wtp_kmod_event_receive(int fd, void** params, int paramscount) {
|
||||
}
|
||||
|
||||
/* */
|
||||
int wtp_kmod_join_mac80211_device(uint32_t ifindex) {
|
||||
int wtp_kmod_join_mac80211_device(struct wifi_wlan* wlan, uint32_t mode, uint32_t flags) {
|
||||
int result;
|
||||
struct nl_sock* nl;
|
||||
struct nl_cb* nl_cb;
|
||||
struct nl_msg* msg;
|
||||
struct capwap_list_item* itemlist;
|
||||
struct wtp_kmod_iface_handle* interface;
|
||||
uint32_t kmodflags = 0;
|
||||
uint16_t subtype_mgmt = 0;
|
||||
uint16_t subtype_ctrl = 0;
|
||||
uint16_t subtype_data = 0;
|
||||
|
||||
ASSERT(wlan != NULL);
|
||||
|
||||
/* */
|
||||
if (!wtp_kmod_isconnected()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
itemlist = capwap_itemlist_create(sizeof(struct wtp_kmod_iface_handle));
|
||||
interface = (struct wtp_kmod_iface_handle*)itemlist->item;
|
||||
|
||||
/* Socket management */
|
||||
nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
|
||||
if (!nl_cb) {
|
||||
capwap_itemlist_free(itemlist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nl_cb_set(nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, wtp_kmod_no_seq_check, NULL);
|
||||
nl_cb_set(nl_cb, NL_CB_VALID, NL_CB_CUSTOM, wtp_kmod_valid_handler, (void*)interface);
|
||||
|
||||
nl = nl_create_handle(nl_cb);
|
||||
if (!nl) {
|
||||
nl_cb_put(nl_cb);
|
||||
capwap_itemlist_free(itemlist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg) {
|
||||
nl_socket_free(nl);
|
||||
nl_cb_put(nl_cb);
|
||||
capwap_itemlist_free(itemlist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set flags */
|
||||
switch (mode) {
|
||||
case WTP_KMOD_MODE_LOCAL: {
|
||||
break;
|
||||
}
|
||||
|
||||
case WTP_KMOD_MODE_TUNNEL_USERMODE: {
|
||||
kmodflags |= SMARTCAPWAP_FLAGS_SEND_USERSPACE | SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME;
|
||||
subtype_data = 0xffff;
|
||||
|
||||
if (flags & WTP_KMOD_FLAGS_TUNNEL_8023) {
|
||||
kmodflags |= SMARTCAPWAP_FLAGS_TUNNEL_8023;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WTP_KMOD_MODE_TUNNEL_KERNELMODE: {
|
||||
kmodflags |= SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME;
|
||||
subtype_data = 0xffff;
|
||||
|
||||
if (flags & WTP_KMOD_FLAGS_TUNNEL_8023) {
|
||||
kmodflags |= SMARTCAPWAP_FLAGS_TUNNEL_8023;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_JOIN_MAC80211_DEVICE, 0);
|
||||
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFINDEX, wlan->virtindex);
|
||||
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_FLAGS, kmodflags);
|
||||
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_MGMT_SUBTYPE_MASK, subtype_mgmt);
|
||||
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK, subtype_ctrl);
|
||||
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK, subtype_data);
|
||||
|
||||
/* */
|
||||
result = wtp_kmod_send_and_recv(nl, nl_cb, msg, NULL, NULL);
|
||||
if (!result) {
|
||||
interface->nl = nl;
|
||||
interface->nl_fd = nl_socket_get_fd(nl);
|
||||
interface->nl_cb = nl_cb;
|
||||
interface->wlan = wlan;
|
||||
|
||||
/* */
|
||||
capwap_itemlist_insert_after(g_wtp.kmodhandle.interfaces, NULL, itemlist);
|
||||
} else {
|
||||
nl_socket_free(nl);
|
||||
nl_cb_put(nl_cb);
|
||||
capwap_itemlist_free(itemlist);
|
||||
}
|
||||
|
||||
/* */
|
||||
nlmsg_free(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
int wtp_kmod_leave_mac80211_device(struct wifi_wlan* wlan) {
|
||||
int result;
|
||||
struct nl_msg* msg;
|
||||
|
||||
ASSERT(wlan != NULL);
|
||||
|
||||
/* */
|
||||
if (!g_wtp.kmodhandle.nlsmartcapwap_id) {
|
||||
if (!wtp_kmod_isconnected()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -193,15 +330,26 @@ int wtp_kmod_join_mac80211_device(uint32_t ifindex) {
|
||||
}
|
||||
|
||||
/* */
|
||||
genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_JOIN_MAC80211_DEVICE, 0);
|
||||
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFINDEX, ifindex);
|
||||
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_FLAGS, SMARTCAPWAP_FLAGS_SEND_USERSPACE | SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME);
|
||||
nla_put_u16(msg, NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK, 0xffff);
|
||||
genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_LEAVE_MAC80211_DEVICE, 0);
|
||||
nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFINDEX, wlan->virtindex);
|
||||
|
||||
/* */
|
||||
result = wtp_kmod_send_and_recv_msg(msg, NULL, NULL);
|
||||
if (result) {
|
||||
capwap_logging_warning("Unable to join with interface: %d", ifindex);
|
||||
if (!result) {
|
||||
struct capwap_list_item* itemlist;
|
||||
|
||||
for (itemlist = g_wtp.kmodhandle.interfaces->first; itemlist != NULL; itemlist = itemlist->next) {
|
||||
struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)itemlist->item;
|
||||
|
||||
if (interface->wlan == wlan) {
|
||||
nl_socket_free(interface->nl);
|
||||
nl_cb_put(interface->nl_cb);
|
||||
|
||||
/* Free item */
|
||||
capwap_itemlist_free(capwap_itemlist_remove(g_wtp.kmodhandle.interfaces, itemlist));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -216,7 +364,9 @@ int wtp_kmod_isconnected(void) {
|
||||
|
||||
/* */
|
||||
int wtp_kmod_getfd(struct pollfd* fds, struct wtp_kmod_event* events, int count) {
|
||||
int kmodcount = (wtp_kmod_isconnected() ? 1 : 0);
|
||||
int i = 1;
|
||||
struct capwap_list_item* itemlist;
|
||||
int kmodcount = (wtp_kmod_isconnected() ? 1 + g_wtp.kmodhandle.interfaces->count : 0);
|
||||
|
||||
/* */
|
||||
if (!fds && !events && !count) {
|
||||
@ -237,6 +387,22 @@ int wtp_kmod_getfd(struct pollfd* fds, struct wtp_kmod_event* events, int count)
|
||||
events[0].params[1] = (void*)g_wtp.kmodhandle.nl_cb;
|
||||
events[0].paramscount = 2;
|
||||
|
||||
/* */
|
||||
for (itemlist = g_wtp.kmodhandle.interfaces->first; itemlist; i++, itemlist = itemlist->next) {
|
||||
struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)itemlist->item;
|
||||
|
||||
/* */
|
||||
fds[i].fd = interface->nl_fd;
|
||||
fds[i].events = POLLIN | POLLERR | POLLHUP;
|
||||
|
||||
/* */
|
||||
events[i].event_handler = wtp_kmod_event_receive;
|
||||
events[i].params[0] = (void*)interface->nl;
|
||||
events[i].params[1] = (void*)interface->nl_cb;
|
||||
events[i].paramscount = 2;
|
||||
}
|
||||
|
||||
ASSERT(kmodcount == i);
|
||||
return kmodcount;
|
||||
}
|
||||
|
||||
@ -279,11 +445,26 @@ int wtp_kmod_init(void) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
g_wtp.kmodhandle.interfaces = capwap_list_create();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
void wtp_kmod_free(void) {
|
||||
if (g_wtp.kmodhandle.interfaces) {
|
||||
while (g_wtp.kmodhandle.interfaces->first) {
|
||||
struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)g_wtp.kmodhandle.interfaces->first->item;
|
||||
|
||||
if (wtp_kmod_leave_mac80211_device(interface->wlan)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
capwap_list_free(g_wtp.kmodhandle.interfaces);
|
||||
}
|
||||
|
||||
if (g_wtp.kmodhandle.nl) {
|
||||
nl_socket_free(g_wtp.kmodhandle.nl);
|
||||
}
|
||||
|
@ -1,17 +1,40 @@
|
||||
#ifndef __WTP_KMOD_HEADER__
|
||||
#define __WTP_KMOD_HEADER__
|
||||
|
||||
#include "wifi_drivers.h"
|
||||
|
||||
/* */
|
||||
#ifdef HAVE_LIBNL_10
|
||||
#define nl_sock nl_handle
|
||||
#endif
|
||||
|
||||
/* */
|
||||
#define WTP_KMOD_MODE_LOCAL 0x00000001
|
||||
#define WTP_KMOD_MODE_TUNNEL_USERMODE 0x00000002
|
||||
#define WTP_KMOD_MODE_TUNNEL_KERNELMODE 0x00000003
|
||||
|
||||
/* */
|
||||
#define WTP_KMOD_FLAGS_TUNNEL_NATIVE 0x00000000
|
||||
#define WTP_KMOD_FLAGS_TUNNEL_8023 0x00000001
|
||||
|
||||
/* */
|
||||
struct wtp_kmod_iface_handle {
|
||||
struct nl_sock* nl;
|
||||
int nl_fd;
|
||||
struct nl_cb* nl_cb;
|
||||
|
||||
struct wifi_wlan* wlan;
|
||||
};
|
||||
|
||||
/* */
|
||||
struct wtp_kmod_handle {
|
||||
struct nl_sock* nl;
|
||||
int nl_fd;
|
||||
struct nl_cb* nl_cb;
|
||||
int nlsmartcapwap_id;
|
||||
|
||||
/* */
|
||||
struct capwap_list* interfaces;
|
||||
};
|
||||
|
||||
/* */
|
||||
@ -31,6 +54,7 @@ int wtp_kmod_isconnected(void);
|
||||
int wtp_kmod_getfd(struct pollfd* fds, struct wtp_kmod_event* events, int count);
|
||||
|
||||
/* */
|
||||
int wtp_kmod_join_mac80211_device(uint32_t ifindex);
|
||||
int wtp_kmod_join_mac80211_device(struct wifi_wlan* wlan, uint32_t mode, uint32_t flags);
|
||||
int wtp_kmod_leave_mac80211_device(struct wifi_wlan* wlan);
|
||||
|
||||
#endif /* __WTP_KMOD_HEADER__ */
|
||||
|
@ -51,15 +51,15 @@ static int wtp_radio_configure_phy(struct wtp_radio* radio) {
|
||||
}
|
||||
|
||||
/* */
|
||||
static void wtp_radio_send_frame_to_ac(void* param, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
|
||||
static int wtp_radio_send_frame_to_ac(void* param, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype) {
|
||||
struct wtp_radio_wlan* wlan = (struct wtp_radio_wlan*)param;
|
||||
|
||||
ASSERT(param != NULL);
|
||||
ASSERT(mgmt != NULL);
|
||||
ASSERT(mgmtlength >= sizeof(struct ieee80211_header));
|
||||
ASSERT(frame != NULL);
|
||||
ASSERT(length > 0);
|
||||
|
||||
/* Send packet */
|
||||
wtp_send_data_packet(wlan->radio->radioid, wlan->wlanid, (const uint8_t*)mgmt, mgmtlength, 1);
|
||||
return wtp_send_data_packet(wlan->radio->radioid, wlan->wlanid, frame, length, nativeframe, rssi, snr, rate, bssaddress, bssaddresstype);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
Loading…
Reference in New Issue
Block a user