Added wifi sniffer basics
[soho-sigint.git] / client-wifi / disect5 / soho-sigint-wifi.c
1 /**********************************************************************
2 This is a wireless pcap capture and parser by example.
3 By: Russell Handorf
4 **********************************************************************/
5
6 #include <pcap.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <errno.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <netinet/if_ether.h> 
14 #include <net/ethernet.h>
15 #include <netinet/ether.h> 
16 #include <netinet/ip.h> 
17 #include <linux/if.h>
18 #include <linux/wireless.h>
19 #include <ctype.h>
20 #include <unistd.h>
21 #include "radiotap.h"
22 #include "radiotap_iter.h"
23
24 const struct pcap_pkthdr* callback_header;
25
26 static const struct radiotap_align_size align_size_000000_00[] = {
27   [0] = { .align = 1, .size = 4, },
28   [52] = { .align = 1, .size = 4, },
29 };
30
31 typedef struct {
32   u_int8_t        it_version;
33   u_int8_t        it_pad;
34   u_int16_t       it_len;
35   u_int32_t       it_present;
36
37   u_int32_t       pad;
38   u_int8_t        flags;
39   u_int8_t        rate;
40   u_int16_t       wr_chan_freq;
41   int8_t          ant_sig;
42   int8_t          lock_quality;
43   u_int8_t        ant;
44
45 } __attribute__((__packed__)) ieee80211_radiotap;
46
47 typedef struct {
48   unsigned short                  fc;
49   unsigned short                  durid;
50   u_char  a1[6];
51   u_char  a2[6];
52   u_char  a3[6];
53   unsigned short                  seq;
54   u_char  a4[6];
55 } __attribute__((__packed__)) dot11_header;
56
57
58 void format_mac(u_char * mac, char * f) {
59   sprintf(f, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
60 }
61
62 void my_callback(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet) {
63
64   //printf("packet size: %d\n", pkthdr->len);
65   //printf("packet: %02x \n", packet);
66   //printf("%u\n", packet);
67   int err, radiotap_header_len, ssid_len, i;
68   int8_t rssi, rate;
69   u_int16_t channel;
70   char client_mac[18];
71   char ssid[38];
72
73   struct ieee80211_radiotap_iterator iter;
74
75   radiotap_header_len = iter._max_length;
76   dot11_header * dot_head = (dot11_header*) (packet + radiotap_header_len * sizeof(char) );
77
78   err = ieee80211_radiotap_iterator_init(&iter, (void*)packet, pkthdr->caplen, NULL);
79   if (err > 0) {
80   }
81
82   radiotap_header_len = iter._max_length;
83
84   while (!(err = ieee80211_radiotap_iterator_next(&iter))) {
85     if (iter.this_arg_index == IEEE80211_RADIOTAP_DBM_ANTSIGNAL) {
86       rssi = (int8_t)iter.this_arg[0];
87     }
88     if (iter.this_arg_index == IEEE80211_RADIOTAP_CHANNEL) {
89       channel = (*(uint16_t *)iter.this_arg);
90     }
91     if (iter.this_arg_index == IEEE80211_RADIOTAP_RATE) {
92       rate = (u_int8_t)iter.this_arg[0];
93     }
94     /* if (iter.this_arg_index == IEEE80211_RADIOTAP_DBM_ANTNOISE) { */
95     /*   noise = (int8_t)iter.this_arg[0]; */
96     /* } */
97   };
98
99   if (pkthdr->len >= 24) {
100     u_int8_t hlen;
101     hlen = packet[2]+(packet[3]<<8); //Usually 18 or 13 in some cases
102     switch (packet[hlen]) {
103       case 0x40:
104         //memset(ssid, 0, sizeof(ssid));
105         printf("Probe request\n");
106         printf("probe request client mac: %02x:%02x:%02x:%02x:%02x:%02x\n", packet[44], packet[45],packet[46],packet[47],packet[48],packet[49]);
107         ssid_len=packet[59];
108         printf("probe size: %d\n", ssid_len);
109         if (ssid_len>0) {
110           for (i=0;i<ssid_len;++i){
111             sprintf(ssid+i, "%c", packet[60+i]);
112           }
113           printf("probe ssid: %s\n", ssid);
114         }
115         break;
116       case 0x50:
117         printf("Probe response\n");
118         printf("probe response client mac: %02x:%02x:%02x:%02x:%02x:%02x\n", packet[38], packet[39],packet[40],packet[41],packet[42],packet[43]);
119         printf("probe response bssid mac: %02x:%02x:%02x:%02x:%02x:%02x\n", packet[44], packet[45],packet[46],packet[47],packet[48],packet[49]);
120         ssid_len=packet[71];
121         printf("probe response size: %d\n", ssid_len);
122         for (i=0;i<ssid_len;++i){
123           sprintf(ssid+i, "%c", packet[72+i]);
124         }
125         printf("probe response ssid: %s\n", ssid);
126
127         break;
128       case 0x80:
129         //memset(&ssid[0], 0, sizeof(ssid));
130         printf("Beacon\n");
131         ssid_len=packet[hlen+37];
132         printf("size: %d\n", ssid_len);
133         for (i=0;i<ssid_len;++i){
134           //printf("%c\n", packet[hlen+38+i]);
135           sprintf(ssid+i, "%c", packet[hlen+38+i]);
136           //puts(ssid);
137           //printf("ssid: %c\n", ssid);
138           //memcpy(ssid,packet[hlen+38+i],2); 
139           //ssid+=packet[hlen+38+i];
140           //printf("counter: %d - ssid: %c\n", (hlen+38+i), packet[hlen+38+i]);
141         }
142         printf("BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n", packet[50], packet[51],packet[52],packet[53],packet[54],packet[55]);
143         printf("ssid: %s\n", ssid);
144         break;
145     }
146   };
147
148   //format_mac(dot_head->a2, client_mac);
149
150   printf("rate: %d  channel: %04x  rssi: %d\n", rate, channel, rssi);
151 }
152
153 int main(int argc,char **argv)
154 {
155   int c;
156   char *dev = NULL; 
157   char errbuf[PCAP_ERRBUF_SIZE];
158   pcap_t* pcap;
159   struct bpf_program fp;      /* hold compiled program     */
160   bpf_u_int32 maskp;          /* subnet mask               */
161   bpf_u_int32 netp;           /* ip                        */
162   u_char* args = NULL;
163   char filter_exp[] = "";
164   char *totpacket = NULL;
165
166   while ((c = getopt (argc, argv, "ha:i:")) != -1)
167     switch (c) {
168       case 'a':
169         totpacket = optarg;
170         break;
171       case 'i':
172         dev = optarg;
173         break;
174       case 'h':
175         printf("./disect -a -i\n\t-a : number of packets to sniff. (default 10)\n\t-i : wlan interface.\n");
176         exit(0);
177       default:
178         return 0;
179      }
180
181   if (totpacket == NULL) {
182     totpacket="-1";
183     printf("-a not specified... setting to 10.\n");
184   }
185
186   if (dev == NULL) {
187     printf("You forgot -i\n");
188     exit(0);
189   }
190
191   printf ("%s %s\n", totpacket, dev);
192
193   if(dev == NULL) {
194     printf("%s\n",errbuf); 
195     exit(1); 
196   }
197
198   /* ask pcap for the network address and mask of the device */
199   pcap_lookupnet(dev,&netp,&maskp,errbuf);
200
201   /* open device for reading. NOTE: defaulting to
202    * promiscuous mode*/
203   pcap = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
204   pcap_set_promisc(pcap, 1);
205
206   if(pcap == NULL) {
207     printf("pcap_open_live(): %s\n",errbuf); 
208     exit(1); 
209   }
210
211   pcap_set_datalink(pcap, DLT_IEEE802_11);
212   pcap_set_datalink(pcap, DLT_IEEE802_11_RADIO_AVS);
213   pcap_set_datalink(pcap, DLT_IEEE802_11_RADIO);
214
215   pcap_setnonblock(pcap, 1, errbuf); 
216
217   int link_layer_type = pcap_datalink(pcap);
218
219   //printf("type: %d\n", link_layer_type);
220
221   if (link_layer_type == DLT_PRISM_HEADER ||
222       link_layer_type == DLT_IEEE802_11_RADIO ||
223       link_layer_type == DLT_IEEE802_11_RADIO_AVS ||
224       link_layer_type == DLT_IEEE802_11 ||
225       link_layer_type == DLT_PPI ||
226       link_layer_type == 127 ) {
227     if (pcap_compile(pcap, &fp, filter_exp, 0, netp) == -1) {
228       fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(pcap));
229       exit(EXIT_FAILURE);
230     }
231     if (pcap_setfilter(pcap, &fp) == -1) {
232       fprintf(stderr, "Couldn't install filter %s: %s\n",
233         filter_exp, pcap_geterr(pcap));
234       exit(EXIT_FAILURE);
235     }
236     printf("starting\n");
237
238     pcap_loop(pcap,atoi(totpacket),my_callback,NULL);
239   } else {
240     fprintf(stderr, "Not using the Wi-Fi interface, are you testing something?\n");
241   }
242   fprintf(stdout,"\nfinished\n");
243   return 0;
244 }
245