-
Notifications
You must be signed in to change notification settings - Fork 1
/
db.c
290 lines (263 loc) · 9.61 KB
/
db.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*
ssid-logger is a simple software to log SSID you encounter in your vicinity
Copyright © 2020-2022 solsTiCe d'Hiver
*/
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <string.h>
#include <math.h>
#include <inttypes.h>
#include <libgen.h>
#include <libwifi.h>
#include "gps_thread.h"
#include "parsers.h"
#include "lruc.h"
int init_beacon_db(const char *db_file, sqlite3 **db)
{
int ret;
if ((ret = sqlite3_open(db_file, db)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
sqlite3_close(*db);
return ret;
}
char *sql;
sql = "create table if not exists authmode("
"id integer not null primary key,"
"mode text"
");";
if ((ret = sqlite3_exec(*db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
sqlite3_close(*db);
return ret;
}
sql = "create table if not exists ap("
"id integer not null primary key,"
"bssid text not null,"
"ssid text not null,"
"unique (bssid, ssid)"
");";
if ((ret = sqlite3_exec(*db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
sqlite3_close(*db);
return ret;
}
sql = "create table if not exists beacon("
"ts integer,"
"ap integer,"
"channel integer,"
"rssi integer,"
"lat float,"
"lon float,"
"alt float,"
"acc float,"
"authmode integer,"
"foreign key(ap) references ap(id),"
"foreign key(authmode) references authmode(id)"
");";
if ((ret = sqlite3_exec(*db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
sqlite3_close(*db);
return ret;
}
sql = "pragma synchronous = normal;";
if ((ret = sqlite3_exec(*db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
return ret;
}
sql = "pragma temp_store = 2;"; // to store temp table and indices in memory
if ((ret = sqlite3_exec(*db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
sqlite3_close(*db);
return ret;
}
sql = "pragma journal_mode = off;"; // disable journal for rollback (we don't use this)
if ((ret = sqlite3_exec(*db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
sqlite3_close(*db);
return ret;
}
sql = "pragma foreign_keys = on;"; // this needs to be turn on
if ((ret = sqlite3_exec(*db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(*db), basename(__FILE__), __LINE__, __func__);
sqlite3_close(*db);
return ret;
}
return 0;
}
// retrieve primary key id for authmode
int64_t search_authmode(const char *authmode, sqlite3 *db)
{
char *sql;
sqlite3_stmt *stmt;
int64_t authmode_id = 0, ret;
// look for an existing authmode in the db
sql = "select id from authmode where mode=?;";
if ((ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
} else {
if ((ret = sqlite3_bind_text(stmt, 1, authmode, -1, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
while ((ret = sqlite3_step(stmt)) != SQLITE_DONE) {
if (ret == SQLITE_ERROR) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
break;
} else if (ret == SQLITE_ROW) {
authmode_id = sqlite3_column_int64(stmt, 0);
} else {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
break;
}
}
sqlite3_finalize(stmt);
}
return authmode_id;
}
// search authmode in the db or insert it if not present and return the primary key
int64_t insert_authmode(const char *authmode, sqlite3 *db)
{
int64_t ret, authmode_id = 0;
char sql[65 + MAX_AUTHMODE_LEN];
authmode_id = search_authmode(authmode, db);
if (!authmode_id) {
snprintf(sql, 128, "insert into authmode (mode) values (\"%s\");", authmode);
if ((ret = sqlite3_exec(db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
authmode_id = search_authmode(authmode, db);
}
return authmode_id;
}
// look for an existing bss in the db, using the ssid and the bssid
int64_t search_ap(struct libwifi_bss bss, sqlite3 *db)
{
char *sql;
sqlite3_stmt *stmt;
int64_t ap_id = 0, ret;
char bssid[18];
sql = "select id from ap where bssid=? and ssid=?;";
if ((ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
} else {
sprintf(bssid, MACSTR, MAC2STR(bss.bssid));
if ((ret = sqlite3_bind_text(stmt, 1, bssid, -1, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
if ((ret = sqlite3_bind_text(stmt, 2, bss.ssid, -1, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
while ((ret = sqlite3_step(stmt)) != SQLITE_DONE) {
if (ret == SQLITE_ERROR) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
break;
} else if (ret == SQLITE_ROW) {
ap_id = sqlite3_column_int64(stmt, 0);
} else {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
break;
}
}
sqlite3_finalize(stmt);
}
return ap_id;
}
// search bss in the db or insert it if not found
int64_t insert_ap(struct libwifi_bss bss, sqlite3 *db)
{
int64_t ret, ap_id = 0;
char sql[128];
ap_id = search_ap(bss, db);
if (!ap_id) {
// if ever the ssid is longer than 32 chars, it is truncated at 128-18-length of string below
snprintf(sql, 128, "insert into ap (bssid, ssid) values (\""MACSTR"\", \"%s\");", MAC2STR(bss.bssid), bss.ssid);
if ((ret = sqlite3_exec(db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
ap_id = search_ap(bss, db);
}
return ap_id;
}
// insert an bss into the db
int insert_beacon(struct libwifi_bss bss, struct gps_loc gloc, sqlite3 *db, lruc *authmode_pk_cache, lruc *ap_pk_cache)
{
int ret;
int64_t ap_id = 0, authmode_id = 0;
void *value = NULL;
// look for ap in ap_pk_cache
size_t ap_key_len = 18 + strnlen(bss.ssid, 32);
char *ap_key = malloc(ap_key_len * sizeof(char));
// concat bssid and ssid to use it as key in ap_pk_cache
snprintf(ap_key, ap_key_len + 1, MACSTR"%s", MAC2STR(bss.bssid), bss.ssid);
lruc_get(ap_pk_cache, ap_key, ap_key_len, &value);
if (value == NULL) {
ap_id = insert_ap(bss, db);
// insert ap_id in ap_pk_cache
int64_t *new_value = malloc(sizeof(int64_t));
*new_value = ap_id;
lruc_set(ap_pk_cache, ap_key, ap_key_len, new_value, 1);
} else {
ap_id = *(int64_t *)value;
free(ap_key);
}
value = NULL;
// look for authmode in authmode_pk_cache
char *authmode = authmode_from_crypto(bss);
if (authmode == NULL) {
authmode = strdup("");
}
lruc_get(authmode_pk_cache, authmode, strlen(authmode), &value);
if (value == NULL) {
authmode_id = insert_authmode(authmode, db);
if (authmode_id < 0) {
// something is wrong ! probably authmode is too long
free(authmode);
return authmode_id;
}
// insert authmode_id in authmode_pk_cache
int64_t *new_value = malloc(sizeof(int64_t));
*new_value = authmode_id;
lruc_set(authmode_pk_cache, authmode, strlen(authmode), new_value, 1);
} else {
authmode_id = *(int64_t *)value;
free(authmode);
}
char sql[256];
snprintf(sql, 256, "insert into beacon (ts, ap, channel, rssi, lat, lon, alt, acc, authmode)"
"values (%lu, %"PRId64", %u, %d, %f, %f, %f, %f, %"PRId64");",
gloc.ftime.tv_sec, ap_id, bss.channel, bss.signal, gloc.lat, gloc.lon, isfinite(gloc.alt) ? gloc.alt : 0.0, gloc.acc, authmode_id);
if ((ret = sqlite3_exec(db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
return 0;
}
// start a new sqlite3 transaction
int begin_txn(sqlite3 *db)
{
int ret;
char *sql = "begin transaction;";
if ((ret = sqlite3_exec(db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
return 0;
}
// commit current transaction
int commit_txn(sqlite3 *db)
{
int ret;
char *sql = "commit transaction;";
if ((ret = sqlite3_exec(db, sql, NULL, 0, NULL)) != SQLITE_OK) {
fprintf(stderr, "Error: %s (%s:%d in %s)\n", sqlite3_errmsg(db), basename(__FILE__), __LINE__, __func__);
return ret * -1;
}
return 0;
}