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"
15 struct wilc_wfi_radiotap_hdr
{
16 struct ieee80211_radiotap_header hdr
;
18 } __attribute__((packed
));
20 struct wilc_wfi_radiotap_cb_hdr
{
21 struct ieee80211_radiotap_header hdr
;
25 } __attribute__((packed
));
27 static struct net_device
*wilc_wfi_mon
; /* global monitor netdev */
31 static u8 broadcast
[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
33 * @brief WILC_WFI_monitor_rx
36 * @return int : Return 0 on Success
42 #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
43 #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/
44 #define IS_MANAGMEMENT 0x100
45 #define IS_MANAGMEMENT_CALLBACK 0x080
46 #define IS_MGMT_STATUS_SUCCES 0x040
47 #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
49 void WILC_WFI_monitor_rx(u8
*buff
, u32 size
)
51 u32 header
, pkt_offset
;
52 struct sk_buff
*skb
= NULL
;
53 struct wilc_wfi_radiotap_hdr
*hdr
;
54 struct wilc_wfi_radiotap_cb_hdr
*cb_hdr
;
56 PRINT_INFO(HOSTAPD_DBG
, "In monitor interface receive function\n");
58 if (wilc_wfi_mon
== NULL
)
61 if (!netif_running(wilc_wfi_mon
)) {
62 PRINT_INFO(HOSTAPD_DBG
, "Monitor interface already RUNNING\n");
67 memcpy(&header
, (buff
- HOST_HDR_OFFSET
), HOST_HDR_OFFSET
);
69 /* The packet offset field conain info about what type of managment frame */
70 /* we are dealing with and ack status */
71 pkt_offset
= GET_PKT_OFFSET(header
);
73 if (pkt_offset
& IS_MANAGMEMENT_CALLBACK
) {
75 /* hostapd callback mgmt frame */
77 skb
= dev_alloc_skb(size
+ sizeof(struct wilc_wfi_radiotap_cb_hdr
));
79 PRINT_INFO(HOSTAPD_DBG
, "Monitor if : No memory to allocate skb");
83 memcpy(skb_put(skb
, size
), buff
, size
);
85 cb_hdr
= (struct wilc_wfi_radiotap_cb_hdr
*) skb_push(skb
, sizeof(*cb_hdr
));
86 memset(cb_hdr
, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr
));
88 cb_hdr
->hdr
.it_version
= 0; /* PKTHDR_RADIOTAP_VERSION; */
90 cb_hdr
->hdr
.it_len
= cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr
));
92 cb_hdr
->hdr
.it_present
= cpu_to_le32(
93 (1 << IEEE80211_RADIOTAP_RATE
) |
94 (1 << IEEE80211_RADIOTAP_TX_FLAGS
));
96 cb_hdr
->rate
= 5; /* txrate->bitrate / 5; */
98 if (pkt_offset
& IS_MGMT_STATUS_SUCCES
) {
100 cb_hdr
->tx_flags
= IEEE80211_RADIOTAP_F_TX_RTS
;
102 cb_hdr
->tx_flags
= IEEE80211_RADIOTAP_F_TX_FAIL
;
107 skb
= dev_alloc_skb(size
+ sizeof(struct wilc_wfi_radiotap_hdr
));
110 PRINT_INFO(HOSTAPD_DBG
, "Monitor if : No memory to allocate skb");
114 memcpy(skb_put(skb
, size
), buff
, size
);
115 hdr
= (struct wilc_wfi_radiotap_hdr
*) skb_push(skb
, sizeof(*hdr
));
116 memset(hdr
, 0, sizeof(struct wilc_wfi_radiotap_hdr
));
117 hdr
->hdr
.it_version
= 0; /* PKTHDR_RADIOTAP_VERSION; */
118 hdr
->hdr
.it_len
= cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr
));
119 PRINT_INFO(HOSTAPD_DBG
, "Radiotap len %d\n", hdr
->hdr
.it_len
);
120 hdr
->hdr
.it_present
= cpu_to_le32
121 (1 << IEEE80211_RADIOTAP_RATE
); /* | */
122 PRINT_INFO(HOSTAPD_DBG
, "Presentflags %d\n", hdr
->hdr
.it_present
);
123 hdr
->rate
= 5; /* txrate->bitrate / 5; */
129 skb
->dev
= wilc_wfi_mon
;
130 skb_set_mac_header(skb
, 0);
131 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
132 skb
->pkt_type
= PACKET_OTHERHOST
;
133 skb
->protocol
= htons(ETH_P_802_2
);
134 memset(skb
->cb
, 0, sizeof(skb
->cb
));
141 struct tx_complete_mon_data
{
146 static void mgmt_tx_complete(void *priv
, int status
)
149 struct tx_complete_mon_data
*pv_data
= (struct tx_complete_mon_data
*)priv
;
150 u8
*buf
= pv_data
->buff
;
155 if (INFO
|| buf
[0] == 0x10 || buf
[0] == 0xb0)
156 PRINT_INFO(HOSTAPD_DBG
, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data
->size
, pv_data
->buff
);
158 PRINT_INFO(HOSTAPD_DBG
, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data
->size
, pv_data
->buff
);
163 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
164 kfree(pv_data
->buff
);
168 static int mon_mgmt_tx(struct net_device
*dev
, const u8
*buf
, size_t len
)
170 struct tx_complete_mon_data
*mgmt_tx
= NULL
;
173 PRINT_D(HOSTAPD_DBG
, "ERROR: dev == NULL\n");
177 netif_stop_queue(dev
);
178 mgmt_tx
= kmalloc(sizeof(struct tx_complete_mon_data
), GFP_ATOMIC
);
179 if (mgmt_tx
== NULL
) {
180 PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
184 mgmt_tx
->buff
= kmalloc(len
, GFP_ATOMIC
);
185 if (mgmt_tx
->buff
== NULL
) {
186 PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
194 memcpy(mgmt_tx
->buff
, buf
, len
);
195 wilc_wlan_txq_add_mgmt_pkt(dev
, mgmt_tx
, mgmt_tx
->buff
, mgmt_tx
->size
,
198 netif_wake_queue(dev
);
203 * @brief WILC_WFI_mon_xmit
206 * @return int : Return 0 on Success
211 static netdev_tx_t
WILC_WFI_mon_xmit(struct sk_buff
*skb
,
212 struct net_device
*dev
)
214 u32 rtap_len
, i
, ret
= 0;
215 struct WILC_WFI_mon_priv
*mon_priv
;
217 struct sk_buff
*skb2
;
218 struct wilc_wfi_radiotap_cb_hdr
*cb_hdr
;
220 if (wilc_wfi_mon
== NULL
)
223 mon_priv
= netdev_priv(wilc_wfi_mon
);
225 if (mon_priv
== NULL
) {
226 PRINT_ER("Monitor interface private structure is NULL\n");
231 rtap_len
= ieee80211_get_radiotap_len(skb
->data
);
232 if (skb
->len
< rtap_len
) {
233 PRINT_ER("Error in radiotap header\n");
236 /* skip the radiotap header */
237 PRINT_INFO(HOSTAPD_DBG
, "Radiotap len: %d\n", rtap_len
);
240 for (i
= 0; i
< rtap_len
; i
++)
241 PRINT_INFO(HOSTAPD_DBG
, "Radiotap_hdr[%d] %02x\n", i
, skb
->data
[i
]);
243 /* Skip the ratio tap header */
244 skb_pull(skb
, rtap_len
);
246 if (skb
->data
[0] == 0xc0)
247 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]);
249 if (skb
->data
[0] == 0xc0 && (!(memcmp(broadcast
, &skb
->data
[4], 6)))) {
250 skb2
= dev_alloc_skb(skb
->len
+ sizeof(struct wilc_wfi_radiotap_cb_hdr
));
252 memcpy(skb_put(skb2
, skb
->len
), skb
->data
, skb
->len
);
254 cb_hdr
= (struct wilc_wfi_radiotap_cb_hdr
*) skb_push(skb2
, sizeof(*cb_hdr
));
255 memset(cb_hdr
, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr
));
257 cb_hdr
->hdr
.it_version
= 0; /* PKTHDR_RADIOTAP_VERSION; */
259 cb_hdr
->hdr
.it_len
= cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr
));
261 cb_hdr
->hdr
.it_present
= cpu_to_le32(
262 (1 << IEEE80211_RADIOTAP_RATE
) |
263 (1 << IEEE80211_RADIOTAP_TX_FLAGS
));
265 cb_hdr
->rate
= 5; /* txrate->bitrate / 5; */
266 cb_hdr
->tx_flags
= 0x0004;
268 skb2
->dev
= wilc_wfi_mon
;
269 skb_set_mac_header(skb2
, 0);
270 skb2
->ip_summed
= CHECKSUM_UNNECESSARY
;
271 skb2
->pkt_type
= PACKET_OTHERHOST
;
272 skb2
->protocol
= htons(ETH_P_802_2
);
273 memset(skb2
->cb
, 0, sizeof(skb2
->cb
));
279 skb
->dev
= mon_priv
->real_ndev
;
281 PRINT_INFO(HOSTAPD_DBG
, "Skipping the radiotap header\n");
285 /* actual deliver of data is device-specific, and not shown here */
286 PRINT_INFO(HOSTAPD_DBG
, "SKB netdevice name = %s\n", skb
->dev
->name
);
287 PRINT_INFO(HOSTAPD_DBG
, "MONITOR real dev name = %s\n", mon_priv
->real_ndev
->name
);
289 /* Identify if Ethernet or MAC header (data or mgmt) */
290 memcpy(srcAdd
, &skb
->data
[10], 6);
291 memcpy(bssid
, &skb
->data
[16], 6);
292 /* if source address and bssid fields are equal>>Mac header */
293 /*send it to mgmt frames handler */
294 if (!(memcmp(srcAdd
, bssid
, 6))) {
295 mon_mgmt_tx(mon_priv
->real_ndev
, skb
->data
, skb
->len
);
298 ret
= wilc_mac_xmit(skb
, mon_priv
->real_ndev
);
303 static const struct net_device_ops wilc_wfi_netdev_ops
= {
304 .ndo_start_xmit
= WILC_WFI_mon_xmit
,
309 * @brief WILC_WFI_init_mon_interface
312 * @return int : Return 0 on Success
317 struct net_device
*WILC_WFI_init_mon_interface(const char *name
, struct net_device
*real_dev
)
322 struct WILC_WFI_mon_priv
*priv
;
324 /*If monitor interface is already initialized, return it*/
329 wilc_wfi_mon
= alloc_etherdev(sizeof(struct WILC_WFI_mon_priv
));
331 PRINT_ER("failed to allocate memory\n");
336 wilc_wfi_mon
->type
= ARPHRD_IEEE80211_RADIOTAP
;
337 strncpy(wilc_wfi_mon
->name
, name
, IFNAMSIZ
);
338 wilc_wfi_mon
->name
[IFNAMSIZ
- 1] = 0;
339 wilc_wfi_mon
->netdev_ops
= &wilc_wfi_netdev_ops
;
341 ret
= register_netdevice(wilc_wfi_mon
);
343 PRINT_ER(" register_netdevice failed (%d)\n", ret
);
346 priv
= netdev_priv(wilc_wfi_mon
);
348 PRINT_ER("private structure is NULL\n");
352 priv
->real_ndev
= real_dev
;
358 * @brief WILC_WFI_deinit_mon_interface
361 * @return int : Return 0 on Success
366 int WILC_WFI_deinit_mon_interface(void)
368 bool rollback_lock
= false;
370 if (wilc_wfi_mon
!= NULL
) {
371 PRINT_D(HOSTAPD_DBG
, "In Deinit monitor interface\n");
372 PRINT_D(HOSTAPD_DBG
, "RTNL is being locked\n");
373 if (rtnl_is_locked()) {
375 rollback_lock
= true;
377 PRINT_D(HOSTAPD_DBG
, "Unregister netdev\n");
378 unregister_netdev(wilc_wfi_mon
);
382 rollback_lock
= false;