Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * (C) 2013-26 - ntop.org |
4 | | * |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software Foundation, |
18 | | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
19 | | * |
20 | | */ |
21 | | |
22 | | #include "ntop_includes.h" |
23 | | |
24 | | /* *************************************** */ |
25 | | |
26 | | Mac::Mac(NetworkInterface* _iface, u_int8_t _mac[6]) |
27 | 18.1k | : GenericHashEntry(_iface) { |
28 | 18.1k | if (trace_new_delete) |
29 | 0 | ntop->getTrace()->traceEvent(TRACE_NORMAL, "[new] %s", __FILE__); |
30 | 18.1k | memcpy(mac, _mac, 6); |
31 | | |
32 | 18.1k | broadcast_mac = Utils::isBroadcastMac(mac); |
33 | 18.1k | special_mac = Utils::isSpecialMac(mac); |
34 | 18.1k | empty_mac = Utils::isEmptyMac(mac); |
35 | 18.1k | source_mac = false; |
36 | 18.1k | bridge_seen_iface_id = 0, lockDeviceTypeChanges = false; |
37 | 18.1k | memset(&names, 0, sizeof(names)); |
38 | 18.1k | device_type = device_unknown, asset_map_updated = true; |
39 | 18.1k | host_pool_id = NO_HOST_POOL_ID; |
40 | 18.1k | device_os = ndpi_os_unknown; |
41 | | #ifdef NTOPNG_PRO |
42 | | captive_portal_notified = 0; |
43 | | #endif |
44 | 18.1k | model = NULL, ssid = NULL, dhcpv4_fingerprint = NULL; |
45 | 18.1k | stats_reset_requested = data_delete_requested = false; |
46 | 18.1k | stats = new (std::nothrow) MacStats(_iface); |
47 | 18.1k | stats_shadow = NULL; |
48 | 18.1k | last_stats_reset = ntop->getLastStatsReset(); /* assume fresh stats, may be |
49 | | changed by deserialize */ |
50 | | #ifdef HAVE_NEDGE |
51 | | last_counter_reset = 0; |
52 | | #endif |
53 | | |
54 | 18.1k | if (ntop->getMacManufacturers()) { |
55 | 0 | manuf = ntop->getMacManufacturers()->getManufacturer(mac); |
56 | 0 | if (manuf) checkDeviceTypeFromManufacturer(); |
57 | 0 | } else |
58 | 18.1k | manuf = NULL; |
59 | | |
60 | | #ifdef MANUF_DEBUG |
61 | | ntop->getTrace()->traceEvent( |
62 | | TRACE_NORMAL, |
63 | | "Assigned manufacturer [mac: %02x:%02x:%02x:%02x:%02x:%02x] " |
64 | | "[manufacturer: %s]", |
65 | | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], |
66 | | manuf ? manuf : "- not available -"); |
67 | | #endif |
68 | | |
69 | | #ifdef DEBUG |
70 | | char buf[32]; |
71 | | |
72 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Created %s [total %u]", |
73 | | Utils::formatMac(mac, buf, sizeof(buf)), |
74 | | iface->getNumL2Devices()); |
75 | | #endif |
76 | | |
77 | 18.1k | updateHostPool(true /* inline with packet processing */, |
78 | 18.1k | true /* first inc */); |
79 | | |
80 | 18.1k | readDHCPCache(); |
81 | | |
82 | 18.1k | if (device_type == device_unknown) guessDeviceType(); |
83 | | |
84 | | #ifdef NTOPNG_PRO |
85 | | dumpMacInfo(false /* Do not add last seen */); |
86 | | #endif |
87 | 18.1k | } |
88 | | |
89 | | /* *************************************** */ |
90 | | |
91 | 18.1k | Mac::~Mac() { |
92 | 18.1k | if (trace_new_delete) |
93 | 0 | ntop->getTrace()->traceEvent(TRACE_NORMAL, "[delete] %s", __FILE__); |
94 | | |
95 | | #ifdef NTOPNG_PRO |
96 | | dumpMacInfo(true /* Add last seen */); |
97 | | #endif |
98 | | |
99 | 18.1k | if (model) free(model); |
100 | 18.1k | if (ssid) free(ssid); |
101 | 18.1k | if (dhcpv4_fingerprint) free(dhcpv4_fingerprint); |
102 | 18.1k | freeMacData(); |
103 | 18.1k | if (stats) delete (stats); |
104 | 18.1k | if (stats_shadow) delete (stats_shadow); |
105 | | |
106 | | #ifdef DEBUG |
107 | | ntop->getTrace()->traceEvent(TRACE_NORMAL, "Deleted %s [total %u][%s]", |
108 | | Utils::formatMac(mac, buf, sizeof(buf)), |
109 | | iface->getNumL2Devices(), |
110 | | source_mac ? "Host" : "Special"); |
111 | | #endif |
112 | 18.1k | } |
113 | | |
114 | | /* *************************************** */ |
115 | | |
116 | 1.36k | void Mac::set_hash_entry_state_idle() { |
117 | 1.36k | if (source_mac) iface->decNumL2Devices(); |
118 | | |
119 | | /* Pool counters are updated both in and outside the datapath. |
120 | | So decPoolNumHosts must stay in the destructor to preserve counters |
121 | | consistency (no thread outside the datapath will change the last pool id) |
122 | | */ |
123 | | #ifdef HOST_POOLS_DEBUG |
124 | | char buf[32]; |
125 | | ntop->getTrace()->traceEvent( |
126 | | TRACE_NORMAL, |
127 | | "Going to decrease the number of pool l2 devices for %s " |
128 | | "[num pool l2 devices: %u]...", |
129 | | Utils::formatMac(mac, buf, sizeof(buf)), |
130 | | iface->getHostPools()->getNumPoolL2Devices(get_host_pool())); |
131 | | #endif |
132 | | |
133 | 1.36k | iface->decPoolNumL2Devices(get_host_pool(), true /* Mac is deleted inline */); |
134 | | |
135 | | #ifdef HOST_POOLS_DEBUG |
136 | | ntop->getTrace()->traceEvent( |
137 | | TRACE_NORMAL, |
138 | | "Number of pool l2 devices decreased." |
139 | | "[num pool l2 devices: %u]", |
140 | | iface->getHostPools()->getNumPoolL2Devices(get_host_pool())); |
141 | | #endif |
142 | | |
143 | 1.36k | GenericHashEntry::set_hash_entry_state_idle(); |
144 | 1.36k | } |
145 | | |
146 | | /* *************************************** */ |
147 | | |
148 | | #ifdef HAVE_NEDGE |
149 | | static const char* location2str(MacLocation location) { |
150 | | switch (location) { |
151 | | case located_on_lan_interface: |
152 | | return "lan"; |
153 | | case located_on_wan_interface: |
154 | | return "wan"; |
155 | | default: |
156 | | return "unknown"; |
157 | | } |
158 | | } |
159 | | #endif |
160 | | |
161 | | /* *************************************** */ |
162 | | |
163 | 0 | void Mac::lua(lua_State* vm, bool show_details, bool asListElement) { |
164 | 0 | char buf[32], *m; |
165 | |
|
166 | 0 | lua_newtable(vm); |
167 | |
|
168 | 0 | lua_push_str_table_entry(vm, "mac", |
169 | 0 | m = Utils::formatMac(mac, buf, sizeof(buf))); |
170 | 0 | lua_push_uint64_table_entry(vm, "bridge_seen_iface_id", bridge_seen_iface_id); |
171 | |
|
172 | 0 | if (show_details) { |
173 | 0 | if (manuf) lua_push_str_table_entry(vm, "manufacturer", (char*)manuf); |
174 | |
|
175 | 0 | lua_push_bool_table_entry(vm, "source_mac", source_mac); |
176 | 0 | lua_push_bool_table_entry(vm, "special_mac", special_mac); |
177 | | #ifdef HAVE_NEDGE |
178 | | lua_push_str_table_entry(vm, "location", (char*)location2str(locate())); |
179 | | #endif |
180 | 0 | lua_push_uint64_table_entry(vm, "devtype", device_type); |
181 | 0 | if (model) lua_push_str_table_entry(vm, "model", (char*)model); |
182 | 0 | if (ssid) lua_push_str_table_entry(vm, "ssid", (char*)ssid); |
183 | 0 | } |
184 | |
|
185 | 0 | if (stats) stats->lua(vm, show_details); |
186 | |
|
187 | 0 | if (dhcpv4_fingerprint) |
188 | 0 | lua_push_str_table_entry(vm, "dhcp_fingerprint", dhcpv4_fingerprint); |
189 | |
|
190 | 0 | lua_push_uint64_table_entry(vm, "seen.first", first_seen); |
191 | 0 | lua_push_uint64_table_entry(vm, "seen.last", last_seen); |
192 | 0 | lua_push_uint64_table_entry(vm, "duration", get_duration()); |
193 | 0 | lua_push_uint64_table_entry(vm, "num_hosts", getNumHosts()); |
194 | 0 | lua_push_uint64_table_entry(vm, "pool", get_host_pool()); |
195 | | #ifdef HAVE_NEDGE |
196 | | lua_push_uint32_table_entry(vm, "last_counter_reset", last_counter_reset); |
197 | | |
198 | | if (events.size() > 0) { |
199 | | u_int i = 1; |
200 | | |
201 | | lua_newtable(vm); |
202 | | |
203 | | for (std::vector<std::string>::iterator it = events.begin(); |
204 | | it != events.end(); ++it, i++) { |
205 | | lua_pushstring(vm, it->c_str()); |
206 | | lua_rawseti(vm, -2, i); |
207 | | } |
208 | | |
209 | | lua_pushstring(vm, "events"); |
210 | | lua_insert(vm, -2); |
211 | | lua_settable(vm, -3); |
212 | | } |
213 | | #endif |
214 | |
|
215 | 0 | if (asListElement) { |
216 | 0 | lua_pushstring(vm, m); |
217 | 0 | lua_insert(vm, -2); |
218 | 0 | lua_settable(vm, -3); |
219 | 0 | } |
220 | 0 | } |
221 | | /* *************************************** */ |
222 | | |
223 | 1.63M | bool Mac::isNull() const { |
224 | 1.63M | u_int8_t zero_mac[6] = {0}; |
225 | | |
226 | 1.63M | return (memcmp(mac, zero_mac, sizeof(zero_mac)) == 0 ? true : false); |
227 | 1.63M | } |
228 | | |
229 | | /* *************************************** */ |
230 | | |
231 | 203k | bool Mac::equal(const u_int8_t _mac[6]) { |
232 | 203k | if (!_mac) return (false); |
233 | 203k | if (memcmp(mac, _mac, 6) == 0) |
234 | 203k | return (true); |
235 | 739 | else |
236 | 739 | return (false); |
237 | 203k | } |
238 | | |
239 | | /* *************************************** */ |
240 | | |
241 | 0 | char* Mac::getSerializationKey(char* buf, u_int bufsize, bool short_format) { |
242 | 0 | char buf1[32]; |
243 | 0 | char* mac_ptr = Utils::formatMac(mac, buf1, sizeof(buf1)); |
244 | |
|
245 | 0 | snprintf(buf, bufsize, |
246 | 0 | short_format ? MAC_SERIALIZED_SHORT_KEY : MAC_SERIALIZED_KEY, |
247 | 0 | iface->get_id(), mac_ptr); |
248 | 0 | return (buf); |
249 | 0 | } |
250 | | |
251 | | /* *************************************** */ |
252 | | |
253 | 2.98k | bool Mac::statsResetRequested() { |
254 | 2.98k | return (stats_reset_requested || |
255 | 2.98k | (last_stats_reset < ntop->getLastStatsReset())); |
256 | 2.98k | } |
257 | | |
258 | | /* *************************************** */ |
259 | | |
260 | | #ifdef HAVE_NEDGE |
261 | | MacLocation Mac::locate() { |
262 | | if (iface->is_bridge_interface()) { |
263 | | InterfaceLocation location = |
264 | | iface->getInterfaceLocation(bridge_seen_iface_id); |
265 | | if (location == lan_interface) |
266 | | return (located_on_lan_interface); |
267 | | else if (location == wan_interface) |
268 | | return (located_on_wan_interface); |
269 | | } else { |
270 | | if (bridge_seen_iface_id == DUMMY_BRIDGE_INTERFACE_ID) |
271 | | return (located_on_lan_interface); |
272 | | } |
273 | | |
274 | | return (located_on_unknown_interface); |
275 | | } |
276 | | #endif |
277 | | |
278 | | /* *************************************** */ |
279 | | |
280 | 18.1k | void Mac::updateHostPool(bool isInlineCall, bool firstUpdate) { |
281 | 18.1k | if (!iface) return; |
282 | | |
283 | | #ifdef HOST_POOLS_DEBUG |
284 | | char buf[24]; |
285 | | u_int16_t cur_pool_id = get_host_pool(); |
286 | | |
287 | | ntop->getTrace()->traceEvent( |
288 | | TRACE_NORMAL, |
289 | | "Going to refresh pool for %s " |
290 | | "[pool id: %u]" |
291 | | "[pool num devices: %u]...", |
292 | | Utils::formatMac(get_mac(), buf, sizeof(buf)), cur_pool_id, |
293 | | iface->getHostPools()->getNumPoolL2Devices(get_host_pool())); |
294 | | #endif |
295 | | |
296 | 18.1k | if (!firstUpdate) iface->decPoolNumL2Devices(get_host_pool(), isInlineCall); |
297 | 18.1k | host_pool_id = iface->getHostPool(this); |
298 | 18.1k | iface->incPoolNumL2Devices(get_host_pool(), isInlineCall); |
299 | | |
300 | | #ifdef HOST_POOLS_DEBUG |
301 | | ntop->getTrace()->traceEvent( |
302 | | TRACE_NORMAL, |
303 | | "Refresh done. " |
304 | | "[old pool id: %u]" |
305 | | "[new pool id: %u]" |
306 | | "[old pool num devices: %u]" |
307 | | "[new pool num devices: %u]", |
308 | | cur_pool_id, get_host_pool(), |
309 | | iface->getHostPools()->getNumPoolL2Devices(cur_pool_id), |
310 | | iface->getHostPools()->getNumPoolL2Devices(get_host_pool())); |
311 | | #endif |
312 | 18.1k | } |
313 | | |
314 | | /* *************************************** */ |
315 | | |
316 | 0 | char* Mac::getDHCPName(char* const buf, ssize_t buf_size) { |
317 | 0 | if (buf && buf_size) { |
318 | 0 | m.lock(__FILE__, __LINE__); |
319 | 0 | snprintf(buf, buf_size, "%s", names.dhcp ? names.dhcp : ""); |
320 | 0 | m.unlock(__FILE__, __LINE__); |
321 | 0 | } |
322 | |
|
323 | 0 | return Utils::stringtolower(buf); |
324 | 0 | } |
325 | | |
326 | | /* *************************************** */ |
327 | | |
328 | 281 | char* Mac::getDHCPNameNotLowerCase(char* const buf, ssize_t buf_size) { |
329 | 281 | if (buf && buf_size) { |
330 | 281 | m.lock(__FILE__, __LINE__); |
331 | 281 | snprintf(buf, buf_size, "%s", names.dhcp ? names.dhcp : ""); |
332 | 281 | m.unlock(__FILE__, __LINE__); |
333 | 281 | } |
334 | | |
335 | 281 | return ((char*)buf); |
336 | 281 | } |
337 | | |
338 | | /* *************************************** */ |
339 | | |
340 | 0 | void Mac::checkDeviceTypeFromManufacturer() { |
341 | 0 | if (isNull()) return; |
342 | | |
343 | 0 | if (strstr(manuf, "Networks") /* Arista, Juniper... */ |
344 | 0 | || strstr(manuf, "Brocade") || strstr(manuf, "Routerboard") || |
345 | 0 | strstr(manuf, "Alcatel-Lucent") || strstr(manuf, "AVM")) |
346 | 0 | setDeviceType(device_networking); |
347 | 0 | else if (strstr(manuf, "Xerox")) |
348 | 0 | setDeviceType(device_printer); |
349 | 0 | else if (strstr(manuf, "Raspberry Pi") || |
350 | 0 | strstr(manuf, "PCS Computer Systems") /* VirtualBox */ |
351 | 0 | ) |
352 | 0 | setDeviceType(device_workstation); |
353 | 0 | else { |
354 | | /* https://www.techrepublic.com/blog/data-center/mac-address-scorecard-for-common-virtual-machine-platforms/ |
355 | | */ |
356 | |
|
357 | 0 | if ((!memcmp(mac, "\x00\x50\x56", 3)) || |
358 | 0 | (!memcmp(mac, "\x00\x0C\x29", 3)) || |
359 | 0 | (!memcmp(mac, "\x00\x05\x69", 3)) || |
360 | 0 | (!memcmp(mac, "\x00\x03\xFF", 3)) || |
361 | 0 | (!memcmp(mac, "\x00\x1C\x42", 3)) || |
362 | 0 | (!memcmp(mac, "\x00\x0F\x4B", 3)) || |
363 | 0 | (!memcmp(mac, "\x00\x16\x3E", 3)) || (!memcmp(mac, "\x08\x00\x27", 3))) |
364 | 0 | setDeviceType(device_workstation); /* VM */ |
365 | 0 | } |
366 | 0 | } |
367 | | |
368 | | /* *************************************** */ |
369 | | |
370 | 562k | void Mac::inlineSetModel(const char* the_model) { |
371 | 562k | if (!model && the_model && (model = strdup(the_model))) { |
372 | 34 | if (strstr(model, "AppleTV") != NULL) |
373 | 1 | setDeviceType(device_multimedia); |
374 | 33 | else if (strstr(model, "MacBook") != NULL) |
375 | 1 | setDeviceType(device_laptop); |
376 | 32 | else if (strstr(model, "AirPort") != NULL) |
377 | 1 | setDeviceType(device_wifi); |
378 | 31 | else if (strstr(model, "Mac") != NULL) |
379 | 5 | setDeviceType(device_workstation); |
380 | 26 | else if (strstr(model, "TimeCapsule") != NULL) |
381 | 1 | setDeviceType(device_nas); |
382 | 34 | } |
383 | 562k | } |
384 | | /* *************************************** */ |
385 | | |
386 | 92.8k | void Mac::inlineSetSSID(const char* s) { |
387 | 92.8k | if (!ssid && s && (ssid = strdup(s))) setDeviceType(device_wifi); |
388 | 92.8k | } |
389 | | |
390 | | /* *************************************** */ |
391 | | |
392 | 241 | void Mac::inlineSetDHCPName(const char* dhcp_name) { |
393 | 241 | if (!names.dhcp && dhcp_name && (names.dhcp = strdup(dhcp_name))) |
394 | 98 | asset_map_updated = true; |
395 | 241 | } |
396 | | |
397 | | /* *************************************** */ |
398 | | |
399 | 2.98k | void Mac::checkDataReset() { |
400 | 2.98k | if (data_delete_requested) { |
401 | 0 | deleteMacData(); |
402 | 0 | data_delete_requested = false; |
403 | 0 | } |
404 | 2.98k | } |
405 | | |
406 | | /* *************************************** */ |
407 | | |
408 | 2.98k | void Mac::checkStatsReset() { |
409 | 2.98k | if (statsResetRequested()) { |
410 | 0 | MacStats* new_stats = new (std::nothrow) MacStats(iface); |
411 | |
|
412 | 0 | stats_shadow = stats; |
413 | 0 | stats = new_stats; |
414 | 0 | last_stats_reset = ntop->getLastStatsReset(); |
415 | 0 | stats_reset_requested = false; |
416 | |
|
417 | | #ifdef HAVE_NEDGE |
418 | | char buf[32]; |
419 | | |
420 | | ntop->getTrace()->traceEvent(TRACE_INFO, "Reset stats for MAC %s", |
421 | | print(buf, sizeof(buf))); |
422 | | last_counter_reset = time(NULL); |
423 | | #endif |
424 | 0 | } |
425 | 2.98k | } |
426 | | |
427 | | /* *************************************** */ |
428 | | |
429 | 2.98k | void Mac::periodic_stats_update(const struct timeval* tv, bool force_update) { |
430 | 2.98k | checkDataReset(); |
431 | 2.98k | checkStatsReset(); |
432 | 2.98k | if (stats) stats->updateStats(tv); |
433 | 2.98k | } |
434 | | |
435 | | /* *************************************** */ |
436 | | |
437 | 18.1k | void Mac::readDHCPCache() { |
438 | | /* Check DHCP cache */ |
439 | 18.1k | char mac_str[24], buf[64], key[CONST_MAX_LEN_REDIS_KEY]; |
440 | | |
441 | 18.1k | if (!names.dhcp && !isNull()) { |
442 | 5.74k | Utils::formatMac(get_mac(), mac_str, sizeof(mac_str)); |
443 | | |
444 | 5.74k | snprintf(key, sizeof(key), DHCP_CACHE, iface->get_id(), mac_str); |
445 | | |
446 | 5.74k | if (ntop->getRedis()->get(key, buf, sizeof(buf)) == 0) { |
447 | 84 | names.dhcp = strdup(buf); |
448 | 84 | } |
449 | 5.74k | } |
450 | 18.1k | } |
451 | | |
452 | | /* *************************************** */ |
453 | | |
454 | 18.1k | void Mac::freeMacData() { |
455 | | // TODO: allow fingerprint, ssid, and model to be resettable |
456 | 18.1k | if (names.dhcp) { |
457 | 182 | free(names.dhcp); |
458 | 182 | names.dhcp = NULL; |
459 | 182 | } |
460 | 18.1k | } |
461 | | |
462 | | /* *************************************** */ |
463 | | |
464 | 0 | void Mac::deleteMacData() { |
465 | 0 | m.lock(__FILE__, __LINE__); |
466 | 0 | freeMacData(); |
467 | 0 | m.unlock(__FILE__, __LINE__); |
468 | 0 | source_mac = false; |
469 | 0 | device_type = device_unknown; |
470 | | #ifdef NTOPNG_PRO |
471 | | captive_portal_notified = false; |
472 | | #endif |
473 | 0 | first_seen = last_seen; |
474 | 0 | } |
475 | | |
476 | | /* *************************************** */ |
477 | | |
478 | 0 | u_int64_t Mac::get_mac64() { return Utils::encodeMacTo64(mac); } |
479 | | |
480 | | /* *************************************** */ |
481 | | |
482 | 2.98k | bool Mac::is_hash_entry_state_idle_transition_ready() { |
483 | | /* ntop->getTrace()->traceEvent(TRACE_NORMAL, |
484 | | "Is idle, current time, last seen, configured expiration: " |
485 | | "[ %s | %d | %d | %d ]", |
486 | | is_active_entry_now_idle(ntop->getPrefs()->macAddressCacheDuration()) |
487 | | ? "true" |
488 | | : "false", |
489 | | time(NULL), last_seen, ntop->getPrefs()->macAddressCacheDuration()); |
490 | | */ |
491 | 2.98k | return ((getUses() == 0) && is_active_entry_now_idle( |
492 | 1.40k | ntop->getPrefs()->macAddressCacheDuration())); |
493 | 2.98k | } |
494 | | |
495 | | /* *************************************** */ |
496 | | |
497 | 0 | void Mac::setDHCPFingerprint(const char* f) { |
498 | 0 | if ((f == NULL) || (f[0] == '\0')) return; |
499 | | |
500 | 0 | if (dhcpv4_fingerprint != NULL) free(dhcpv4_fingerprint); |
501 | |
|
502 | 0 | dhcpv4_fingerprint = strdup(f); |
503 | |
|
504 | | #ifdef NTOPNG_PRO |
505 | | analyzeDevice(); |
506 | | #endif |
507 | 0 | } |
508 | | |
509 | | /* *************************************** */ |
510 | | |
511 | 18.1k | void Mac::guessDeviceType() { |
512 | 18.1k | if (manuf == NULL) return; |
513 | | |
514 | | /* ntop->getTrace()->traceEvent(TRACE_ERROR, "*** %s", manuf); */ |
515 | | |
516 | 0 | if (strncasecmp(manuf, "Sonos", 5) == 0) |
517 | 0 | device_type = device_wifi; |
518 | 0 | else if ((strncasecmp(manuf, "Tp-Link", 7) == 0) || |
519 | 0 | (strncasecmp(manuf, "Technicolor", 11) == 0)) |
520 | 0 | device_type = device_networking; |
521 | 0 | else if (strncasecmp(manuf, "ASUSTek", 7) == 0) |
522 | 0 | device_type = device_workstation; |
523 | 0 | } |
524 | | |
525 | | /* *************************************** */ |
526 | | |
527 | 1.60M | void Mac::setDeviceType(DeviceType devtype) { |
528 | 1.60M | if (isNull() || (device_type == devtype)) return; |
529 | | |
530 | | /* Called by ntopng when it can guess a device type during normal packet |
531 | | * processing */ |
532 | 58 | if (!lockDeviceTypeChanges) { |
533 | 58 | device_type = devtype; |
534 | 58 | asset_map_updated = true; |
535 | 58 | ntop->trackAssetChange("MAC", "setDeviceType", this, NULL, NULL, NULL, |
536 | 58 | (char*)Utils::deviceType2str(devtype)); |
537 | 58 | } |
538 | 58 | } |
539 | | |
540 | | /* *************************************** */ |
541 | | |
542 | 0 | void Mac::setDeviceOS(ndpi_os _os) { |
543 | 0 | if (device_os == _os) return; |
544 | | |
545 | 0 | device_os = _os, asset_map_updated = true; |
546 | 0 | ntop->trackAssetChange("MAC", "setDeviceOS", this, NULL, NULL, NULL, |
547 | 0 | (char*)Utils::OS2Str(_os)); |
548 | 0 | } |
549 | | |
550 | | /* *************************************** */ |
551 | | |
552 | | #ifdef HAVE_NEDGE |
553 | | void Mac::logMacEvent(char* msg) { |
554 | | char buf[512], theDate[32]; |
555 | | time_t theTime = time(NULL); |
556 | | struct tm result; |
557 | | |
558 | | strftime(theDate, sizeof(theDate), "%d/%b/%Y %H:%M:%S", |
559 | | localtime_r(&theTime, &result)); |
560 | | snprintf(buf, sizeof(buf), "%s %s", theDate, msg); |
561 | | |
562 | | events.insert(events.begin(), buf); /* Asdds a message at the beginning */ |
563 | | |
564 | | if (events.size() > 25 /* max number of events */) |
565 | | events.pop_back(); /* Deletes last element */ |
566 | | } |
567 | | #endif |