1 /*
2 This file is part of Kismet
3
4 Kismet is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 Kismet is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Kismet; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "config.h"
20
21 #include "util.h"
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <math.h>
28 #include <string.h>
29
30 #ifdef HAVE_LIBUTIL_H
31 # include <libutil.h>
32 #endif /* HAVE_LIBUTIL_H */
33
34 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
35 #error "pstat?"
36 #endif
37
38 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
39 # ifdef HAVE_SYS_PSTAT_H
40 # include <sys/pstat.h>
41 # else
42 # undef PF_ARGV_TYPE
43 # define PF_ARGV_TYPE PF_ARGV_WRITEABLE
44 # endif /* HAVE_SYS_PSTAT_H */
45 #endif /* PF_ARGV_PSTAT */
46
47 #if PF_ARGV_TYPE == PF_ARGV_PSSTRINGS
48 # ifndef HAVE_SYS_EXEC_H
49 # undef PF_ARGV_TYPE
50 # define PF_ARGV_TYPE PF_ARGV_WRITEABLE
51 # else
52 # include <machine/vmparam.h>
53 # include <sys/exec.h>
54 # endif /* HAVE_SYS_EXEC_H */
55 #endif /* PF_ARGV_PSSTRINGS */
56
57 // We need this to make uclibc happy since they don't even have rintf...
58 #ifndef rintf
59 #define rintf(x) (float) rint((double) (x))
60 #endif
61
62 #include <sstream>
63 #include <iomanip>
64
65 // Munge input to shell-safe
MungeToShell(char * in_data,int max)66 void MungeToShell(char *in_data, int max) {
67 int i, j;
68
69 for (i = 0, j = 0; i < max && j < max; i++) {
70 if (in_data[i] == '\0')
71 break;
72
73 if (isalnum(in_data[i]) || isspace(in_data[i]) ||
74 in_data[i] == '=' || in_data[i] == '-' || in_data[i] == '_' ||
75 in_data[i] == '.' || in_data[i] == ',') {
76
77 if (j == i) {
78 j++;
79 } else {
80 in_data[j++] = in_data[i];
81 }
82 }
83 }
84
85 in_data[j] = '\0';
86
87 }
88
89 // Quick wrapper to save us time in other code
MungeToShell(string in_data)90 string MungeToShell(string in_data) {
91 char *data = new char[in_data.length() + 1];
92 string ret;
93
94 snprintf(data, in_data.length() + 1, "%s", in_data.c_str());
95
96 MungeToShell(data, in_data.length() + 1);
97
98 ret = data;
99 delete[] data;
100 return ret;
101 }
102
103 // Munge text down to printable characters only. Simpler, cleaner munger than
104 // before (and more blatant when munging)
MungeToPrintable(const char * in_data,int max,int nullterm)105 string MungeToPrintable(const char *in_data, int max, int nullterm) {
106 string ret;
107 int i;
108
109 for (i = 0; i < max; i++) {
110 if ((unsigned char) in_data[i] == 0 && nullterm == 1)
111 return ret;
112
113 if ((unsigned char) in_data[i] >= 32 && (unsigned char) in_data[i] <= 126) {
114 ret += in_data[i];
115 } else {
116 ret += '\\';
117 ret += ((in_data[i] >> 6) & 0x03) + '0';
118 ret += ((in_data[i] >> 3) & 0x07) + '0';
119 ret += ((in_data[i] >> 0) & 0x07) + '0';
120 }
121 }
122
123 return ret;
124 }
125
MungeToPrintable(string in_str)126 string MungeToPrintable(string in_str) {
127 return MungeToPrintable(in_str.c_str(), in_str.length(), 1);
128 }
129
StrLower(string in_str)130 string StrLower(string in_str) {
131 string thestr = in_str;
132 for (unsigned int i = 0; i < thestr.length(); i++)
133 thestr[i] = tolower(thestr[i]);
134
135 return thestr;
136 }
137
StrUpper(string in_str)138 string StrUpper(string in_str) {
139 string thestr = in_str;
140
141 for (unsigned int i = 0; i < thestr.length(); i++)
142 thestr[i] = toupper(thestr[i]);
143
144 return thestr;
145 }
146
StrStrip(string in_str)147 string StrStrip(string in_str) {
148 string temp;
149 unsigned int start, end;
150
151 start = 0;
152 end = in_str.length();
153
154 if (in_str[0] == '\n')
155 return "";
156
157 for (unsigned int x = 0; x < in_str.length(); x++) {
158 if (in_str[x] != ' ' && in_str[x] != '\t') {
159 start = x;
160 break;
161 }
162 }
163 for (unsigned int x = in_str.length(); x > 1; ) {
164 x--;
165 if (in_str[x] != ' ' && in_str[x] != '\t' && in_str[x] != '\n') {
166 end = x;
167 break;
168 }
169 }
170
171 return in_str.substr(start, end-start+1);
172 }
173
StrPrintable(string in_str)174 string StrPrintable(string in_str) {
175 string thestr;
176
177 for (unsigned int i = 0; i < in_str.length(); i++) {
178 if (isprint(in_str[i])) {
179 thestr += in_str[i];
180 }
181 }
182
183 return thestr;
184 }
185
IsBlank(const char * s)186 int IsBlank(const char *s) {
187 int len, i;
188
189 if (NULL == s) {
190 return 1;
191 }
192
193 if (0 == (len = strlen(s))) {
194 return 1;
195 }
196
197 for (i = 0; i < len; ++i) {
198 if (' ' != s[i]) {
199 return 0;
200 }
201 }
202
203 return 1;
204 }
205
AlignString(string in_txt,char in_spacer,int in_align,int in_width)206 string AlignString(string in_txt, char in_spacer, int in_align, int in_width) {
207 if (in_align == 1) {
208 // Center -- half, text, chop to fit
209 int sp = (in_width / 2) - (in_txt.length() / 2);
210 string ts = "";
211
212 if (sp > 0) {
213 ts = string(sp, in_spacer);
214 }
215
216 ts += in_txt.substr(0, in_width);
217
218 return ts;
219 } else if (in_align == 2) {
220 // Right -- width - len, chop to fit
221 int sp = (in_width - in_txt.length());
222 string ts = "";
223
224 if (sp > 0) {
225 ts = string(sp, in_spacer);
226 }
227
228 ts += in_txt.substr(0, in_width);
229
230 return ts;
231 }
232
233 // Left align -- make sure it's not too long
234 return in_txt.substr(0, in_width);
235 }
236
HexStrToUint8(string in_str,uint8_t * in_buf,int in_buflen)237 int HexStrToUint8(string in_str, uint8_t *in_buf, int in_buflen) {
238 int decode_pos = 0;
239 int str_pos = 0;
240
241 while ((unsigned int) str_pos < in_str.length() && decode_pos < in_buflen) {
242 short int tmp;
243
244 if (in_str[str_pos] == ' ') {
245 str_pos++;
246 continue;
247 }
248
249 if (sscanf(in_str.substr(str_pos, 2).c_str(), "%2hx", &tmp) != 1) {
250 return -1;
251 }
252
253 in_buf[decode_pos++] = tmp;
254 str_pos += 2;
255 }
256
257 return decode_pos;
258 }
259
XtoI(char x)260 int XtoI(char x) {
261 if (isxdigit(x)) {
262 if (x <= '9')
263 return x - '0';
264 return toupper(x) - 'A' + 10;
265 }
266
267 return -1;
268 }
269
Hex2UChar(unsigned char * in_hex,unsigned char * in_chr)270 int Hex2UChar(unsigned char *in_hex, unsigned char *in_chr) {
271 memset(in_chr, 0, sizeof(unsigned char) * WEPKEY_MAX);
272 int chrpos = 0;
273
274 for (unsigned int strpos = 0; strpos < WEPKEYSTR_MAX && chrpos < WEPKEY_MAX; strpos++) {
275 if (in_hex[strpos] == 0)
276 break;
277
278 if (in_hex[strpos] == ':')
279 strpos++;
280
281 // Assume we're going to eat the pair here
282 if (isxdigit(in_hex[strpos])) {
283 if (strpos > (WEPKEYSTR_MAX - 2))
284 return 0;
285
286 int d1, d2;
287 if ((d1 = XtoI(in_hex[strpos++])) == -1)
288 return 0;
289 if ((d2 = XtoI(in_hex[strpos])) == -1)
290 return 0;
291
292 in_chr[chrpos++] = (d1 * 16) + d2;
293 }
294
295 }
296
297 return(chrpos);
298 }
299
300 // Complex string tokenizer which understands nested delimiters, such as
301 // "foo","bar","baz,foo",something
302 // and network protocols like
303 // foo bar \001baz foo\001
BaseStrTokenize(string in_str,string in_split,string in_quote)304 vector<smart_word_token> BaseStrTokenize(string in_str,
305 string in_split, string in_quote) {
306 size_t begin = 0;
307 size_t end = 0;
308 vector<smart_word_token> ret;
309 smart_word_token stok;
310 int special = 0;
311 string val;
312
313 if (in_str.length() == 0)
314 return ret;
315
316 for (unsigned int x = 0; x < in_str.length(); x++) {
317 if (in_str.find(in_quote, x) == x) {
318 if (special == 0) {
319 // reset beginning on string if we're in a special block
320 begin = x;
321 special = 1;
322 } else {
323 special = 0;
324 }
325
326 continue;
327 }
328
329 if (special == 0 && in_str.find(in_split, x) == x) {
330 stok.begin = begin;
331 stok.end = end;
332 stok.word = val;
333
334 ret.push_back(stok);
335
336 val = "";
337 x += in_split.length() - 1;
338
339 begin = x;
340
341 continue;
342 }
343
344 val += in_str[x];
345 end = x;
346 }
347
348 stok.begin = begin;
349 stok.end = end;
350 stok.word = val;
351 ret.push_back(stok);
352
353 return ret;
354 }
355
356 // No-frills tokenize with no intelligence about nested delimiters
StrTokenize(string in_str,string in_split,int return_partial)357 vector<string> StrTokenize(string in_str, string in_split, int return_partial) {
358 size_t begin = 0;
359 size_t end = in_str.find(in_split);
360 vector<string> ret;
361
362 if (in_str.length() == 0)
363 return ret;
364
365 while (end != string::npos) {
366 string sub = in_str.substr(begin, end-begin);
367 begin = end+1;
368 end = in_str.find(in_split, begin);
369 ret.push_back(sub);
370 }
371
372 if (return_partial && begin != in_str.size())
373 ret.push_back(in_str.substr(begin, in_str.size() - begin));
374
375 return ret;
376 }
377
378 // Collapse into basic tokenizer
NetStrTokenize(string in_str,string in_split,int return_partial)379 vector<smart_word_token> NetStrTokenize(string in_str, string in_split,
380 int return_partial) {
381 return BaseStrTokenize(in_str, in_split, "\001");
382 }
383
384 // Collapse into basic tokenizer rewrite
QuoteStrTokenize(string in_str,string in_split)385 vector<string> QuoteStrTokenize(string in_str, string in_split) {
386 vector<string> ret;
387 vector<smart_word_token> bret;
388
389 bret = BaseStrTokenize(in_str, in_split, "\"");
390
391 for (unsigned int b = 0; b < bret.size(); b++) {
392 ret.push_back(bret[b].word);
393 }
394
395 return ret;
396 }
397
TokenNullJoin(string * ret_str,const char ** in_list)398 int TokenNullJoin(string *ret_str, const char **in_list) {
399 int ret = 0;
400
401 while (in_list[ret] != NULL) {
402 (*ret_str) += in_list[ret];
403
404 if (in_list[ret + 1] != NULL)
405 (*ret_str) += ",";
406
407 ret++;
408 }
409
410 return ret;
411 }
412
413 // Find an option - just like config files
FetchOpt(string in_key,vector<opt_pair> * in_vec)414 string FetchOpt(string in_key, vector<opt_pair> *in_vec) {
415 string lkey = StrLower(in_key);
416
417 if (in_vec == NULL)
418 return "";
419
420 for (unsigned int x = 0; x < in_vec->size(); x++) {
421 if ((*in_vec)[x].opt == lkey)
422 return (*in_vec)[x].val;
423 }
424
425 return "";
426 }
427
FetchOptBoolean(string in_key,vector<opt_pair> * in_vec,int dvalue)428 int FetchOptBoolean(string in_key, vector<opt_pair> *in_vec, int dvalue) {
429 string s = FetchOpt(in_key, in_vec);
430
431 return StringToBool(s, dvalue);
432 }
433
FetchOptVec(string in_key,vector<opt_pair> * in_vec)434 vector<string> FetchOptVec(string in_key, vector<opt_pair> *in_vec) {
435 string lkey = StrLower(in_key);
436 vector<string> ret;
437
438 if (in_vec == NULL)
439 return ret;
440
441 for (unsigned int x = 0; x < in_vec->size(); x++) {
442 if ((*in_vec)[x].opt == lkey)
443 ret.push_back((*in_vec)[x].val);
444 }
445
446 return ret;
447 }
448
StringToOpts(string in_line,string in_sep,vector<opt_pair> * in_vec)449 int StringToOpts(string in_line, string in_sep, vector<opt_pair> *in_vec) {
450 vector<string> optv;
451 opt_pair optp;
452
453 int in_tag = 1, in_quote = 0;
454
455 optp.quoted = 0;
456
457 for (unsigned int x = 0; x < in_line.length(); x++) {
458 if (in_tag && in_line[x] != '=') {
459 optp.opt += in_line[x];
460 continue;
461 }
462
463 if (in_tag && in_line[x] == '=') {
464 in_tag = 0;
465 continue;
466 }
467
468 if (in_line[x] == '"') {
469 if (in_quote == 0) {
470 in_quote = 1;
471 optp.quoted = 1;
472 } else {
473 in_quote = 0;
474 }
475
476 continue;
477 }
478
479 if (in_quote == 0 && in_line[x] == in_sep[0]) {
480 in_vec->push_back(optp);
481 optp.quoted = 0;
482 optp.opt = "";
483 optp.val = "";
484 in_tag = 1;
485 continue;
486 }
487
488 optp.val += in_line[x];
489 }
490
491 in_vec->push_back(optp);
492
493 return 1;
494 }
495
AddOptToOpts(string opt,string val,vector<opt_pair> * in_vec)496 void AddOptToOpts(string opt, string val, vector<opt_pair> *in_vec) {
497 opt_pair optp;
498
499 optp.opt = StrLower(opt);
500 optp.val = val;
501
502 in_vec->push_back(optp);
503 }
504
ReplaceAllOpts(string opt,string val,vector<opt_pair> * in_vec)505 void ReplaceAllOpts(string opt, string val, vector<opt_pair> *in_vec) {
506 opt_pair optp;
507
508 optp.opt = StrLower(opt);
509 optp.val = val;
510
511 for (unsigned int x = 0; x < in_vec->size(); x++) {
512 if ((*in_vec)[x].val == optp.val) {
513 in_vec->erase(in_vec->begin() + x);
514 x--;
515 continue;
516 }
517 }
518
519 in_vec->push_back(optp);
520 }
521
LineWrap(string in_txt,unsigned int in_hdr_len,unsigned int in_maxlen)522 vector<string> LineWrap(string in_txt, unsigned int in_hdr_len,
523 unsigned int in_maxlen) {
524 vector<string> ret;
525
526 size_t pos, prev_pos, start, hdroffset;
527 start = hdroffset = 0;
528
529 for (pos = prev_pos = in_txt.find(' ', in_hdr_len); pos != string::npos;
530 pos = in_txt.find(' ', pos + 1)) {
531 if ((hdroffset + pos) - start >= in_maxlen) {
532 if (pos - prev_pos > (in_maxlen / 5)) {
533 pos = prev_pos = start + (in_maxlen - hdroffset);
534 }
535
536 string str(hdroffset, ' ');
537 hdroffset = in_hdr_len;
538 str += in_txt.substr(start, prev_pos - start);
539 ret.push_back(str);
540
541 start = prev_pos;
542 }
543
544 prev_pos = pos + 1;
545 }
546
547 while (in_txt.length() - start > (in_maxlen - hdroffset)) {
548 string str(hdroffset, ' ');
549 hdroffset = in_hdr_len;
550
551 str += in_txt.substr(start, (prev_pos - start));
552 ret.push_back(str);
553
554 start = prev_pos;
555
556 prev_pos+= (in_maxlen - hdroffset);
557 }
558
559 string str(hdroffset, ' ');
560 str += in_txt.substr(start, in_txt.length() - start);
561 ret.push_back(str);
562
563 return ret;
564 }
565
InLineWrap(string in_txt,unsigned int in_hdr_len,unsigned int in_maxlen)566 string InLineWrap(string in_txt, unsigned int in_hdr_len,
567 unsigned int in_maxlen) {
568 vector<string> raw = LineWrap(in_txt, in_hdr_len, in_maxlen);
569 string ret;
570
571 for (unsigned int x = 0; x < raw.size(); x++) {
572 ret += raw[x] + "\n";
573 }
574
575 return ret;
576 }
577
SanitizeXML(string in_str)578 string SanitizeXML(string in_str) {
579 // Ghetto-fied XML sanitizer. Add more stuff later if we need to.
580 string ret;
581 for (unsigned int x = 0; x < in_str.length(); x++) {
582 if (in_str[x] == '&')
583 ret += "&";
584 else if (in_str[x] == '<')
585 ret += "<";
586 else if (in_str[x] == '>')
587 ret += ">";
588 else
589 ret += in_str[x];
590 }
591
592 return ret;
593 }
594
SanitizeCSV(string in_str)595 string SanitizeCSV(string in_str) {
596 string ret;
597 for (unsigned int x = 0; x < in_str.length(); x++) {
598 if (in_str[x] == ';')
599 ret += " ";
600 else
601 ret += in_str[x];
602 }
603
604 return ret;
605 }
606
Float2Pair(float in_float,int16_t * primary,int64_t * mantissa)607 void Float2Pair(float in_float, int16_t *primary, int64_t *mantissa) {
608 *primary = (int) in_float;
609 *mantissa = (long) (1000000 * ((in_float) - *primary));
610 }
611
Pair2Float(int16_t primary,int64_t mantissa)612 float Pair2Float(int16_t primary, int64_t mantissa) {
613 return (double) primary + ((double) mantissa / 1000000);
614 }
615
Str2IntVec(string in_text)616 vector<int> Str2IntVec(string in_text) {
617 vector<string> optlist = StrTokenize(in_text, ",");
618 vector<int> ret;
619 int ch;
620
621 for (unsigned int x = 0; x < optlist.size(); x++) {
622 if (sscanf(optlist[x].c_str(), "%d", &ch) != 1) {
623 ret.clear();
624 break;
625 }
626
627 ret.push_back(ch);
628 }
629
630 return ret;
631 }
632
RunSysCmd(char * in_cmd)633 int RunSysCmd(char *in_cmd) {
634 return system(in_cmd);
635 }
636
ExecSysCmd(char * in_cmd)637 pid_t ExecSysCmd(char *in_cmd) {
638 // Slice it into an array to pass to exec
639 vector<string> cmdvec = StrTokenize(in_cmd, " ");
640 char **cmdarg = new char *[cmdvec.size() + 1];
641 pid_t retpid;
642 unsigned int x;
643
644 // Convert it to a pointer array
645 for (x = 0; x < cmdvec.size(); x++)
646 cmdarg[x] = (char *) cmdvec[x].c_str();
647 cmdarg[x] = NULL;
648
649 if ((retpid = fork()) == 0) {
650 // Nuke the file descriptors so that they don't blat on
651 // input or output
652 for (unsigned int x = 0; x < 256; x++)
653 close(x);
654
655 execve(cmdarg[0], cmdarg, NULL);
656 exit(0);
657 }
658
659 delete[] cmdarg;
660 return retpid;
661 }
662
663 #ifdef SYS_LINUX
FetchSysLoadAvg(uint8_t * in_avgmaj,uint8_t * in_avgmin)664 int FetchSysLoadAvg(uint8_t *in_avgmaj, uint8_t *in_avgmin) {
665 FILE *lf;
666 short unsigned int tmaj, tmin;
667
668 if ((lf = fopen("/proc/loadavg", "r")) == NULL) {
669 fclose(lf);
670 return -1;
671 }
672
673 if (fscanf(lf, "%hu.%hu", &tmaj, &tmin) != 2) {
674 fclose(lf);
675 return -1;
676 }
677
678 (*in_avgmaj) = tmaj;
679 (*in_avgmin) = tmin;
680
681 fclose(lf);
682
683 return 1;
684 }
685 #endif
686
687 // Convert the beacon interval to # of packets per second
Ieee80211Interval2NSecs(int in_interval)688 unsigned int Ieee80211Interval2NSecs(int in_interval) {
689 double interval_per_sec;
690
691 interval_per_sec = (double) in_interval * 1024 / 1000000;
692
693 return (unsigned int) ceil(1.0f / interval_per_sec);
694 }
695
Adler32Checksum(const char * buf1,int len)696 uint32_t Adler32Checksum(const char *buf1, int len) {
697 int i;
698 uint32_t s1, s2;
699 char *buf = (char *)buf1;
700 int CHAR_OFFSET = 0;
701
702 s1 = s2 = 0;
703 for (i = 0; i < (len-4); i+=4) {
704 s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] +
705 10*CHAR_OFFSET;
706 s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
707 }
708
709 for (; i < len; i++) {
710 s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
711 }
712
713 return (s1 & 0xffff) + (s2 << 16);
714 }
715
ChanToFreq(int in_chan)716 int ChanToFreq(int in_chan) {
717 // 80211 frequencies to channels
718 // Stolen from Linux net/wireless/util.c
719 if (in_chan == 14)
720 return 2484;
721 else if (in_chan < 14)
722 return 2407 + in_chan * 5;
723 if (in_chan >= 182 && in_chan <= 196)
724 return 4000 + in_chan * 5;
725 else
726 return 5000 + in_chan * 5;
727
728 return in_chan;
729 }
730
FreqToChan(int in_freq)731 int FreqToChan(int in_freq) {
732 // 80211 frequencies to channels
733 // Stolen from Linux net/wireless/util.c
734 /* see 802.11 17.3.8.3.2 and Annex J */
735 if (in_freq == 2484)
736 return 14;
737 else if (in_freq < 2484)
738 return (in_freq - 2407) / 5;
739 else if (in_freq >= 4910 && in_freq <= 4980)
740 return (in_freq - 4000) / 5;
741 else if (in_freq <= 45000) /* DMG band lower limit */
742 return (in_freq - 5000) / 5;
743 else if (in_freq >= 58320 && in_freq <= 64800)
744 return (in_freq - 56160) / 2160;
745 else
746 return in_freq;
747 }
748
749 // Multiplatform method of setting a process title. Lifted from proftpd main.c
750 // * ProFTPD - FTP server daemon
751 // * Copyright (c) 1997, 1998 Public Flood Software
752 // * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
753 // * Copyright (c) 2001, 2002, 2003 The ProFTPD Project team
754 //
755 // Process title munging is ugly!
756
757 // Externs to glibc
758 #ifdef HAVE___PROGNAME
759 extern char *__progname, *__progname_full;
760 #endif /* HAVE___PROGNAME */
761 extern char **environ;
762
763 // This is not good at all. i should probably rewrite this, but...
764 static char **Argv = NULL;
765 static char *LastArgv = NULL;
766
init_proc_title(int argc,char * argv[],char * envp[])767 void init_proc_title(int argc, char *argv[], char *envp[]) {
768 register int i, envpsize;
769 char **p;
770
771 /* Move the environment so setproctitle can use the space. */
772 for (i = envpsize = 0; envp[i] != NULL; i++)
773 envpsize += strlen(envp[i]) + 1;
774
775 if ((p = (char **)malloc((i + 1) * sizeof(char *))) != NULL) {
776 environ = p;
777
778 // Stupid strncpy because it makes the linker not whine
779 for (i = 0; envp[i] != NULL; i++)
780 if ((environ[i] = (char *) malloc(strlen(envp[i]) + 1)) != NULL)
781 strncpy(environ[i], envp[i], strlen(envp[i]) + 1);
782
783 environ[i] = NULL;
784 }
785
786 Argv = argv;
787
788 for (i = 0; i < argc; i++)
789 if (!i || (LastArgv + 1 == argv[i]))
790 LastArgv = argv[i] + strlen(argv[i]);
791
792 for (i = 0; envp[i] != NULL; i++)
793 if ((LastArgv + 1) == envp[i])
794 LastArgv = envp[i] + strlen(envp[i]);
795
796 #ifdef HAVE___PROGNAME
797 /* Set the __progname and __progname_full variables so glibc and company
798 * don't go nuts.
799 */
800 __progname = strdup("kismet");
801 __progname_full = strdup(argv[0]);
802 #endif /* HAVE___PROGNAME */
803 }
804
set_proc_title(const char * fmt,...)805 void set_proc_title(const char *fmt, ...) {
806 va_list msg;
807 static char statbuf[BUFSIZ];
808
809 #ifndef HAVE_SETPROCTITLE
810 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
811 union pstun pst;
812 #endif /* PF_ARGV_PSTAT */
813 char *p;
814 int i,maxlen = (LastArgv - Argv[0]) - 2;
815 #endif /* HAVE_SETPROCTITLE */
816
817 va_start(msg,fmt);
818
819 memset(statbuf, 0, sizeof(statbuf));
820
821 #ifdef HAVE_SETPROCTITLE
822 # if defined(__DragonFly__) || defined(__FreeBSD__)
823 /* FreeBSD's setproctitle() automatically prepends the process name. */
824 vsnprintf(statbuf, sizeof(statbuf), fmt, msg);
825
826 # else /* FREEBSD4 */
827 /* Manually append the process name for non-FreeBSD platforms. */
828 snprintf(statbuf, sizeof(statbuf), "%s: ", Argv[0]);
829 vsnprintf(statbuf + strlen(statbuf), sizeof(statbuf) - strlen(statbuf),
830 fmt, msg);
831
832 # endif /* FREEBSD4 */
833 setproctitle("%s", statbuf);
834
835 #else /* HAVE_SETPROCTITLE */
836 /* Manually append the process name for non-setproctitle() platforms. */
837 snprintf(statbuf, sizeof(statbuf), "%s: ", Argv[0]);
838 vsnprintf(statbuf + strlen(statbuf), sizeof(statbuf) - strlen(statbuf),
839 fmt, msg);
840
841 #endif /* HAVE_SETPROCTITLE */
842
843 va_end(msg);
844
845 #ifdef HAVE_SETPROCTITLE
846 return;
847 #else
848 i = strlen(statbuf);
849
850 #if PF_ARGV_TYPE == PF_ARGV_NEW
851 /* We can just replace argv[] arguments. Nice and easy.
852 */
853 Argv[0] = statbuf;
854 Argv[1] = NULL;
855 #endif /* PF_ARGV_NEW */
856
857 #if PF_ARGV_TYPE == PF_ARGV_WRITEABLE
858 /* We can overwrite individual argv[] arguments. Semi-nice.
859 */
860 snprintf(Argv[0], maxlen, "%s", statbuf);
861 p = &Argv[0][i];
862
863 while(p < LastArgv)
864 *p++ = '\0';
865 Argv[1] = NULL;
866 #endif /* PF_ARGV_WRITEABLE */
867
868 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
869 pst.pst_command = statbuf;
870 pstat(PSTAT_SETCMD, pst, i, 0, 0);
871 #endif /* PF_ARGV_PSTAT */
872
873 #if PF_ARGV_TYPE == PF_ARGV_PSSTRINGS
874 PS_STRINGS->ps_nargvstr = 1;
875 PS_STRINGS->ps_argvstr = statbuf;
876 #endif /* PF_ARGV_PSSTRINGS */
877
878 #endif /* HAVE_SETPROCTITLE */
879 }
880
LexString(string in_line,string & errstr)881 list<_kis_lex_rec> LexString(string in_line, string& errstr) {
882 list<_kis_lex_rec> ret;
883 int curstate = _kis_lex_none;
884 _kis_lex_rec cpr;
885 string tempstr;
886 char lastc = 0;
887 char c = 0;
888
889 cpr.type = _kis_lex_none;
890 cpr.data = "";
891 ret.push_back(cpr);
892
893 for (size_t pos = 0; pos < in_line.length(); pos++) {
894 lastc = c;
895 c = in_line[pos];
896
897 cpr.data = "";
898
899 if (curstate == _kis_lex_none) {
900 // Open paren
901 if (c == '(') {
902 cpr.type = _kis_lex_popen;
903 ret.push_back(cpr);
904 continue;
905 }
906
907 // Close paren
908 if (c == ')') {
909 cpr.type = _kis_lex_pclose;
910 ret.push_back(cpr);
911 continue;
912 }
913
914 // Negation
915 if (c == '!') {
916 cpr.type = _kis_lex_negate;
917 ret.push_back(cpr);
918 continue;
919 }
920
921 // delimiter
922 if (c == ',') {
923 cpr.type = _kis_lex_delim;
924 ret.push_back(cpr);
925 continue;
926 }
927
928 // start a quoted string
929 if (c == '"') {
930 curstate = _kis_lex_quotestring;
931 tempstr = "";
932 continue;
933 }
934
935 curstate = _kis_lex_string;
936 tempstr = c;
937 continue;
938 }
939
940 if (curstate == _kis_lex_quotestring) {
941 // We don't close on an escaped \"
942 if (c == '"' && lastc != '\\') {
943 // Drop out of the string and make the lex stack element
944 curstate = _kis_lex_none;
945 cpr.type = _kis_lex_quotestring;
946 cpr.data = tempstr;
947 ret.push_back(cpr);
948
949 tempstr = "";
950
951 continue;
952 }
953
954 // Add it to the quoted temp strnig
955 tempstr += c;
956 }
957
958 if (curstate == _kis_lex_string) {
959 // If we're a special character break out and add the lex stack element
960 // otherwise increase our unquoted string
961 if (c == '(' || c == ')' || c == '!' || c == '"' || c == ',') {
962 cpr.type = _kis_lex_string;
963 cpr.data = tempstr;
964 ret.push_back(cpr);
965 tempstr = "";
966 curstate = _kis_lex_none;
967 pos--;
968 continue;
969 }
970
971 tempstr += c;
972 continue;
973 }
974 }
975
976 if (curstate == _kis_lex_quotestring) {
977 errstr = "Unfinished quoted string in line '" + in_line + "'";
978 ret.clear();
979 }
980
981 return ret;
982 }
983
984 // Taken from the BBN USRP 802.11 encoding code
update_crc32_80211(unsigned int crc,const unsigned char * data,int len,unsigned int poly)985 unsigned int update_crc32_80211(unsigned int crc, const unsigned char *data,
986 int len, unsigned int poly) {
987 int i, j;
988 unsigned short ch;
989
990 for ( i = 0; i < len; ++i) {
991 ch = data[i];
992 for (j = 0; j < 8; ++j) {
993 if ((crc ^ ch) & 0x0001) {
994 crc = (crc >> 1) ^ poly;
995 } else {
996 crc = (crc >> 1);
997 }
998 ch >>= 1;
999 }
1000 }
1001 return crc;
1002 }
1003
crc32_init_table_80211(unsigned int * crc32_table)1004 void crc32_init_table_80211(unsigned int *crc32_table) {
1005 int i;
1006 unsigned char c;
1007
1008 for (i = 0; i < 256; ++i) {
1009 c = (unsigned char) i;
1010 crc32_table[i] = update_crc32_80211(0, &c, 1, IEEE_802_3_CRC32_POLY);
1011 }
1012 }
1013
crc32_le_80211(unsigned int * crc32_table,const unsigned char * buf,int len)1014 unsigned int crc32_le_80211(unsigned int *crc32_table, const unsigned char *buf,
1015 int len) {
1016 int i;
1017 unsigned int crc = 0xFFFFFFFF;
1018
1019 for (i = 0; i < len; ++i) {
1020 crc = (crc >> 8) ^ crc32_table[(crc ^ buf[i]) & 0xFF];
1021 }
1022
1023 crc ^= 0xFFFFFFFF;
1024
1025 return crc;
1026 }
1027
SubtractTimeval(struct timeval * in_tv1,struct timeval * in_tv2,struct timeval * out_tv)1028 void SubtractTimeval(struct timeval *in_tv1, struct timeval *in_tv2,
1029 struct timeval *out_tv) {
1030 if (in_tv1->tv_sec < in_tv2->tv_sec ||
1031 (in_tv1->tv_sec == in_tv2->tv_sec && in_tv1->tv_usec < in_tv2->tv_usec) ||
1032 in_tv1->tv_sec == 0 || in_tv2->tv_sec == 0) {
1033 out_tv->tv_sec = 0;
1034 out_tv->tv_usec = 0;
1035 return;
1036 }
1037
1038 if (in_tv2->tv_usec > in_tv1->tv_usec) {
1039 out_tv->tv_usec = 1000000 + in_tv1->tv_usec - in_tv2->tv_usec;
1040 out_tv->tv_sec = in_tv1->tv_sec - in_tv2->tv_sec - 1;
1041 } else {
1042 out_tv->tv_usec = in_tv1->tv_usec - in_tv2->tv_usec;
1043 out_tv->tv_sec = in_tv1->tv_sec - in_tv2->tv_sec;
1044 }
1045 }
1046
1047 /* Airware PPI gps conversion code from Johnny Csh */
1048
1049 /*
1050 * input: a unsigned 32-bit (native endian) value between 0 and 3600000000 (inclusive)
1051 * output: a signed floating point value betwen -180.0000000 and + 180.0000000, inclusive)
1052 */
fixed3_7_to_double(u_int32_t in)1053 double fixed3_7_to_double(u_int32_t in) {
1054 int32_t remapped_in = in - (180 * 10000000);
1055 double ret = (double) ((double) remapped_in / 10000000);
1056 return ret;
1057 }
1058 /*
1059 * input: a native 32 bit unsigned value between 0 and 999999999
1060 * output: a positive floating point value between 000.0000000 and 999.9999999
1061 */
fixed3_6_to_double(u_int32_t in)1062 double fixed3_6_to_double(u_int32_t in) {
1063 double ret = (double) in / 1000000.0;
1064 return ret;
1065 }
1066 /*
1067 * input: a native 32 bit unsigned value between 0 and 999.999999
1068 * output: a signed floating point value between -180000.0000 and +180000.0000
1069 */
fixed6_4_to_double(u_int32_t in)1070 double fixed6_4_to_double(u_int32_t in) {
1071 int32_t remapped_in = in - (180000 * 10000);
1072 double ret = (double) ((double) remapped_in / 10000);
1073 return ret;
1074 }
1075 /*
1076 * input: a native 32 bit nano-second counter
1077 * output: a signed floating point second counter
1078 */
ns_to_double(u_int32_t in)1079 double ns_to_double(u_int32_t in) {
1080 double ret;
1081 ret = (double) in / 1000000000;
1082 return ret;
1083 }
1084
1085 /*
1086 * input: a signed floating point value betwen -180.0000000 and + 180.0000000, inclusive)
1087 * output: a unsigned 32-bit (native endian) value between 0 and 3600000000 (inclusive)
1088 */
double_to_fixed3_7(double in)1089 u_int32_t double_to_fixed3_7(double in)
1090 {
1091 if (in < -180 || in >= 180)
1092 return 0;
1093 //This may be positive or negative.
1094 int32_t scaled_in = (int32_t) ((in) * (double) 10000000);
1095 //If the input conditions are met, this will now always be positive.
1096 u_int32_t ret = (u_int32_t) (scaled_in + ((int32_t) 180 * 10000000));
1097 return ret;
1098 }
1099 /*
1100 * input: a signed floating point value betwen -180000.0000 and + 180000.0000, inclusive)
1101 * output: a unsigned 32-bit (native endian) value between 0 and 3600000000 (inclusive)
1102 */
double_to_fixed6_4(double in)1103 u_int32_t double_to_fixed6_4(double in)
1104 {
1105 if (in < -180000.0001 || in >= 180000.0001)
1106 return 0;
1107 //This may be positive or negative.
1108 int32_t scaled_in = (int32_t) ((in) * (double) 10000);
1109 //If the input conditions are met, this will now always be positive.
1110 u_int32_t ret = (u_int32_t) (scaled_in + ((int32_t) 180000 * 10000));
1111 return ret;
1112 }
1113 /*
1114 * input: a positive floating point value between 000.0000000 and 999.9999999
1115 * output: a native 32 bit unsigned value between 0 and 999999999
1116 */
double_to_fixed3_6(double in)1117 u_int32_t double_to_fixed3_6(double in) {
1118 u_int32_t ret = (u_int32_t) (in * (double) 1000000.0);
1119 return ret;
1120 }
1121
1122 /*
1123 * input: a signed floating point second counter
1124 * output: a native 32 bit nano-second counter
1125 */
double_to_ns(double in)1126 u_int32_t double_to_ns(double in) {
1127 u_int32_t ret;
1128 ret = in * (double) 1000000000;
1129 return ret;
1130 }
1131
StringToBool(string s,int dvalue)1132 int StringToBool(string s, int dvalue) {
1133 string ls = StrLower(s);
1134
1135 if (ls == "true" || ls == "t") {
1136 return 1;
1137 } else if (ls == "false" || ls == "f") {
1138 return 0;
1139 }
1140
1141 return dvalue;
1142 }
1143
StringAppend(string s,string a,string d)1144 string StringAppend(string s, string a, string d) {
1145 if (s.length() == 0)
1146 return a;
1147
1148 if (s.length() > d.length() &&
1149 s.substr(s.length() - d.length(), d.length()) == d)
1150 return s + a;
1151
1152 return s + d + a;
1153 }
1154
1155