3 * @brief File Operations OS wrapper functionality
5 * @sa wilc_wfi_netdevice.h
9 #include "wilc_wfi_cfgoperations.h"
10 #include "linux_wlan_common.h"
11 #include "wilc_wlan_if.h"
12 #include "wilc_wlan.h"
14 #ifdef WILC_FULLY_HOSTING_AP
15 #include "wilc_host_ap.h"
17 #ifdef WILC_AP_EXTERNAL_MLME
19 struct wilc_wfi_radiotap_hdr {
20 struct ieee80211_radiotap_header hdr;
23 } __attribute__((packed));
25 struct wilc_wfi_radiotap_cb_hdr {
26 struct ieee80211_radiotap_header hdr;
31 } __attribute__((packed));
33 extern linux_wlan_t *g_linux_wlan;
35 static struct net_device *wilc_wfi_mon; /* global monitor netdev */
38 extern int mac_xmit(struct sk_buff *skb, struct net_device *dev);
44 u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
46 * @brief WILC_WFI_monitor_rx
49 * @return int : Return 0 on Success
55 #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
56 #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/
57 #define IS_MANAGMEMENT 0x100
58 #define IS_MANAGMEMENT_CALLBACK 0x080
59 #define IS_MGMT_STATUS_SUCCES 0x040
60 #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
62 void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size)
64 uint32_t header, pkt_offset;
65 struct sk_buff *skb = NULL;
66 struct wilc_wfi_radiotap_hdr *hdr;
67 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
69 PRINT_INFO(HOSTAPD_DBG, "In monitor interface receive function\n");
71 /* struct WILC_WFI_priv *priv = netdev_priv(dev); */
73 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
76 if (wilc_wfi_mon == NULL)
79 if (!netif_running(wilc_wfi_mon)) {
80 PRINT_INFO(HOSTAPD_DBG, "Monitor interface already RUNNING\n");
85 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
87 /* The packet offset field conain info about what type of managment frame */
88 /* we are dealing with and ack status */
89 pkt_offset = GET_PKT_OFFSET(header);
91 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
93 /* hostapd callback mgmt frame */
95 skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr));
97 PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
101 memcpy(skb_put(skb, size), buff, size);
103 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
104 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
106 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
108 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
110 cb_hdr->hdr.it_present = cpu_to_le32(
111 (1 << IEEE80211_RADIOTAP_RATE) |
112 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
114 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
116 if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
118 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
120 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
125 skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr));
128 PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
132 /* skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); */
133 /* if (skb == NULL) */
136 memcpy(skb_put(skb, size), buff, size);
137 hdr = (struct wilc_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr));
138 memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr));
139 hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
140 /* hdr->hdr.it_pad = 0; */
141 hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr));
142 PRINT_INFO(HOSTAPD_DBG, "Radiotap len %d\n", hdr->hdr.it_len);
143 hdr->hdr.it_present = cpu_to_le32
144 (1 << IEEE80211_RADIOTAP_RATE); /* | */
145 /* (1 << IEEE80211_RADIOTAP_CHANNEL)); */
146 PRINT_INFO(HOSTAPD_DBG, "Presentflags %d\n", hdr->hdr.it_present);
147 hdr->rate = 5; /* txrate->bitrate / 5; */
151 /* if(INFO || if(skb->data[9] == 0x00 || skb->data[9] == 0xb0))
153 * for(i=0;i<skb->len;i++)
154 * PRINT_INFO(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,skb->data[i]);
158 skb->dev = wilc_wfi_mon;
159 skb_set_mac_header(skb, 0);
160 skb->ip_summed = CHECKSUM_UNNECESSARY;
161 skb->pkt_type = PACKET_OTHERHOST;
162 skb->protocol = htons(ETH_P_802_2);
163 memset(skb->cb, 0, sizeof(skb->cb));
170 struct tx_complete_mon_data {
175 static void mgmt_tx_complete(void *priv, int status)
178 /* struct sk_buff *skb2; */
179 /* struct wilc_wfi_radiotap_cb_hdr *cb_hdr; */
181 struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv;
182 u8 *buf = pv_data->buff;
187 if (INFO || buf[0] == 0x10 || buf[0] == 0xb0)
188 PRINT_INFO(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
190 PRINT_INFO(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
194 /* //(skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 )
196 * skb2 = dev_alloc_skb(pv_data->size+sizeof(struct wilc_wfi_radiotap_cb_hdr));
198 * memcpy(skb_put(skb2,pv_data->size),pv_data->buff, pv_data->size);
200 * cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
201 * memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
203 * cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
205 * cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
207 * cb_hdr->hdr.it_present = cpu_to_le32(
208 * (1 << IEEE80211_RADIOTAP_RATE) |
209 * (1 << IEEE80211_RADIOTAP_TX_FLAGS));
211 * cb_hdr->rate = 5;//txrate->bitrate / 5;
212 * cb_hdr->tx_flags = 0x0004;
214 * skb2->dev = wilc_wfi_mon;
215 * skb_set_mac_header(skb2, 0);
216 * skb2->ip_summed = CHECKSUM_UNNECESSARY;
217 * skb2->pkt_type = PACKET_OTHERHOST;
218 * skb2->protocol = htons(ETH_P_802_2);
219 * memset(skb2->cb, 0, sizeof(skb2->cb));
224 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
225 #ifndef WILC_FULLY_HOSTING_AP
226 kfree(pv_data->buff);
231 static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
233 struct tx_complete_mon_data *mgmt_tx = NULL;
236 PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n");
240 netif_stop_queue(dev);
241 mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC);
242 if (mgmt_tx == NULL) {
243 PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
247 #ifdef WILC_FULLY_HOSTING_AP
248 /* add space for the pointer to tx_complete_mon_data */
249 len += sizeof(struct tx_complete_mon_data *);
252 mgmt_tx->buff = kmalloc(len, GFP_ATOMIC);
253 if (mgmt_tx->buff == NULL) {
254 PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
261 #ifndef WILC_FULLY_HOSTING_AP
262 memcpy(mgmt_tx->buff, buf, len);
264 memcpy(mgmt_tx->buff, buf, len - sizeof(struct tx_complete_mon_data *));
265 memcpy((mgmt_tx->buff) + (len - sizeof(struct tx_complete_mon_data *)), &mgmt_tx, sizeof(struct tx_complete_mon_data *));
267 /* filter data frames to handle it's PS */
268 if (filter_monitor_data_frames((mgmt_tx->buff), len) == true) {
272 #endif /* WILC_FULLY_HOSTING_AP */
274 g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx, mgmt_tx->buff, mgmt_tx->size, mgmt_tx_complete);
276 netif_wake_queue(dev);
281 * @brief WILC_WFI_mon_xmit
284 * @return int : Return 0 on Success
289 static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
290 struct net_device *dev)
292 u32 rtap_len, i, ret = 0;
293 struct WILC_WFI_mon_priv *mon_priv;
295 struct sk_buff *skb2;
296 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
299 if (wilc_wfi_mon == NULL)
302 /* if(skb->data[3] == 0x10 || skb->data[3] == 0xb0) */
304 mon_priv = netdev_priv(wilc_wfi_mon);
306 if (mon_priv == NULL) {
307 PRINT_ER("Monitor interface private structure is NULL\n");
312 rtap_len = ieee80211_get_radiotap_len(skb->data);
313 if (skb->len < rtap_len) {
314 PRINT_ER("Error in radiotap header\n");
317 /* skip the radiotap header */
318 PRINT_INFO(HOSTAPD_DBG, "Radiotap len: %d\n", rtap_len);
321 for (i = 0; i < rtap_len; i++)
322 PRINT_INFO(HOSTAPD_DBG, "Radiotap_hdr[%d] %02x\n", i, skb->data[i]);
324 /* Skip the ratio tap header */
325 skb_pull(skb, rtap_len);
327 if (skb->data[0] == 0xc0)
328 PRINT_INFO(HOSTAPD_DBG, "%x:%x:%x:%x:%x%x\n", skb->data[4], skb->data[5], skb->data[6], skb->data[7], skb->data[8], skb->data[9]);
330 if (skb->data[0] == 0xc0 && (!(memcmp(broadcast, &skb->data[4], 6)))) {
331 skb2 = dev_alloc_skb(skb->len + sizeof(struct wilc_wfi_radiotap_cb_hdr));
333 memcpy(skb_put(skb2, skb->len), skb->data, skb->len);
335 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
336 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
338 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
340 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
342 cb_hdr->hdr.it_present = cpu_to_le32(
343 (1 << IEEE80211_RADIOTAP_RATE) |
344 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
346 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
347 cb_hdr->tx_flags = 0x0004;
349 skb2->dev = wilc_wfi_mon;
350 skb_set_mac_header(skb2, 0);
351 skb2->ip_summed = CHECKSUM_UNNECESSARY;
352 skb2->pkt_type = PACKET_OTHERHOST;
353 skb2->protocol = htons(ETH_P_802_2);
354 memset(skb2->cb, 0, sizeof(skb2->cb));
360 skb->dev = mon_priv->real_ndev;
362 PRINT_INFO(HOSTAPD_DBG, "Skipping the radiotap header\n");
366 /* actual deliver of data is device-specific, and not shown here */
367 PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name);
368 PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name);
371 /* Identify if Ethernet or MAC header (data or mgmt) */
372 memcpy(srcAdd, &skb->data[10], 6);
373 memcpy(bssid, &skb->data[16], 6);
374 /* if source address and bssid fields are equal>>Mac header */
375 /*send it to mgmt frames handler */
376 if (!(memcmp(srcAdd, bssid, 6))) {
377 mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len);
380 ret = mac_xmit(skb, mon_priv->real_ndev);
383 /* return NETDEV_TX_OK; */
387 static const struct net_device_ops wilc_wfi_netdev_ops = {
388 .ndo_start_xmit = WILC_WFI_mon_xmit,
392 #ifdef WILC_FULLY_HOSTING_AP
394 * @brief WILC_mgm_HOSTAPD_ACK
395 * @details report the status of transmitted mgmt frames to HOSTAPD
396 * @param[in] priv : pointer to tx_complete_mon_data struct
397 * bStatus : status of transmission
398 * @author Abd Al-Rahman Diab
402 void WILC_mgm_HOSTAPD_ACK(void *priv, bool bStatus)
405 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
407 struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv;
408 u8 *buf = pv_data->buff;
410 /* len of the original frame without the added pointer at the tail */
411 u16 u16len = (pv_data->size) - sizeof(struct tx_complete_mon_data *);
415 * if(INFO || buf[0] == 0x10 || buf[0] == 0xb0)
416 * PRINT_D(HOSTAPD_DBG,"Packet sent successfully - Size = %d - Address = %p.\n",u16len,pv_data->buff);
418 * PRINT_D(HOSTAPD_DBG,"Couldn't send packet - Size = %d - Address = %p.\n",u16len,pv_data->buff);
422 /* (skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 ) */
424 skb = dev_alloc_skb(u16len + sizeof(struct wilc_wfi_radiotap_cb_hdr));
426 memcpy(skb_put(skb, u16len), pv_data->buff, u16len);
428 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
429 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
431 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
433 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
435 cb_hdr->hdr.it_present = cpu_to_le32(
436 (1 << IEEE80211_RADIOTAP_RATE) |
437 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
439 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
444 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
446 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
449 skb->dev = wilc_wfi_mon;
450 skb_set_mac_header(skb, 0);
451 skb->ip_summed = CHECKSUM_UNNECESSARY;
452 skb->pkt_type = PACKET_OTHERHOST;
453 skb->protocol = htons(ETH_P_802_2);
454 memset(skb->cb, 0, sizeof(skb->cb));
459 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
460 kfree(pv_data->buff);
465 #endif /* WILC_FULLY_HOSTING_AP */
468 * @brief WILC_WFI_mon_setup
471 * @return int : Return 0 on Success
476 static void WILC_WFI_mon_setup(struct net_device *dev)
479 dev->netdev_ops = &wilc_wfi_netdev_ops;
480 /* dev->destructor = free_netdev; */
481 PRINT_INFO(CORECONFIG_DBG, "In Ethernet setup function\n");
483 dev->tx_queue_len = 0;
484 dev->type = ARPHRD_IEEE80211_RADIOTAP;
485 eth_zero_addr(dev->dev_addr);
490 unsigned char mac_add[] = {0x00, 0x50, 0xc2, 0x5e, 0x10, 0x8f};
491 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
492 /* mac_add = (u8*)WILC_MALLOC(ETH_ALEN); */
493 /* status = host_int_get_MacAddress(priv->hWILCWFIDrv,mac_add); */
494 /* mac_add[ETH_ALEN-1]+=1; */
495 memcpy(dev->dev_addr, mac_add, ETH_ALEN);
498 dev->dev_addr[0] = 0x12;
504 * @brief WILC_WFI_init_mon_interface
507 * @return int : Return 0 on Success
512 struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_device *real_dev)
516 u32 ret = WILC_SUCCESS;
517 struct WILC_WFI_mon_priv *priv;
519 /*If monitor interface is already initialized, return it*/
524 wilc_wfi_mon = alloc_etherdev(sizeof(struct WILC_WFI_mon_priv));
526 PRINT_ER("failed to allocate memory\n");
531 wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP;
532 strncpy(wilc_wfi_mon->name, name, IFNAMSIZ);
533 wilc_wfi_mon->name[IFNAMSIZ - 1] = 0;
534 wilc_wfi_mon->netdev_ops = &wilc_wfi_netdev_ops;
536 ret = register_netdevice(wilc_wfi_mon);
538 PRINT_ER(" register_netdevice failed (%d)\n", ret);
541 priv = netdev_priv(wilc_wfi_mon);
543 PRINT_ER("private structure is NULL\n");
547 priv->real_ndev = real_dev;
553 * @brief WILC_WFI_deinit_mon_interface
556 * @return int : Return 0 on Success
561 int WILC_WFI_deinit_mon_interface(void)
563 bool rollback_lock = false;
565 if (wilc_wfi_mon != NULL) {
566 PRINT_D(HOSTAPD_DBG, "In Deinit monitor interface\n");
567 PRINT_D(HOSTAPD_DBG, "RTNL is being locked\n");
568 if (rtnl_is_locked()) {
570 rollback_lock = true;
572 PRINT_D(HOSTAPD_DBG, "Unregister netdev\n");
573 unregister_netdev(wilc_wfi_mon);
574 /* free_netdev(wilc_wfi_mon); */
578 rollback_lock = false;
585 #endif /* WILC_AP_EXTERNAL_MLME */