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 += "&amp;";
584 		else if (in_str[x] == '<')
585 			ret += "&lt;";
586 		else if (in_str[x] == '>')
587 			ret += "&gt;";
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