c577e72cdc998f7fedbde0aaa74294c12e117028
[soho-sigint.git] / client-wifi / client-c / soho-sigint-wifi.c
1 #include <pcap.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <sys/socket.h>
7 //#include <netinet/in.h>
8 //#include <arpa/inet.h>
9 //#include <netinet/if_ether.h> 
10 //#include <net/ethernet.h>
11 //#include <netinet/ether.h> 
12 //#include <netinet/ip.h> 
13 //#include <linux/if.h>
14 //#include <linux/wireless.h>
15 #include <ctype.h>
16 #include <unistd.h>
17 #include "radiotap.h"
18 #include "radiotap_iter.h"
19 #include <curl/curl.h>
20 #include <json-c/json.h>
21 #include <stdbool.h>
22
23 const struct pcap_pkthdr* callback_header;
24
25 time_t start = 0;
26 char *ssid_buf[34][2] = { NULL, NULL };
27 char *probe_resp_buf[34][3] = { NULL, NULL };
28 char *probe_buf[34][2] = { NULL, NULL };
29
30 //char post_url[255] = "http://intranet.spangdorfia.com/butler/sohoinput.php";
31 char *post_url = NULL;
32
33 static uint8_t insecure = 0;
34
35 static const struct radiotap_align_size align_size_000000_00[] = {
36   [0] = { .align = 1, .size = 4, },
37   [52] = { .align = 1, .size = 4, },
38 };
39
40 typedef struct {
41   u_int8_t        it_version;
42   u_int8_t        it_pad;
43   u_int16_t       it_len;
44   u_int32_t       it_present;
45
46   u_int32_t       pad;
47   u_int8_t        flags;
48   u_int8_t        rate;
49   u_int16_t       wr_chan_freq;
50   int8_t          ant_sig;
51   int8_t          lock_quality;
52   u_int8_t        ant;
53
54 } __attribute__((__packed__)) ieee80211_radiotap;
55
56 struct json_object *obj1, *obj2, *array, *tmp1, *tmp2;
57
58 void send_data(json_object *array) {
59
60   CURL *curl;
61   CURLcode res;
62
63   struct curl_slist *headers = NULL;
64
65   headers = curl_slist_append(headers, "Accept: application/json");
66   headers = curl_slist_append(headers, "Content-Type: application/json");
67
68   //json_object *obj1 = json_object_new_object();
69   //json_object *jvs = json_object_new_string("1");
70   //json_object *japmac = json_object_new_string(ap_mac);
71   //json_object *jlat = json_object_new_double(lat);
72   //json_object *jlng = json_object_new_double(lng);
73
74   //json_object_object_add(obj1,"v", jvs);
75   //json_object_object_add(obj1,"ap_mac", japmac);
76   //json_object_object_add(obj1,"data", array);
77   //json_object_object_add(obj1,"lat", jlat);
78   //json_object_object_add(obj1,"lng", jlng);
79
80   curl = curl_easy_init();
81
82   if(curl) {
83
84     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
85     curl_easy_setopt(curl, CURLOPT_URL, post_url);
86     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
87     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
88     curl_easy_setopt(curl, CURLOPT_USERAGENT, "SoHoSIGINT");
89     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_object_to_json_string(array));
90
91     if (insecure) {
92       curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
93     }
94
95     //printf("Sending this: %s\n",json_object_to_json_string(array));
96
97     //openlog(SYSLOG_NAME, LOG_PID|LOG_CONS, LOG_USER);
98     res = curl_easy_perform(curl);
99
100     if(res != CURLE_OK) {
101       printf("There was a problem sending to %s\n", post_url);
102       //syslog (LOG_INFO, "couldn't send JSON.");
103     } else {
104       //printf("sent JSON to %s\n", post_url);
105     }
106     //closelog ();
107     curl_easy_cleanup(curl);
108     curl_slist_free_all(headers);
109     //json_object_put(obj1);
110   }
111
112   curl_global_cleanup();
113
114 }
115
116
117 void my_callback(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet) {
118
119   int err, radiotap_header_len, ssid_len, i;
120   int8_t rssi, rate, flags, fcsfail;
121   u_int16_t channel;
122   char client_mac[18];
123   char bssid_mac[18];
124   char *ssid;
125   char tmp_channel[2];
126   char tmp_rssi[1];
127
128
129   int diff;
130   if (start == 0) {
131     start = time(0);
132   }
133
134   time_t t0 = time(0);
135
136   if ( json_object_get_type(array) != json_type_array) {
137     //printf("type of json= %d\n", json_object_get_type(array) == json_type_array);
138     array = json_object_new_array();
139   };
140
141   struct ieee80211_radiotap_iterator iter;
142
143   radiotap_header_len = iter._max_length;
144
145   err = ieee80211_radiotap_iterator_init(&iter, (void*)packet, pkthdr->caplen, NULL);
146   if (err > 0) {
147   }
148
149   radiotap_header_len = iter._max_length;
150
151   fcsfail = 0;
152   while (!(err = ieee80211_radiotap_iterator_next(&iter))) {
153     if (iter.this_arg_index == IEEE80211_RADIOTAP_DBM_ANTSIGNAL) {
154       rssi = (int8_t)iter.this_arg[0];
155     }
156     if (iter.this_arg_index == IEEE80211_RADIOTAP_CHANNEL) {
157       channel = (*(uint16_t *)iter.this_arg);
158     }
159     if (iter.this_arg_index == IEEE80211_RADIOTAP_RATE) {
160       rate = (u_int8_t)iter.this_arg[0];
161     }
162     if (iter.this_arg_index == IEEE80211_RADIOTAP_FLAGS) {
163       flags = (*(u_int8_t *)iter.this_arg);
164       if (flags & IEEE80211_RADIOTAP_F_BADFCS) {
165         //printf("bad fcs\n");
166         fcsfail=1;
167         break;
168       }
169       if (flags & IEEE80211_RADIOTAP_F_FRAG) {
170         printf("frag\n");
171       }
172       if (flags & IEEE80211_RADIOTAP_F_CFP) {
173         printf("cfp\n");
174       }
175     }
176   };
177
178   sprintf(tmp_channel, "%04x", channel);
179   sprintf(tmp_rssi, "%d", rssi);
180  
181   if (pkthdr->len >= 24) {
182     u_int8_t hlen;
183     hlen = packet[2]+(packet[3]<<8); //Usually 18 or 13 in some cases
184     switch (packet[hlen]) {
185       case 0x40: //probe request
186         ssid_len=packet[61];
187         memset(ssid, 0, sizeof(ssid));
188         if (ssid_len>0) {
189           for (i=0;i<ssid_len;++i){
190             sprintf(ssid+i, "%c", packet[62+i]);
191           }
192         }
193         memset(client_mac, 0, sizeof(client_mac));
194         sprintf(client_mac, "%02x:%02x:%02x:%02x:%02x:%02x", packet[46], packet[47],packet[48],packet[49],packet[50],packet[51]);
195
196         for (i=0; i<34; i++) {
197           if (probe_buf[i][0] != NULL) {
198             if ((strcoll(probe_buf[i][0], ssid) == 0 && strcoll(probe_buf[i][1], client_mac) == 0)) {
199               break;
200             }
201           }
202           if (probe_buf[i][0] == NULL) {
203               probe_buf[i][0] = strdup(ssid);
204               probe_buf[i][1] = strdup(client_mac);
205               obj2 = json_object_new_object();
206               json_object *type = json_object_new_string("40");
207               json_object *tssid = json_object_new_string(ssid);
208               json_object *tclient_mac = json_object_new_string(client_mac);
209               json_object *tchannel = json_object_new_string(tmp_channel);
210               json_object *jrssi = json_object_new_string(tmp_rssi);
211               json_object_object_add(obj2,"type", type);
212               json_object_object_add(obj2,"ssid", tssid);
213               json_object_object_add(obj2,"client_mac", tclient_mac);
214               json_object_object_add(obj2,"channel", tchannel);
215               json_object_object_add(obj2,"rssi", jrssi);
216               json_object_array_add(array,obj2);
217               break;
218             }
219         }
220
221         break;
222       case 0x50: //probe response
223         ssid_len=packet[73];
224         for (i=0;i<ssid_len;++i){
225           sprintf(ssid+i, "%c", packet[hlen+38+i]);
226         }
227
228         sprintf(client_mac, "%02x:%02x:%02x:%02x:%02x:%02x", packet[39], packet[40],packet[41],packet[42],packet[43],packet[44]);
229         sprintf(bssid_mac, "%02x:%02x:%02x:%02x:%02x:%02x", packet[52], packet[53],packet[54],packet[55],packet[56],packet[57]);
230
231         for (i=0; i<34; i++) {
232           if (probe_resp_buf[i][0] != NULL) {
233             if ((strcoll(probe_resp_buf[i][0], ssid) == 0 && strcoll(probe_resp_buf[i][1], client_mac) == 0)) {
234               break;
235             }
236           }
237           if (probe_resp_buf[i][0] == NULL) {
238               probe_resp_buf[i][0] = strdup(ssid);
239               probe_resp_buf[i][1] = strdup(client_mac);
240               probe_resp_buf[i][2] = strdup(bssid_mac);
241               obj2 = json_object_new_object();
242               json_object *type = json_object_new_string("50");
243               json_object *tssid = json_object_new_string(ssid);
244               json_object *tclient_mac = json_object_new_string(client_mac);
245               json_object *tbssid_mac = json_object_new_string(bssid_mac);
246               json_object *tchannel = json_object_new_string(tmp_channel);
247               json_object *jrssi = json_object_new_string(tmp_rssi);
248               json_object_object_add(obj2,"type", type);
249               json_object_object_add(obj2,"ssid", tssid);
250               json_object_object_add(obj2,"client_mac", tclient_mac);
251               json_object_object_add(obj2,"bssid_mac", tbssid_mac);
252               json_object_object_add(obj2,"channel", tchannel);
253               json_object_object_add(obj2,"rssi", jrssi);
254               json_object_array_add(array,obj2);
255               break;
256             }
257         }
258         break;
259       case 0x80: //beacon
260         ssid_len=packet[73];
261         if (ssid_len>0) {
262           for (i=0;i<ssid_len;++i){
263             sprintf(ssid+i, "%c", packet[hlen+38+i]);
264           }
265         } else {
266           sprintf(ssid,"[HIDDEN]");
267         }
268
269         if (ssid_len == 15 && strlen(ssid) == 0) {
270           sprintf(ssid,"[truncated]");
271         } 
272         //printf("debug ssid: %s  fieldlen: %d strlen: %d\n", ssid, ssid_len, strlen(ssid));
273         sprintf(client_mac, "%02x:%02x:%02x:%02x:%02x:%02x", packet[52], packet[53],packet[54],packet[55],packet[56],packet[57]);
274
275         for (i=0; i<34; i++) {
276           if (ssid_buf[i][0] != NULL) {
277             if ((strcoll(ssid_buf[i][0], ssid) == 0 && strcoll(ssid_buf[i][1], client_mac) == 0)) {
278               break;
279             }
280           }
281           if (ssid_buf[i][0] == NULL) {
282               ssid_buf[i][0] = strdup(ssid);
283               ssid_buf[i][1] = strdup(client_mac);
284               obj2 = json_object_new_object();
285               json_object *type = json_object_new_string("80");
286               json_object *tssid = json_object_new_string(ssid);
287               json_object *tclient_mac = json_object_new_string(client_mac);
288               json_object *tchannel = json_object_new_string(tmp_channel);
289               json_object *jrssi = json_object_new_string(tmp_rssi);
290               json_object_object_add(obj2,"type", type);
291               json_object_object_add(obj2,"ssid", tssid);
292               json_object_object_add(obj2,"bssid", tclient_mac);
293               json_object_object_add(obj2,"channel", tchannel);
294               json_object_object_add(obj2,"rssi", jrssi);
295               json_object_array_add(array,obj2);
296               break;
297             }
298         }
299         break;
300     }
301   };
302
303   diff = (t0 - start);
304
305   if (diff >= 5) {
306     //printf("time to barf!\n");
307     //for (i=0; i<34; i++) {
308     //  printf("barf beacons: buffer %d, ssid: %s \t\t mac: %s  channel: %s rssi: %s\n", i, ssid_buf[i][0], ssid_buf[i][1], ssid_buf[i][2], ssid_buf[i][3]);
309     //}
310     //for (i=0; i<34; i++) {
311     //  printf("barf probe reponses: buffer %d, ssid: %s \t mac: %s mac: %s  channel: %s rssi: %s\n", i, probe_resp_buf[i][0], probe_resp_buf[i][1], probe_resp_buf[i][2], probe_resp_buf[i][3], probe_resp_buf[i][4]);
312     //}
313     for (i=0; i<34; i++) {
314       //printf("barf probes: buffer %d, ssid: %s \t mac: %s channel: %s rssi: %s\n", i, probe_buf[i][0], probe_buf[i][1], probe_buf[i][2], probe_buf[i][3]);
315     }
316
317     send_data(array);
318     //printf ("The json object created: %s\n",json_object_to_json_string(array));
319     json_object_put(array);
320
321     memset(ssid_buf, 0, sizeof(ssid_buf));
322     memset(probe_resp_buf, 0, sizeof(probe_resp_buf));
323     memset(probe_buf, 0, sizeof(probe_buf));
324     start = time(0);
325   }
326   //printf("rate: %d  channel: %04x  rssi: %d\n", rate, channel, rssi);
327 }
328
329 int main(int argc,char **argv)
330 {
331   int c;
332   char *dev = NULL; 
333   char errbuf[PCAP_ERRBUF_SIZE];
334   pcap_t* pcap;
335   struct bpf_program fp;      /* hold compiled program     */
336   bpf_u_int32 maskp;          /* subnet mask               */
337   bpf_u_int32 netp;           /* ip                        */
338   u_char* args = NULL;
339   char filter_exp[] = "";
340   char *totpacket = NULL;
341
342   while ((c = getopt (argc, argv, "ha:i:p:")) != -1)
343     switch (c) {
344       case 'a':
345         totpacket = optarg;
346         break;
347       case 'i':
348         dev = optarg;
349         break;
350       case 'p':
351         post_url = optarg;
352         break;
353       case 'h':
354         printf("./disect -a -i\n\t-a : number of packets to sniff. (default 10)\n\t-i : wlan interface.\n\t-p : URL for your collector.\n");
355         exit(0);
356       default:
357         return 0;
358      }
359
360   if (totpacket == NULL) {
361     totpacket="-1";
362     printf("-a not specified... setting to 10.\n");
363   }
364
365   if (dev == NULL) {
366     printf("You forgot -i\n");
367     exit(0);
368   }
369
370   if (post_url == NULL) {
371     printf("You forgot -p\n");
372     exit(0);
373   }
374
375   printf ("%s %s\n", totpacket, dev);
376
377   if(dev == NULL) {
378     printf("%s\n",errbuf); 
379     exit(1); 
380   }
381
382   /* ask pcap for the network address and mask of the device */
383   pcap_lookupnet(dev,&netp,&maskp,errbuf);
384
385   /* open device for reading. NOTE: defaulting to
386    * promiscuous mode*/
387   pcap = pcap_open_live(dev,2346,1,1000,errbuf);
388   pcap_set_promisc(pcap, 1);
389
390   if(pcap == NULL) {
391     printf("pcap_open_live(): %s\n",errbuf); 
392     exit(1); 
393   }
394
395   pcap_set_datalink(pcap, DLT_IEEE802_11);
396   pcap_set_datalink(pcap, DLT_IEEE802_11_RADIO_AVS);
397   pcap_set_datalink(pcap, DLT_IEEE802_11_RADIO);
398
399   //pcap_setnonblock(pcap, 1, errbuf); 
400
401   int link_layer_type = pcap_datalink(pcap);
402
403   //printf("type: %d\n", link_layer_type);
404
405   if (link_layer_type == DLT_PRISM_HEADER ||
406       link_layer_type == DLT_IEEE802_11_RADIO ||
407       link_layer_type == DLT_IEEE802_11_RADIO_AVS ||
408       link_layer_type == DLT_IEEE802_11 ||
409       link_layer_type == DLT_PPI ||
410       link_layer_type == 127 ) {
411     if (pcap_compile(pcap, &fp, filter_exp, 0, netp) == -1) {
412       fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(pcap));
413       exit(EXIT_FAILURE);
414     }
415     if (pcap_setfilter(pcap, &fp) == -1) {
416       fprintf(stderr, "Couldn't install filter %s: %s\n",
417         filter_exp, pcap_geterr(pcap));
418       exit(EXIT_FAILURE);
419     }
420     printf("starting\n");
421
422     pcap_loop(pcap,atoi(totpacket),my_callback,NULL);
423   } else {
424     fprintf(stderr, "Not using the Wi-Fi interface, are you testing something?\n");
425   }
426   fprintf(stdout,"\nfinished\n");
427   return 0;
428 }
429
430