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 <stdio.h>
22 #include "configfile.h"
23 #include "messagebus.h"
24 #include "util.h"
25 #include "manuf.h"
26 
Manuf(GlobalRegistry * in_globalreg)27 Manuf::Manuf(GlobalRegistry *in_globalreg) {
28 	globalreg = in_globalreg;
29 
30 	if (globalreg->kismet_config == NULL) {
31 		fprintf(stderr, "FATAL OOPS:  Manuf called before kismet_config\n");
32 		exit(1);
33 	}
34 
35 	vector<string> fname = globalreg->kismet_config->FetchOptVec("ouifile");
36 	if (fname.size() == 0) {
37 		_MSG("Missing 'ouifile' option in config, will not resolve manufacturer "
38 			 "names for MAC addresses", MSGFLAG_ERROR);
39 		return;
40 	}
41 
42 	for (unsigned int x = 0; x < fname.size(); x++) {
43 		if ((mfile = fopen(fname[x].c_str(), "r")) != NULL) {
44 			_MSG("Opened OUI file '" + fname[x], MSGFLAG_INFO);
45 			break;
46 		}
47 
48 		_MSG("Could not open OUI file '" + fname[x] + "': " +
49 			 string(strerror(errno)), MSGFLAG_ERROR);
50 	}
51 
52 	if (mfile == NULL) {
53 		_MSG("No OUI files were available, will not resolve manufacturer "
54 			 "names for MAC addresses", MSGFLAG_ERROR);
55 		return;
56 	}
57 
58 	IndexOUI();
59 }
60 
IndexOUI()61 void Manuf::IndexOUI() {
62 	char buf[1024];
63 	int line = 0;
64 	fpos_t prev_pos;
65 	short int m[3];
66 
67 	if (mfile == NULL)
68 		return;
69 
70 	_MSG("Indexing manufacturer db", MSGFLAG_INFO);
71 
72 	fgetpos(mfile, &prev_pos);
73 
74 	while (!feof(mfile)) {
75 		if (fgets(buf, 1024, mfile) == NULL || feof(mfile))
76 			break;
77 
78 		if ((line % 50) == 0) {
79 			if (sscanf(buf, "%hx:%hx:%hx",
80 					   &(m[0]), &(m[1]), &(m[2])) == 3) {
81 
82 				// Log a position at the previous pos - which is the line before
83 				// this one, so we're inclusive
84 				index_pos ip;
85 				uint32_t oui;
86 
87 				oui = 0;
88 				oui |= (uint32_t) m[0] << 16;
89 				oui |= (uint32_t) m[1] << 8;
90 				oui |= (uint32_t) m[2];
91 
92 				ip.oui = oui;
93 				ip.pos = prev_pos;
94 
95 				index_vec.push_back(ip);
96 			} else {
97 				// Compensate for not getting a reasonable line (probably a
98 				// comment) by decrementing here so we keep trying at each
99 				// index point until we get info we're looking for
100 				line--;
101 			}
102 		}
103 
104 		fgetpos(mfile, &prev_pos);
105 		line++;
106 	}
107 
108 	_MSG("Completed indexing manufacturer db, " + IntToString(line) + " lines " +
109 		 IntToString(index_vec.size()) + " indexes", MSGFLAG_INFO);
110 }
111 
LookupOUI(mac_addr in_mac)112 string Manuf::LookupOUI(mac_addr in_mac) {
113 	uint32_t soui = in_mac.OUI(), toui;
114 	int matched = -1;
115 	char buf[1024];
116 	short int m[3];
117 	char manuf[16];
118 
119 	if (mfile == NULL)
120 		return "Unknown";
121 
122 	// Use the cache first
123 	if (oui_map.find(soui) != oui_map.end()) {
124 		return oui_map[soui].manuf;
125 	}
126 
127 	for (unsigned int x = 0; x < index_vec.size(); x++) {
128 		if (soui > index_vec[x].oui)
129 			continue;
130 
131 		matched = x - 1;
132 		break;
133 	}
134 
135 	// Cache unknown to save us effort in the future
136 	if (matched < 0) {
137 		manuf_data md;
138 		md.oui = soui;
139 		md.manuf = "Unknown";
140 		oui_map[soui] = md;
141 
142 		return md.manuf;
143 	}
144 
145 	fsetpos(mfile, &(index_vec[matched].pos));
146 
147 	while (!feof(mfile)) {
148 		if (fgets(buf, 1024, mfile) == NULL || feof(mfile))
149 			break;
150 
151 		if (sscanf(buf, "%hx:%hx:%hx\t%10s",
152 				   &(m[0]), &(m[1]), &(m[2]), manuf) == 4) {
153 
154 			// Log a position at the previous pos - which is the line before
155 			// this one, so we're inclusive
156 			toui = 0;
157 			toui |= (uint32_t) m[0] << 16;
158 			toui |= (uint32_t) m[1] << 8;
159 			toui |= (uint32_t) m[2];
160 
161 			if (toui == soui) {
162 				manuf_data md;
163 				md.oui = soui;
164 				md.manuf = MungeToPrintable(string(manuf));
165 				oui_map[soui] = md;
166 
167 				return md.manuf;
168 			}
169 
170 			if (toui > soui) {
171 				manuf_data md;
172 				md.oui = soui;
173 				md.manuf = "Unknown";
174 				oui_map[soui] = md;
175 
176 				return md.manuf;
177 			}
178 		}
179 	}
180 
181 	return "Unknown";
182 }
183 
184 
185