]> git.sesse.net Git - wardrive/blob - bt-remote.c
77ca2702273ab40e5b14321bfe65ec2d3bf313dd
[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:0D:54:A0:27:7F") == 0) {
140                                         static int last_crypted = 0;
141                                         char str1[64], str2[64], str3[64], str4[64], str5[64], str6[64];
142                                         short len;
143                                         sprintf(str1, "Crypted: %d", crypted);
144                                         sprintf(str2, "Weak IVs: %d", weak);
145                                         sprintf(str3, "Signal level: %d dB", signal);
146                                         sprintf(str4, "Noise level: %d dB", noise);
147                                         sprintf(str5, "");
148
149                                         update_battery_time();
150                                         if (bat_ac)
151                                                 sprintf(str6, "On AC power");
152                                         else
153                                                 sprintf(str6, "Battery left: %uh%um", bat_time / 3600, (bat_time / 60) % 60);
154                                         
155                                         write(sock, "\000\001", 2);
156                                         len = htons(2 * 6 + strlen(str1) + strlen(str2) + strlen(str3) + strlen(str4) + strlen(str5) + strlen(str6));
157                                         write(sock, (char*)&len, 2);
158                                         
159                                         len = htons(strlen(str1));
160                                         write(sock, (char*)&len, 2);
161                                         write(sock, str1, strlen(str1));
162
163                                         len = htons(strlen(str2));
164                                         write(sock, (char*)&len, 2);
165                                         write(sock, str2, strlen(str2));
166
167                                         len = htons(strlen(str3));
168                                         write(sock, (char*)&len, 2);
169                                         write(sock, str3, strlen(str3));
170
171                                         len = htons(strlen(str4));
172                                         write(sock, (char*)&len, 2);
173                                         write(sock, str4, strlen(str4));
174                                 
175                                         len = htons(strlen(str5));
176                                         write(sock, (char*)&len, 2);
177                                         write(sock, str5, strlen(str5));
178                                 
179                                         len = htons(strlen(str6));
180                                         write(sock, (char*)&len, 2);
181                                         write(sock, str6, strlen(str6));
182                                 
183                                         // vibrate 250ms for every 10k packets
184                                         if (crypted/10000 != last_crypted/10000) {
185                                                 write(sock, "\000\016\000\002\000\372", 6);
186                                         }
187                                         
188                                         // vibrate 1750ms extra for every 100k packets
189                                         if (crypted/100000 != last_crypted/100000) {
190                                                 write(sock, "\000\016\000\002\006\326", 6);
191                                         }
192
193                                         last_crypted = crypted;
194
195                                         ret = 1;
196                                 }
197                         }
198                 }
199                 ptr = strtok(NULL, "\n");
200         }
201
202         return ret;
203 }
204
205 int main(int argc, char **argv)
206 {
207         struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
208         struct sockaddr_in addr;
209         unsigned char buf[1024] = { 0 };
210         char initstr[] = "!1 ENABLE NETWORK bssid,cryptpackets,weakpackets,signal,noise\n";
211         int s, client, kismet, bytes_read;
212         size_t opt = sizeof(rem_addr);
213         unsigned one = 1;
214         
215         // allocate socket
216         s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
217         
218         // bind socket to port 1 of the first available 
219         // local bluetooth adapter
220         loc_addr.rc_family = AF_BLUETOOTH;
221         loc_addr.rc_bdaddr = *BDADDR_ANY;
222         loc_addr.rc_channel = (uint8_t) 1;
223         bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
224
225         // put socket into listening mode
226         listen(s, 1);
227
228         // accept one connection
229         client = accept(s, (struct sockaddr *)&rem_addr, &opt);
230
231         ba2str( &rem_addr.rc_bdaddr, buf );
232         fprintf(stderr, "accepted connection from %s\n", buf);
233         memset(buf, 0, sizeof(buf));
234
235         ioctl(client, FIONBIO, &one);
236         
237         // connect to kismet
238         kismet = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
239         addr.sin_family = AF_INET;
240         addr.sin_addr.s_addr = inet_addr("127.0.0.1");
241         addr.sin_port = htons(2501);
242
243         if (connect(kismet, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
244                 perror("connect()");
245                 exit(1);
246         }
247         ioctl(kismet, FIONBIO, &one);
248         write(kismet, initstr, strlen(initstr));
249         
250         printf("Connected to Kismet.\n");
251
252         // read data from the client
253         for ( ;; ) {
254                 int flag = 1;
255
256                 // gobble up data from the phone
257                 bytes_read = read(client, buf, sizeof(buf) - 1);
258                 if( bytes_read > 0 ) {
259                         unsigned i;
260                         printf("received [");
261                         for (i = 0; i < bytes_read; ++i)
262                                 printf("0x%02x ", buf[i]);
263                         printf("]\n");
264
265                         // don't bother with any sophisticated parsing
266                         while (bytes_read > 4) {
267                                 int command = (buf[0] << 8) | buf[1];
268                                 int len = (buf[2] << 8) | buf[3];
269         
270                                 // menu item
271                                 if (command == 3) {
272                                         int no = (buf[4] << 8) | buf[5];
273                                         if (no == 5) {
274                                                 system("killall kismet_client");
275                                                 exit(0);
276                                         }
277                                 }
278
279                                 memmove(buf, buf + len + 4, bytes_read - (len + 4));
280                                 bytes_read -= len + 4;
281                         }
282                 }
283                 
284                 // read from kismet
285                 bytes_read = read(kismet, buf, sizeof(buf));
286                 if( bytes_read > 0 ) {
287                         unsigned i;
288                         for (i = 0; i < bytes_read; ++i)
289                                 printf("%c", buf[i]);
290
291                         flag = parse_packet(buf, bytes_read, client);
292                 }
293
294                 if (flag) {
295                         // alive?
296                         write(client, "\000\012\000\000", 4);
297                         sleep(1);
298                 }
299         }
300
301         // close connection
302         close(client);
303         close(s);
304         return 0;
305 }
306