#include #include #include "wifi/wifi_conf.h" // #ifndef CONFIG_WLAN // #define CONFIG_WLAN 1 // #endif #if CONFIG_WLAN // #include extern void _promisc_deinit(void *padapter); extern int _promisc_recv_func(void *padapter, void *rframe); extern int _promisc_set(rtw_rcr_level_t enabled, void (*callback)(unsigned char*, unsigned int, void*), unsigned char len_used); extern unsigned char _is_promisc_enabled(void); extern int _promisc_get_fixed_channel(void * fixed_bssid, u8 *ssid, int * ssid_length); extern void _promisc_filter_by_ap_and_phone_mac(u8 enable, void *ap_mac, void *phone_mac); // Add extra interfaces to make release sdk able to determine promisc API linking void promisc_deinit(void *padapter) { #if CONFIG_PROMISC _promisc_deinit(padapter); #endif } int promisc_recv_func(void *padapter, void *rframe) { // Never reach here if not define CONFIG_PROMISC #if CONFIG_PROMISC return _promisc_recv_func(padapter, rframe); #else return 0; #endif } int promisc_recv_lens_func(void *padapter, u8 *payload, u8 plen) { // Never reach here if not define CONFIG_PROMISC #if CONFIG_PROMISC #if CONFIG_UNSUPPORT_PLCPHDR_RPT return _promisc_recv_lens_func(padapter, payload, plen); #else return 0; #endif #else return 0; #endif } int promisc_filter_with_len(u16 len) { // Never reach here if not define CONFIG_PROMISC #if CONFIG_PROMISC #if CONFIG_UNSUPPORT_PLCPHDR_RPT return _promisc_filter_with_len(len); #else return -1; #endif #else return -1; #endif } int promisc_set(rtw_rcr_level_t enabled, void (*callback)(unsigned char*, unsigned int, void*), unsigned char len_used) { #if CONFIG_PROMISC return _promisc_set(enabled, callback, len_used); #else return -1; #endif } unsigned char is_promisc_enabled(void) { #if CONFIG_PROMISC return _is_promisc_enabled(); #else return 0; #endif } int promisc_get_fixed_channel(void *fixed_bssid, u8 *ssid, int *ssid_length) { #if CONFIG_PROMISC return _promisc_get_fixed_channel(fixed_bssid, ssid, ssid_length); #else return 0; #endif } void promisc_filter_by_ap_and_phone_mac(u8 enable, void *ap_mac, void *phone_mac) { #if CONFIG_PROMISC _promisc_filter_by_ap_and_phone_mac(enable, ap_mac, phone_mac); #endif } // End of Add extra interfaces struct eth_frame { struct eth_frame *prev; struct eth_frame *next; unsigned char da[6]; unsigned char sa[6]; unsigned int len; unsigned char type; signed char rssi; }; struct eth_buffer { struct eth_frame *head; struct eth_frame *tail; }; static struct eth_buffer eth_buffer; #if CONFIG_PROMISC #define MAX_PACKET_FILTER_INFO 5 #define FILTER_ID_INIT_VALUE 10 rtw_packet_filter_info_t paff_array[MAX_PACKET_FILTER_INFO]={0, 0, 0, 0, 0}; static u8 packet_filter_enable_num = 0; void promisc_init_packet_filter() { int i = 0; for(i=0; ioffset; paff_array[i].patt.mask_size = patt->mask_size; paff_array[i].patt.mask = rtw_malloc(patt->mask_size); memcpy(paff_array[i].patt.mask, patt->mask, patt->mask_size); paff_array[i].patt.pattern= rtw_malloc(patt->mask_size); memcpy(paff_array[i].patt.pattern, patt->pattern, patt->mask_size); paff_array[i].rule = rule; paff_array[i].enable = 0; return 0; } int promisc_enable_packet_filter(u8 filter_id) { int i = 0; while(i < MAX_PACKET_FILTER_INFO){ if(paff_array[i].filter_id == filter_id) break; i++; } if(i == MAX_PACKET_FILTER_INFO) return -1; paff_array[i].enable = 1; packet_filter_enable_num++; return 0; } int promisc_disable_packet_filter(u8 filter_id) { int i = 0; while(i < MAX_PACKET_FILTER_INFO){ if(paff_array[i].filter_id == filter_id) break; i++; } if(i == MAX_PACKET_FILTER_INFO) return -1; paff_array[i].enable = 0; packet_filter_enable_num--; return 0; } int promisc_remove_packet_filter(u8 filter_id) { int i = 0; while(i < MAX_PACKET_FILTER_INFO){ if(paff_array[i].filter_id == filter_id) break; i++; } if(i == MAX_PACKET_FILTER_INFO) return -1; paff_array[i].filter_id = FILTER_ID_INIT_VALUE; paff_array[i].enable = 0; paff_array[i].patt.mask_size = 0; paff_array[i].rule = 0; if(paff_array[i].patt.mask){ rtw_free(paff_array[i].patt.mask); paff_array[i].patt.mask = NULL; } if(paff_array[i].patt.pattern){ rtw_free(paff_array[i].patt.pattern); paff_array[i].patt.pattern = NULL; } return 0; } #endif /* Make callback simple to prevent latency to wlan rx when promiscuous mode */ static void promisc_callback(unsigned char *buf, unsigned int len, void* userdata) { struct eth_frame *frame = (struct eth_frame *) rtw_malloc(sizeof(struct eth_frame)); _lock lock; _irqL irqL; if(frame) { frame->prev = NULL; frame->next = NULL; memcpy(frame->da, buf, 6); memcpy(frame->sa, buf+6, 6); frame->len = len; frame->rssi = ((ieee80211_frame_info_t *)userdata)->rssi; rtw_enter_critical(&lock, &irqL); if(eth_buffer.tail) { eth_buffer.tail->next = frame; frame->prev = eth_buffer.tail; eth_buffer.tail = frame; } else { eth_buffer.head = frame; eth_buffer.tail = frame; } rtw_exit_critical(&lock, &irqL); } } struct eth_frame* retrieve_frame(void) { struct eth_frame *frame = NULL; _lock lock; _irqL irqL; rtw_enter_critical(&lock, &irqL); if(eth_buffer.head) { frame = eth_buffer.head; if(eth_buffer.head->next) { eth_buffer.head = eth_buffer.head->next; eth_buffer.head->prev = NULL; } else { eth_buffer.head = NULL; eth_buffer.tail = NULL; } } rtw_exit_critical(&lock, &irqL); return frame; } static void promisc_test(int duration, unsigned char len_used) { int ch; unsigned int start_time; struct eth_frame *frame; eth_buffer.head = NULL; eth_buffer.tail = NULL; wifi_enter_promisc_mode(); wifi_set_promisc(RTW_PROMISC_ENABLE, promisc_callback, len_used); for(ch = 1; ch <= 13; ch ++) { if(wifi_set_channel(ch) == 0) pr_info("Switch to channel(%d)", ch); start_time = rtw_get_current_time(); while(1) { unsigned int current_time = rtw_get_current_time(); if(rtw_systime_to_ms(current_time - start_time) < duration) { frame = retrieve_frame(); if(frame) { int i; pr_info("DA:"); for(i = 0; i < 6; i ++) pr_info(" %02x", frame->da[i]); pr_info(", SA:"); for(i = 0; i < 6; i ++) pr_info(" %02x", frame->sa[i]); pr_info(", len=%d", frame->len); pr_info(", RSSI=%d", frame->rssi); rtw_free((void *) frame); } else rtw_mdelay_os(1); //delay 1 tick } else break; } } wifi_set_promisc(RTW_PROMISC_DISABLE, NULL, 0); while((frame = retrieve_frame()) != NULL) rtw_free((void *) frame); } static void promisc_callback_all(unsigned char *buf, unsigned int len, void* userdata) { struct eth_frame *frame = (struct eth_frame *) rtw_malloc(sizeof(struct eth_frame)); _lock lock; _irqL irqL; if(frame) { frame->prev = NULL; frame->next = NULL; #if CONFIG_UNSUPPORT_PLCPHDR_RPT if(((ieee80211_frame_info_t *)userdata)->type == RTW_RX_UNSUPPORT){ //NOTICE: buf structure now is rtw_rx_info_t. frame->type = 0xFF; memset(frame->da, 0, 6); memset(frame->sa, 0, 6); } else #endif { memcpy(frame->da, buf+4, 6); memcpy(frame->sa, buf+10, 6); frame->type = *buf; } frame->len = len; /* * type is the first byte of Frame Control Field of 802.11 frame * If the from/to ds information is needed, type could be reused as follows: * frame->type = ((((ieee80211_frame_info_t *)userdata)->i_fc & 0x0100) == 0x0100) ? 2 : 1; * 1: from ds; 2: to ds */ frame->rssi = ((ieee80211_frame_info_t *)userdata)->rssi; rtw_enter_critical(&lock, &irqL); if(eth_buffer.tail) { eth_buffer.tail->next = frame; frame->prev = eth_buffer.tail; eth_buffer.tail = frame; } else { eth_buffer.head = frame; eth_buffer.tail = frame; } rtw_exit_critical(&lock, &irqL); } } static void promisc_test_all(int duration, unsigned char len_used) { int ch; unsigned int start_time; struct eth_frame *frame; eth_buffer.head = NULL; eth_buffer.tail = NULL; wifi_enter_promisc_mode(); wifi_set_promisc(RTW_PROMISC_ENABLE_2, promisc_callback_all, len_used); for(ch = 1; ch <= 13; ch ++) { if(wifi_set_channel(ch) == 0) pr_info("Switch to channel(%d)", ch); start_time = rtw_get_current_time(); while(1) { unsigned int current_time = rtw_get_current_time(); if(rtw_systime_to_ms(current_time - start_time) < duration) { frame = retrieve_frame(); if(frame) { int i; pr_info("TYPE: 0x%x, ", frame->type); pr_info("DA:"); for(i = 0; i < 6; i ++) pr_info(" %02x", frame->da[i]); pr_info(", SA:"); for(i = 0; i < 6; i ++) pr_info(" %02x", frame->sa[i]); pr_info(", len=%d", frame->len); pr_info(", RSSI=%d", frame->rssi); rtw_free((void *) frame); } else rtw_mdelay_os(1); //delay 1 tick } else break; } } wifi_set_promisc(RTW_PROMISC_DISABLE, NULL, 0); while((frame = retrieve_frame()) != NULL) rtw_free((void *) frame); } void cmd_promisc(int argc, char **argv) { int duration; #if CONFIG_PROMISC wifi_init_packet_filter(); #endif if((argc == 2) && ((duration = atoi(argv[1])) > 0)) //promisc_test(duration, 0); promisc_test_all(duration, 0); else if((argc == 3) && ((duration = atoi(argv[1])) > 0) && (strcmp(argv[2], "with_len") == 0)) promisc_test(duration, 1); else pr_info("Usage: %s DURATION_SECONDS [with_len]", argv[0]); } #endif //#if CONFIG_WLAN