Added functionality into capwap data channel kernel module

This commit is contained in:
vemax78
2014-12-23 21:12:25 +01:00
parent e2dea6b3de
commit 33ea96d9f5
35 changed files with 2172 additions and 541 deletions

View File

@ -1,5 +1,7 @@
#include "config.h"
#include <linux/module.h>
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
#include "socket.h"
#include "capwap.h"
@ -12,6 +14,12 @@
/* */
union capwap_addr sc_localaddr;
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
static unsigned char sc_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
static unsigned char sc_bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
/* */
static void sc_capwap_fragment_free(struct sc_capwap_fragment* fragment) {
TRACEKMOD("### sc_capwap_fragment_free\n");
@ -32,7 +40,6 @@ static void sc_capwap_fragment_free(struct sc_capwap_fragment* fragment) {
/* */
static void sc_capwap_defrag_evictor(struct sc_capwap_session* session, ktime_t now) {
ktime_t delta;
unsigned long flags;
struct sc_capwap_fragment* fragment;
TRACEKMOD("### sc_capwap_defrag_evictor\n");
@ -45,7 +52,7 @@ static void sc_capwap_defrag_evictor(struct sc_capwap_session* session, ktime_t
/* Remove last old fragment */
if (!list_empty(&session->fragments.lru_list)) {
spin_lock_irqsave(&session->fragments.lock, flags);
spin_lock(&session->fragments.lock);
fragment = list_first_entry(&session->fragments.lru_list, struct sc_capwap_fragment, lru_list);
if (fragment) {
@ -58,7 +65,7 @@ static void sc_capwap_defrag_evictor(struct sc_capwap_session* session, ktime_t
}
}
spin_unlock_irqrestore(&session->fragments.lock, flags);
spin_unlock(&session->fragments.lock);
}
}
@ -104,7 +111,6 @@ static struct sk_buff* sc_capwap_reasm(struct sc_capwap_fragment* fragment) {
/* */
static struct sk_buff* sc_capwap_defrag(struct sc_capwap_session* session, struct sk_buff* skb) {
unsigned long flags;
uint16_t headersize;
uint16_t frag_id;
struct sk_buff* prev;
@ -132,7 +138,7 @@ static struct sk_buff* sc_capwap_defrag(struct sc_capwap_session* session, struc
cb->frag_length = skb->len - headersize;
/* */
spin_lock_irqsave(&session->fragments.lock, flags);
spin_lock(&session->fragments.lock);
/* Get fragment */
fragment = &session->fragments.queues[frag_id % CAPWAP_FRAGMENT_QUEUE];
@ -219,18 +225,158 @@ static struct sk_buff* sc_capwap_defrag(struct sc_capwap_session* session, struc
}
}
spin_unlock_irqrestore(&session->fragments.lock, flags);
spin_unlock(&session->fragments.lock);
return skb_defrag;
error2:
spin_unlock_irqrestore(&session->fragments.lock, flags);
spin_unlock(&session->fragments.lock);
error:
kfree_skb(skb);
return NULL;
}
/* */
static unsigned int sc_capwap_80211_hdrlen(__le16 fc) {
unsigned int hdrlen = 24;
TRACEKMOD("### sc_capwap_80211_hdrlen\n");
if (ieee80211_is_data(fc)) {
if (ieee80211_has_a4(fc)) {
hdrlen = 30;
}
if (ieee80211_is_data_qos(fc)) {
hdrlen += IEEE80211_QOS_CTL_LEN;
if (ieee80211_has_order(fc)) {
hdrlen += IEEE80211_HT_CTL_LEN;
}
}
} else if (ieee80211_is_ctl(fc)) {
if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0)) {
hdrlen = 10;
} else {
hdrlen = 16;
}
}
return hdrlen;
}
/* */
int sc_capwap_8023_to_80211(struct sk_buff* skb, const uint8_t* bssid) {
uint16_t hdrlen;
int head_need;
struct ieee80211_hdr hdr;
int skip_header_bytes;
uint8_t* encaps_data;
int encaps_len;
struct ethhdr* eh = (struct ethhdr*)skb->data;
uint16_t ethertype = ntohs(eh->h_proto);
TRACEKMOD("### sc_capwap_8023_to_80211\n");
/* IEEE 802.11 header */
hdrlen = 24;
hdr.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_FROMDS);
memcpy(hdr.addr1, eh->h_dest, ETH_ALEN);
memcpy(hdr.addr2, bssid, ETH_ALEN);
memcpy(hdr.addr3, eh->h_source, ETH_ALEN);
hdr.duration_id = 0;
hdr.seq_ctrl = 0;
/* */
skip_header_bytes = ETH_HLEN;
if ((ethertype == ETH_P_AARP) || (ethertype == ETH_P_IPX)) {
encaps_data = sc_bridge_tunnel_header;
encaps_len = sizeof(sc_bridge_tunnel_header);
skip_header_bytes -= 2;
} else if (ethertype >= ETH_P_802_3_MIN) {
encaps_data = sc_rfc1042_header;
encaps_len = sizeof(sc_rfc1042_header);
skip_header_bytes -= 2;
} else {
encaps_data = NULL;
encaps_len = 0;
}
/* Remove IEEE 802.3 header */
skb_pull(skb, skip_header_bytes);
/* Check headroom */
head_need = hdrlen + encaps_len - skb_headroom(skb);
if ((head_need > 0) || skb_cloned(skb)) {
head_need = max(head_need, 0);
if (head_need) {
skb_orphan(skb);
}
TRACEKMOD("*** Expand headroom skb of: %d\n", head_need);
if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) {
return -ENOMEM;
}
skb->truesize += head_need;
}
/* Add LLC header */
if (encaps_data) {
memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
}
/* Add IEEE 802.11 header */
memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
skb_reset_mac_header(skb);
return 0;
}
/* */
int sc_capwap_80211_to_8023(struct sk_buff* skb) {
struct ieee80211_hdr* hdr = (struct ieee80211_hdr*)skb->data;
uint16_t hdrlen;
uint16_t ethertype;
uint8_t* payload;
uint8_t dst[ETH_ALEN];
uint8_t src[ETH_ALEN] __aligned(2);
TRACEKMOD("### sc_capwap_80211_to_8023\n");
/* */
hdrlen = sc_capwap_80211_hdrlen(hdr->frame_control);
memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
/* */
if (!pskb_may_pull(skb, hdrlen + 8)) {
return -1;
}
/* */
payload = skb->data + hdrlen;
ethertype = (payload[6] << 8) | payload[7];
if (likely((ether_addr_equal(payload, sc_rfc1042_header) && (ethertype != ETH_P_AARP) && (ethertype != ETH_P_IPX)) || ether_addr_equal(payload, sc_bridge_tunnel_header))) {
skb_pull(skb, hdrlen + 6);
memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
} else {
struct ethhdr *ehdr;
__be16 len;
skb_pull(skb, hdrlen);
len = htons(skb->len);
ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
memcpy(ehdr->h_dest, dst, ETH_ALEN);
memcpy(ehdr->h_source, src, ETH_ALEN);
ehdr->h_proto = len;
}
return 0;
}
/* */
int sc_capwap_bind(union capwap_addr* sockaddr) {
int ret;
@ -275,13 +421,12 @@ void sc_capwap_freesession(struct sc_capwap_session* session) {
/* */
uint16_t sc_capwap_newfragmentid(struct sc_capwap_session* session) {
uint16_t fragmentid;
unsigned long flags;
TRACEKMOD("### sc_capwap_newfragmentid\n");
spin_lock_irqsave(&session->fragmentid_lock, flags);
spin_lock(&session->fragmentid_lock);
fragmentid = session->fragmentid++;
spin_unlock_irqrestore(&session->fragmentid_lock, flags);
spin_unlock(&session->fragmentid_lock);
return fragmentid;
}
@ -454,8 +599,6 @@ int sc_capwap_parsingpacket(struct sc_capwap_session* session, const union capwa
}
}
/* Parsing complete */
kfree_skb(skb);
return 0;
}
@ -464,6 +607,7 @@ int sc_capwap_parsingpacket(struct sc_capwap_session* session, const union capwa
/* */
int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, uint8_t binding, struct sk_buff* skb, uint32_t flags, struct sc_capwap_radio_addr* radioaddr, int radioaddrlength, struct sc_capwap_wireless_information* winfo, int winfolength) {
int err;
int size;
int length;
int reserve;
@ -482,7 +626,7 @@ int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, ui
reserve = sizeof(struct sc_capwap_header) + radioaddrlength + winfolength;
if (skb_is_nonlinear(skb) || (headroom < reserve)) {
printk("*** Expand socket buffer\n");
clone = skb_copy_expand(skb, max_t(int, headroom, reserve), skb_tailroom(skb), GFP_KERNEL);
clone = skb_copy_expand(skb, max(headroom, reserve), skb_tailroom(skb), GFP_KERNEL);
if (!clone) {
printk("*** Unable to expand socket buffer\n");
return -ENOMEM;
@ -551,7 +695,9 @@ int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, ui
}
/* Send packet */
if (sc_socket_send(SOCKET_UDP, (uint8_t*)header, (size + length), &session->peeraddr) < 0) {
err = sc_socket_send(SOCKET_UDP, (uint8_t*)header, (size + length), &session->peeraddr);
TRACEKMOD("*** Send packet result: %d\n", err);
if (err < 0) {
break;
}
@ -593,18 +739,18 @@ struct sc_capwap_radio_addr* sc_capwap_setradiomacaddress(uint8_t* buffer, int s
radioaddr = (struct sc_capwap_radio_addr*)buffer;
radioaddr->length = MACADDRESS_EUI48_LENGTH;
addr = (struct sc_capwap_macaddress_eui48*)(buffer + sizeof(struct sc_capwap_radio_addr));
addr = (struct sc_capwap_macaddress_eui48*)radioaddr->addr;
memcpy(addr->addr, bssid, MACADDRESS_EUI48_LENGTH);
return radioaddr;
}
/* */
struct sc_capwap_wireless_information* sc_capwap_setwirelessinformation(uint8_t* buffer, int size, uint8_t rssi, uint8_t snr, uint16_t rate) {
struct sc_capwap_wireless_information* sc_capwap_setwinfo_frameinfo(uint8_t* buffer, int size, uint8_t rssi, uint8_t snr, uint16_t rate) {
struct sc_capwap_wireless_information* winfo;
struct sc_capwap_ieee80211_frame_info* frameinfo;
TRACEKMOD("### sc_capwap_setwirelessinformation\n");
TRACEKMOD("### sc_capwap_setwinfo_frameinfo\n");
memset(buffer, 0, size);
@ -618,3 +764,21 @@ struct sc_capwap_wireless_information* sc_capwap_setwirelessinformation(uint8_t*
return winfo;
}
/* */
struct sc_capwap_wireless_information* sc_capwap_setwinfo_destwlans(uint8_t* buffer, int size, uint16_t wlanidbitmap) {
struct sc_capwap_wireless_information* winfo;
struct sc_capwap_destination_wlans* destwlans;
TRACEKMOD("### sc_capwap_setwinfo_destwlans\n");
memset(buffer, 0, size);
winfo = (struct sc_capwap_wireless_information*)buffer;
winfo->length = sizeof(struct sc_capwap_destination_wlans);
destwlans = (struct sc_capwap_destination_wlans*)(buffer + sizeof(struct sc_capwap_wireless_information));
destwlans->wlanidbitmap = cpu_to_be16(wlanidbitmap);
return winfo;
}

View File

@ -21,27 +21,25 @@
/* */
#define SKB_CAPWAP_FLAG_FROM_DATA_CHANNEL 0x0001
#define SKB_CAPWAP_FLAG_FROM_USER_SPACE 0x0002
#define SKB_CAPWAP_FLAG_FROM_IEEE80211 0x0004
#define SKB_CAPWAP_FLAG_PEERADDRESS 0x0010
#define SKB_CAPWAP_FLAG_RADIOID 0x0020
#define SKB_CAPWAP_FLAG_BINDING 0x0040
#define SKB_CAPWAP_FLAG_RADIOADDRESS 0x0080
#define SKB_CAPWAP_FLAG_WIRELESSINFORMATION 0x0100
#define SKB_CAPWAP_FLAG_FROM_AC_TAP 0x0004
#define SKB_CAPWAP_FLAG_FROM_IEEE80211 0x0008
#define SKB_CAPWAP_FLAG_SESSIONID 0x0100
#define SKB_CAPWAP_FLAG_RADIOID 0x0200
#define SKB_CAPWAP_FLAG_BINDING 0x0400
#define SKB_CAPWAP_FLAG_WIRELESSINFORMATION 0x0800
#define SKB_CAPWAP_FLAG_FRAGMENT 0x1000
struct sc_skb_capwap_cb {
uint16_t flags;
struct capwap_addr_little peeraddr;
/* Session ID */
struct sc_capwap_sessionid_element sessionid;
/* Capwap information */
uint8_t radioid;
uint8_t binding;
/* Radio Address */
uint8_t radioaddr_addr[MACADDRESS_EUI48_LENGTH];
/* Wireless Information */
uint8_t winfo_rssi;
uint8_t winfo_snr;
@ -106,16 +104,17 @@ void sc_capwap_initsession(struct sc_capwap_session* session);
void sc_capwap_freesession(struct sc_capwap_session* session);
uint16_t sc_capwap_newfragmentid(struct sc_capwap_session* session);
void sc_capwap_sessionid_printf(const struct sc_capwap_sessionid_element* sessionid, char* string);
int sc_capwap_8023_to_80211(struct sk_buff* skb, const uint8_t* bssid);
int sc_capwap_80211_to_8023(struct sk_buff* skb);
struct sc_capwap_packet* sc_capwap_poppacketqueue(struct sc_capwap_session* session);
void sc_capwap_pushpacketqueue(struct sc_capwap_session* session, struct sc_capwap_packet* packet);
void sc_capwap_sessionid_printf(const struct sc_capwap_sessionid_element* sessionid, char* string);
int sc_capwap_createkeepalive(struct sc_capwap_sessionid_element* sessionid, uint8_t* buffer, int size);
int sc_capwap_parsingpacket(struct sc_capwap_session* session, const union capwap_addr* sockaddr, struct sk_buff* skb);
struct sc_capwap_radio_addr* sc_capwap_setradiomacaddress(uint8_t* buffer, int size, uint8_t* bssid);
struct sc_capwap_wireless_information* sc_capwap_setwirelessinformation(uint8_t* buffer, int size, uint8_t rssi, uint8_t snr, uint16_t rate);
struct sc_capwap_wireless_information* sc_capwap_setwinfo_frameinfo(uint8_t* buffer, int size, uint8_t rssi, uint8_t snr, uint16_t rate);
struct sc_capwap_wireless_information* sc_capwap_setwinfo_destwlans(uint8_t* buffer, int size, uint16_t wlanidbitmap);
int sc_capwap_forwarddata(struct sc_capwap_session* session, uint8_t radioid, uint8_t binding, struct sk_buff* skb, uint32_t flags, struct sc_capwap_radio_addr* radioaddr, int radioaddrlength, struct sc_capwap_wireless_information* winfo, int winfolength);

View File

@ -1,6 +1,9 @@
#include "config.h"
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
#include <net/mac80211.h>
#include <net/ipv6.h>
#include "capwap.h"
#include "nlsmartcapwap.h"
@ -77,6 +80,7 @@ int sc_capwap_sendkeepalive(void) {
/* Send packet */
ret = sc_socket_send(SOCKET_UDP, buffer, length, &sc_acsession.peeraddr);
TRACEKMOD("*** Send keep-alive result: %d\n", ret);
if (ret > 0) {
ret = 0;
}
@ -151,8 +155,119 @@ struct sc_capwap_session* sc_capwap_recvunknownkeepalive(const union capwap_addr
/* */
void sc_capwap_parsingdatapacket(struct sc_capwap_session* session, struct sk_buff* skb) {
uint8_t* pos;
uint8_t* dstaddress;
struct net_device* dev;
struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
int is80211 = (IS_FLAG_T_HEADER(header) ? 1 : 0);
struct sc_capwap_radio_addr* radioaddr = NULL;
int radioaddrsize = 0;
struct sc_capwap_wireless_information* winfo = NULL;
struct sc_capwap_destination_wlans* destwlan = NULL;
int winfosize = 0;
TRACEKMOD("### sc_capwap_parsingdatapacket\n");
/* Retrieve optional attribute */
pos = skb->data + sizeof(struct sc_capwap_header);
if (IS_FLAG_M_HEADER(header)) {
radioaddr = (struct sc_capwap_radio_addr*)pos;
radioaddrsize = (sizeof(struct sc_capwap_radio_addr) + radioaddr->length + 3) & ~3;
pos += radioaddrsize;
}
if (IS_FLAG_W_HEADER(header)) {
winfo = (struct sc_capwap_wireless_information*)pos;
destwlan = (struct sc_capwap_destination_wlans*)(pos + sizeof(struct sc_capwap_wireless_information));
winfosize = (sizeof(struct sc_capwap_wireless_information) + winfo->length + 3) & ~3;
pos += winfosize;
}
/* Body packet */
skb_pull(skb, GET_HLEN_HEADER(header) * 4);
dstaddress = (is80211 ? ieee80211_get_DA((struct ieee80211_hdr*)skb->data) : (uint8_t*)((struct ethhdr*)skb->data)->h_dest);
if (is_multicast_ether_addr(dstaddress)) {
/* Accept only broadcast packet with wireless information */
if (winfo) {
uint8_t wlanid = 1;
uint16_t bitmask = be16_to_cpu(destwlan->wlanidbitmap);
while (bitmask) {
if (bitmask & 0x01) {
dev = sc_netlink_getdev_from_wlanid(GET_RID_HEADER(header), wlanid);
if (dev) {
struct sk_buff* clone = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb), GFP_KERNEL);
if (!clone) {
goto error;
}
TRACEKMOD("****************\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, clone->data, sizeof(struct ethhdr), 1);
TRACEKMOD("++++++++++++++++\n");
/* */
if (!is80211) {
if (sc_capwap_8023_to_80211(clone, dev->dev_addr)) {
kfree_skb(clone);
goto error;
}
}
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, clone->data, sizeof(struct ieee80211_hdr), 1);
TRACEKMOD("****************\n");
TRACEKMOD("** Send broadcast packet to interface: %d\n", dev->ifindex);
/* Send packet */
local_bh_disable();
ieee80211_inject_xmit(clone, dev);
local_bh_enable();
} else {
TRACEKMOD("*** Unknown wlanid: %d\n", (int)wlanid);
}
}
/* Next */
wlanid++;
bitmask >>= 1;
}
} else {
TRACEKMOD("*** Invalid broadcast packet\n");
}
/* Free broadcast packet */
kfree_skb(skb);
} else {
/* Accept only 802.11 frame or 802.3 frame with radio address */
if (is80211 || (radioaddr && (radioaddr->length == MACADDRESS_EUI48_LENGTH))){
if (!is80211) {
if (sc_capwap_8023_to_80211(skb, radioaddr->addr)) {
goto error;
}
}
/* */
dev = sc_netlink_getdev_from_bssid(GET_RID_HEADER(header), ((struct ieee80211_hdr*)skb->data)->addr2);
if (!dev) {
goto error;
}
TRACEKMOD("** Send packet to interface: %d\n", dev->ifindex);
/* Send packet */
local_bh_disable();
ieee80211_inject_xmit(skb, dev);
local_bh_enable();
} else {
goto error;
}
}
return;
error:
TRACEKMOD("*** Invalid packet\n");
kfree_skb(skb);
}
/* */

View File

@ -79,6 +79,7 @@ struct sc_capwap_header {
#define CAPWAP_RADIO_MAX_LENGTH_PADDED 12
struct sc_capwap_radio_addr {
uint8_t length;
uint8_t addr[0];
} __packed;
/* Wireless Information */
@ -96,6 +97,12 @@ struct sc_capwap_ieee80211_frame_info {
__be16 rate;
} __packed;
/* Destination WLANs */
struct sc_capwap_destination_wlans {
__be16 wlanidbitmap;
__be16 reserved;
} __packed;
/* */
#define CAPWAP_HEADER_MAX_LENGTH (sizeof(struct sc_capwap_header) + CAPWAP_RADIO_MAX_LENGTH_PADDED + CAPWAP_WINFO_MAX_LENGTH_PADDED)
@ -112,7 +119,10 @@ struct sc_capwap_message_element {
/* Session id message element */
struct sc_capwap_sessionid_element {
uint8_t id[16];
union {
uint8_t id[16];
uint32_t id32[4];
};
} __packed;
/* */
@ -169,4 +179,9 @@ struct sc_capwap_macaddress_eui64 {
#define IS_FLAG_K_HEADER(x) ((x)->flag_k)
#define SET_FLAG_K_HEADER(x, y) ((x)->flag_k = ((y) ? 1 : 0))
/* IEEE 802.11 Add WLAN */
#define CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL 0
#define CAPWAP_ADD_WLAN_TUNNELMODE_8023 1
#define CAPWAP_ADD_WLAN_TUNNELMODE_80211 2
#endif /* __KMOD_CAPWAP_RFC_HEADER__ */

View File

@ -68,8 +68,8 @@ static int sc_netlink_handler(uint32_t ifindex, struct sk_buff* skb, int sig_dbm
if (ieee80211_is_data(hdr->frame_control)) {
int err;
struct sc_capwap_session* session;
unsigned char radioaddrbuffer[CAPWAP_RADIO_EUI48_LENGTH_PADDED];
unsigned char winfobuffer[CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED];
uint8_t radioaddrbuffer[CAPWAP_RADIO_EUI48_LENGTH_PADDED];
uint8_t winfobuffer[CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED];
struct sc_capwap_radio_addr* radioaddr = NULL;
struct sc_capwap_wireless_information* winfo = NULL;
@ -97,7 +97,7 @@ static int sc_netlink_handler(uint32_t ifindex, struct sk_buff* skb, int sig_dbm
/* Create Wireless Information */
if (sig_dbm || rate) {
winfo = sc_capwap_setwirelessinformation(winfobuffer, CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED, (uint8_t)sig_dbm, 0, ((uint16_t)rate) * 5);
winfo = sc_capwap_setwinfo_frameinfo(winfobuffer, CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED, (uint8_t)sig_dbm, 0, ((uint16_t)rate) * 5);
}
/* */
@ -455,7 +455,7 @@ static int sc_netlink_send_data(struct sk_buff* skb, struct genl_info* info) {
/* Create Wireless Information */
if (rssi || snr || rate) {
winfo = sc_capwap_setwirelessinformation(winfobuffer, CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED, rssi, snr, rate);
winfo = sc_capwap_setwinfo_frameinfo(winfobuffer, CAPWAP_WINFO_FRAMEINFO_LENGTH_PADDED, rssi, snr, rate);
}
/* Create socket buffer */
@ -728,6 +728,38 @@ error:
return -ENOMEM;
}
/* */
struct net_device* sc_netlink_getdev_from_wlanid(uint8_t radioid, uint8_t wlanid) {
struct sc_netlink_device* nldev;
TRACEKMOD("### sc_netlink_getdev_from_wlanid\n");
/* Search */
list_for_each_entry(nldev, &sc_netlink_dev_list, list) {
if ((nldev->radioid == radioid) && (nldev->wlanid == wlanid)) {
return nldev->dev;
}
}
return NULL;
}
/* */
struct net_device* sc_netlink_getdev_from_bssid(uint8_t radioid, const uint8_t* addr) {
struct sc_netlink_device* nldev;
TRACEKMOD("### sc_netlink_getdev_from_bssid\n");
/* Search */
list_for_each_entry(nldev, &sc_netlink_dev_list, list) {
if ((nldev->radioid == radioid) && !memcmp(nldev->dev->dev_addr, addr, MACADDRESS_EUI48_LENGTH)) {
return nldev->dev;
}
}
return NULL;
}
/* */
int sc_netlink_init(void) {
int ret;

View File

@ -8,6 +8,10 @@
int sc_netlink_init(void);
void sc_netlink_exit(void);
/* */
struct net_device* sc_netlink_getdev_from_wlanid(uint8_t radioid, uint8_t wlanid);
struct net_device* sc_netlink_getdev_from_bssid(uint8_t radioid, const uint8_t* addr);
/* */
int sc_netlink_notify_recv_keepalive(const union capwap_addr* sockaddr, struct sc_capwap_sessionid_element* sessionid);
int sc_netlink_notify_recv_data(uint8_t* packet, int length);

View File

@ -225,29 +225,3 @@ int sc_addr_compare(const union capwap_addr* addr1, const union capwap_addr* add
return -1;
}
/* */
void sc_addr_tolittle(const union capwap_addr* addr, struct capwap_addr_little* little) {
little->family = (uint8_t)addr->ss.ss_family;
if (addr->ss.ss_family == AF_INET) {
memcpy(&little->addr4, &addr->sin.sin_addr, sizeof(struct in_addr));
little->port = addr->sin.sin_port;
} else if (addr->ss.ss_family == AF_INET6) {
memcpy(&little->addr6, &addr->sin6.sin6_addr, sizeof(struct in6_addr));
little->port = addr->sin6.sin6_port;
}
}
/* */
void sc_addr_fromlittle(const struct capwap_addr_little* little, union capwap_addr* addr) {
memset(addr, 0, sizeof(union capwap_addr));
addr->ss.ss_family = little->family;
if (little->family == AF_INET) {
memcpy(&addr->sin.sin_addr, &little->addr4, sizeof(struct in_addr));
addr->sin.sin_port = little->port;
} else if (little->family == AF_INET6) {
memcpy(&addr->sin6.sin6_addr, &little->addr6, sizeof(struct in6_addr));
addr->sin6.sin6_port = little->port;
}
}

View File

@ -10,16 +10,6 @@
#define SOCKET_UDP 0
#define SOCKET_UDPLITE 1
/* Little socket address */
struct capwap_addr_little {
uint8_t family;
union {
struct in_addr addr4;
struct in6_addr addr6;
};
uint16_t port;
};
/* Universal socket address */
union capwap_addr {
struct sockaddr sa;
@ -35,11 +25,11 @@ void sc_socket_close(void);
/* */
int sc_socket_bind(union capwap_addr* sockaddr);
int sc_socket_send(int type, uint8_t* buffer, int length, union capwap_addr* sockaddr);
/* */
int sc_socket_getpeeraddr(struct sk_buff* skb, union capwap_addr* peeraddr);
/* */
int sc_addr_compare(const union capwap_addr* addr1, const union capwap_addr* addr2);
void sc_addr_tolittle(const union capwap_addr* addr, struct capwap_addr_little* little);
void sc_addr_fromlittle(const struct capwap_addr_little* little, union capwap_addr* addr);
#endif /* __KMOD_SOCKET_HEADER__ */