]> git.sesse.net Git - wardrive/blob - bt-remote.c
More test data.
[wardrive] / bt-remote.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <bluetooth/bluetooth.h>
8 #include <bluetooth/rfcomm.h>
9 #include <sys/ioctl.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 #include <sys/types.h>
13 #include <dirent.h>
14     
15 unsigned int use_acpi;
16 unsigned int monitor_bat;
17 unsigned int bat_percentage;
18 unsigned int bat_time;
19 unsigned int bat_available;
20 unsigned int bat_ac;
21 unsigned int bat_charging;
22 unsigned int bat_full_capacity[3];  // I doubt a machine has more than 3 batteries...
23
24 void update_battery_time()
25 {
26         DIR *batteries, *ac_adapters;
27         struct dirent *this_battery, *this_adapter;
28         FILE *acpi;
29         char battery_state[PATH_MAX];
30         int rate = 1, remain = 0, current = 0;
31         static int total_remain = 0, total_cap = 0;
32         int batno = 0;
33         const int info_res = 5;
34         static int info_timer = 0;
35         char buf[256];
36
37         ac_adapters = opendir("/proc/acpi/ac_adapter");
38
39         while (ac_adapters != NULL && ((info_timer % info_res) == 0) && 
40                         ((this_adapter = readdir(ac_adapters)) != NULL)) {
41                 if (this_adapter->d_name[0] == '.')
42                         continue;
43                 // safe overloaded use of battery_state path var
44                 snprintf(battery_state, sizeof(battery_state), 
45                                 "/proc/acpi/ac_adapter/%s/state", this_adapter->d_name);
46                 if ((acpi = fopen(battery_state, "r")) == NULL)
47                         continue;
48                 if (acpi != NULL) {
49                         while(fgets(buf, 128, acpi)) {
50                                 if (strstr(buf, "on-line") != NULL)
51                                         bat_ac = 1;
52                                 else
53                                         bat_ac = 0;
54                         }
55                         fclose(acpi);
56                 }
57         }
58
59         if (ac_adapters != NULL)
60                 closedir(ac_adapters);
61
62         batteries = opendir("/proc/acpi/battery");
63
64         if (batteries == NULL)
65                 bat_available = 0;
66         else
67                 bat_available = 1;
68
69         if (!bat_available || ((info_timer % info_res) == 0)) {
70                 bat_percentage = 0;
71                 bat_time = 0;
72                 bat_charging = 0;
73                 total_remain = total_cap = 0;
74         }
75
76         while (batteries != NULL && ((info_timer % info_res) == 0) && 
77                         ((this_battery = readdir(batteries)) != NULL)) {
78                 if (this_battery->d_name[0] == '.')
79                         continue;
80                 snprintf(battery_state, sizeof(battery_state), 
81                                 "/proc/acpi/battery/%s/state", this_battery->d_name);
82                 if ((acpi = fopen(battery_state, "r")) == NULL)
83                         continue;
84                 while (fgets(buf, 128, acpi))
85                 {
86                         if (strncmp(buf, "present:", 8 ) == 0)
87                         {
88                                 // No information for this battery
89                                 if (strstr(buf, "no" ))
90                                         continue;
91                         }
92                         else if (strncmp(buf, "charging state:", 15) == 0)
93                         {
94                                 // the space makes it different than discharging
95                                 if (strstr(buf, " charging" ))
96                                         bat_charging = 1;
97                         }
98                         else if (strncmp(buf, "present rate:", 13) == 0)
99                                 rate = atoi(buf + 25);
100                         else if (strncmp(buf, "remaining capacity:", 19) == 0)
101                         {
102                                 remain = atoi(buf + 25);
103                                 total_remain += remain;
104                         }
105                         else if (strncmp(buf, "present voltage:", 17) == 0)
106                                 current = atoi(buf + 25);
107                 }
108                 total_cap += bat_full_capacity[batno];
109                 fclose(acpi);
110                 if (bat_charging)
111                         bat_time += (((float)(bat_full_capacity[batno] - remain) / 
112                                                 rate) * 3600);
113                 else
114                         bat_time += (((float)(remain) / rate) * 3600);
115                 batno++;
116         }
117         if (total_cap > 0)
118                 bat_percentage = ((float)(total_remain) / total_cap) * 100;
119         info_timer++;
120
121         if (batteries != NULL)
122                 closedir(batteries);
123 }
124
125 int parse_packet(unsigned char *buf, unsigned bytes, int sock)
126 {
127         char *ptr;
128         int ret = 0;
129         buf[bytes + 1] = 0;
130
131         ptr = strtok((char *)buf, "\n");
132         while (ptr) {
133                 if (strncmp(ptr, "*NETWORK: ", 10) == 0) {
134                         char bssid[32];
135                         int crypted, weak, signal, noise;
136                         if (sscanf(ptr, "*NETWORK: %s %d %d %d %d", bssid, &crypted, &weak, &signal, &noise) != 5) {
137                                 printf("Couldn't parse NETWORK packet\n");
138                         } else {
139                                 if (strcmp(bssid, "00:18:39:0A:97:C9") == 0) {
140                                 //if (strcmp(bssid, "00:13:10:1F:2A:1C") == 0) {
141                                         static int last_crypted = 0;
142                                         char str1[64], str2[64], str3[64], str4[64], str5[64], str6[64];
143                                         short len;
144                                         sprintf(str1, "Crypted: %d", crypted);
145                                         sprintf(str2, "Weak IVs: %d", weak);
146                                         sprintf(str3, "Signal level: %d dB", signal);
147                                         sprintf(str4, "Noise level: %d dB", noise);
148                                         sprintf(str5, "");
149
150                                         update_battery_time();
151                                         if (bat_ac)
152                                                 sprintf(str6, "On AC power");
153                                         else
154                                                 sprintf(str6, "Battery left: %uh%um", bat_time / 3600, (bat_time / 60) % 60);
155                                         
156                                         write(sock, "\000\001", 2);
157                                         len = htons(2 * 6 + strlen(str1) + strlen(str2) + strlen(str3) + strlen(str4) + strlen(str5) + strlen(str6));
158                                         write(sock, (char*)&len, 2);
159                                         
160                                         len = htons(strlen(str1));
161                                         write(sock, (char*)&len, 2);
162                                         write(sock, str1, strlen(str1));
163
164                                         len = htons(strlen(str2));
165                                         write(sock, (char*)&len, 2);
166                                         write(sock, str2, strlen(str2));
167
168                                         len = htons(strlen(str3));
169                                         write(sock, (char*)&len, 2);
170                                         write(sock, str3, strlen(str3));
171
172                                         len = htons(strlen(str4));
173                                         write(sock, (char*)&len, 2);
174                                         write(sock, str4, strlen(str4));
175                                 
176                                         len = htons(strlen(str5));
177                                         write(sock, (char*)&len, 2);
178                                         write(sock, str5, strlen(str5));
179                                 
180                                         len = htons(strlen(str6));
181                                         write(sock, (char*)&len, 2);
182                                         write(sock, str6, strlen(str6));
183                                 
184                                         // vibrate 250ms for every 10k packets
185                                         if (crypted/10000 != last_crypted/10000) {
186                                                 write(sock, "\000\016\000\002\000\372", 6);
187                                         }
188                                         
189                                         // vibrate 1750ms extra for every 100k packets
190                                         if (crypted/100000 != last_crypted/100000) {
191                                                 write(sock, "\000\016\000\002\006\326", 6);
192                                         }
193
194                                         last_crypted = crypted;
195
196                                         ret = 1;
197                                 }
198                         }
199                 }
200                 ptr = strtok(NULL, "\n");
201         }
202
203         return ret;
204 }
205
206 int main(int argc, char **argv)
207 {
208         struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
209         struct sockaddr_in addr;
210         unsigned char buf[1024] = { 0 };
211         char initstr[] = "!1 ENABLE NETWORK bssid,cryptpackets,weakpackets,signal,noise\n";
212         int s, client, kismet, bytes_read;
213         size_t opt = sizeof(rem_addr);
214         unsigned one = 1;
215         
216         // allocate socket
217         s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
218         
219         // bind socket to port 1 of the first available 
220         // local bluetooth adapter
221         loc_addr.rc_family = AF_BLUETOOTH;
222         loc_addr.rc_bdaddr = *BDADDR_ANY;
223         loc_addr.rc_channel = (uint8_t) 1;
224         bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
225
226         // put socket into listening mode
227         listen(s, 1);
228
229         // accept one connection
230         client = accept(s, (struct sockaddr *)&rem_addr, &opt);
231
232         ba2str( &rem_addr.rc_bdaddr, buf );
233         fprintf(stderr, "accepted connection from %s\n", buf);
234         memset(buf, 0, sizeof(buf));
235
236         ioctl(client, FIONBIO, &one);
237         
238         // connect to kismet
239         kismet = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
240         addr.sin_family = AF_INET;
241         addr.sin_addr.s_addr = inet_addr("127.0.0.1");
242         addr.sin_port = htons(2501);
243
244         if (connect(kismet, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
245                 perror("connect()");
246                 exit(1);
247         }
248         ioctl(kismet, FIONBIO, &one);
249         write(kismet, initstr, strlen(initstr));
250         
251         printf("Connected to Kismet.\n");
252
253         // read data from the client
254         for ( ;; ) {
255                 int flag = 1;
256
257                 // gobble up data from the phone
258                 bytes_read = read(client, buf, sizeof(buf) - 1);
259                 if( bytes_read > 0 ) {
260                         unsigned i;
261                         printf("received [");
262                         for (i = 0; i < bytes_read; ++i)
263                                 printf("0x%02x ", buf[i]);
264                         printf("]\n");
265
266                         // don't bother with any sophisticated parsing
267                         while (bytes_read > 4) {
268                                 int command = (buf[0] << 8) | buf[1];
269                                 int len = (buf[2] << 8) | buf[3];
270         
271                                 // menu item
272                                 if (command == 3) {
273                                         int no = (buf[4] << 8) | buf[5];
274                                         if (no == 5) {
275                                                 system("killall kismet_client");
276                                                 exit(0);
277                                         }
278                                 }
279
280                                 memmove(buf, buf + len + 4, bytes_read - (len + 4));
281                                 bytes_read -= len + 4;
282                         }
283                 }
284                 
285                 // read from kismet
286                 bytes_read = read(kismet, buf, sizeof(buf));
287                 if( bytes_read > 0 ) {
288                         unsigned i;
289                         for (i = 0; i < bytes_read; ++i)
290                                 printf("%c", buf[i]);
291
292                         flag = parse_packet(buf, bytes_read, client);
293                 }
294
295                 if (flag) {
296                         // alive?
297                         write(client, "\000\012\000\000", 4);
298                         sleep(1);
299                 }
300         }
301
302         // close connection
303         close(client);
304         close(s);
305         return 0;
306 }
307