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