return result.second;
}
+size_t HostTracker::get_client_count()
+{
+ lock_guard<mutex> lck(host_tracker_lock);
+ return clients.size();
+}
+
+HostClient HostTracker::get_client(AppId id, const char* version, AppId service, bool& is_new)
+{
+ lock_guard<mutex> lck(host_tracker_lock);
+
+ for ( const auto& c : clients )
+ {
+ if (c.id != APP_ID_NONE and c.id == id and c.service == service
+ and ((c.version[0] == '\0' and !version) or
+ (version and strncmp(c.version, version, INFO_SIZE) == 0)))
+ {
+ return c;
+ }
+ }
+
+ is_new = true;
+ clients.emplace_back(id, version, service);
+ return clients.back();
+}
+
static inline string to_time_string(uint32_t p_time)
{
time_t raw_time = (time_t) p_time;
}
}
+ if ( !clients.empty() )
+ {
+ str += "\nclients size: " + to_string(clients.size());
+ for ( const auto& c : clients )
+ {
+ str += "\n id: " + to_string(c.id)
+ + ", service: " + to_string(c.service);
+ if ( c.version[0] != '\0' )
+ str += ", version: " + string(c.version);
+ }
+ }
+
auto total = network_protos.size();
if ( total )
{
char version[INFO_SIZE] = { 0 };
};
+struct HostClient
+{
+ HostClient() = default;
+ HostClient(AppId clientid, const char *ver, AppId ser) :
+ id(clientid), service(ser)
+ {
+ if (ver)
+ {
+ strncpy(version, ver, INFO_SIZE);
+ version[INFO_SIZE-1] = '\0';
+ }
+ }
+
+ AppId id;
+ char version[INFO_SIZE] = { 0 };
+ AppId service;
+};
+
enum HostType
{
HOST_TYPE_HOST=0,
typedef HostCacheAllocIp<HostMac> HostMacAllocator;
typedef HostCacheAllocIp<HostApplication> HostAppAllocator;
+typedef HostCacheAllocIp<HostClient> HostClientAllocator;
class SO_PUBLIC HostTracker
{
bool update_service_info(HostApplication& ha, const char* vendor, const char* version);
void remove_inferred_services();
+ size_t get_client_count();
+ HostClient get_client(AppId id, const char* version, AppId service, bool& is_new);
bool add_tcp_fingerprint(uint32_t fpid);
// This should be updated whenever HostTracker data members are changed
std::vector<uint16_t, HostCacheAllocIp<uint16_t>> network_protos;
std::vector<uint8_t, HostCacheAllocIp<uint8_t>> xport_protos;
std::vector<HostApplication, HostAppAllocator> services;
+ std::vector<HostClient, HostClientAllocator> clients;
std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> tcp_fpids;
bool vlan_tag_present = false;
if ( appid_change_bits[APPID_SERVICE_BIT] and service > APP_ID_NONE )
discover_service(p, proto, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(),
src_mac, conf, logger, service);
+
+ if (appid_change_bits[APPID_CLIENT_BIT] and client > APP_ID_NONE
+ and service > APP_ID_NONE)
+ {
+ const char* version = appid_session_api.get_client_version();
+ discover_client(p, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac,
+ conf, logger, version, client, service);
+ }
}
if ( appid_change_bits[APPID_SERVICE_VENDOR_BIT] or appid_change_bits[APPID_VERSION_BIT] )
ha.hits = 0;
rt->update_service(ha);
}
+
+void RnaAppDiscovery::discover_client(const Packet* p, RnaTracker& rt,
+ const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf,
+ RnaLogger& logger, const char* version, AppId client, AppId service)
+{
+ if (conf and conf->max_host_client_apps and
+ conf->max_host_client_apps <= rt->get_client_count())
+ return;
+
+ bool is_new = false;
+
+ auto hc = rt->get_client(client, version, service, is_new);
+ if ( is_new )
+ {
+ logger.log(RNA_EVENT_NEW, NEW_CLIENT_APP, p, &rt, src_ip, src_mac, &hc);
+ }
+}
const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf,
RnaLogger& logger, AppId service = APP_ID_NONE);
+ static void discover_client(const snort::Packet* p, RnaTracker& rt,
+ const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf,
+ RnaLogger& logger, const char* version, AppId client, AppId service);
private:
static void update_service_info(const snort::Packet* p, IpProtocol proto, const char* vendor,
const char* version, RnaTracker& rt, const snort::SfIp* ip, const uint8_t* src_mac,
ip.set(rle.ip); // using this instead of packet's ip to support ARP
debug_logf(rna_trace, nullptr, "RNA log: type %u, subtype %u, mac %s, ip %s\n",
rle.type, rle.subtype, macbuf, ip.ntop(ipbuf));
+ if (rle.hc)
+ {
+ if (rle.hc->version[0] != '\0')
+ debug_logf(rna_trace, nullptr,
+ "RNA client log: client %u, service %u, version %s\n",
+ rle.hc->id, rle.hc->service, rle.hc->version);
+ else
+ debug_logf(rna_trace, nullptr, "RNA client log: client %u, service %u\n",
+ rle.hc->id, rle.hc->service);
+ }
}
else
debug_logf(rna_trace, nullptr, "RNA log: type %u, subtype %u, mac %s\n",
const struct in6_addr* src_ip, const uint8_t* src_mac, const HostApplication* ha)
{
log(type, subtype, src_ip, src_mac, ht, p, 0, 0,
- nullptr, ha, nullptr, nullptr);
+ nullptr, ha, nullptr, nullptr, nullptr);
+}
+
+void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
+ const struct in6_addr* src_ip, const uint8_t* src_mac, const HostClient* hc)
+{
+ log(type, subtype, src_ip, src_mac, ht, p, 0, 0,
+ nullptr, nullptr, nullptr, nullptr, hc);
}
void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
const struct in6_addr* src_ip, const uint8_t* src_mac, const TcpFingerprint* tfp)
{
log(type, subtype, src_ip, src_mac, ht, p, 0, 0,
- nullptr, nullptr, tfp, nullptr);
+ nullptr, nullptr, tfp, nullptr, nullptr);
}
void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
const struct in6_addr* src_ip, const uint8_t* src_mac, uint32_t event_time)
{
log(type, subtype, src_ip, src_mac, ht, p, event_time, 0,
- nullptr, nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr);
}
void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
const struct in6_addr* src_ip, const uint8_t* src_mac, const HostMac* hm, uint32_t event_time)
{
log(type, subtype, src_ip, src_mac, ht, p, event_time, 0,
- hm, nullptr, nullptr, nullptr);
+ hm, nullptr, nullptr, nullptr, nullptr);
}
void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
uint16_t proto, const uint8_t* src_mac, const struct in6_addr* src_ip, uint32_t event_time)
{
log(type, subtype, src_ip, src_mac, ht, p, event_time, proto,
- nullptr, nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr);
}
void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, const uint8_t* src_mac,
const struct in6_addr* src_ip, RnaTracker* ht, uint32_t event_time, void* cond_var)
{
log(type, subtype, src_ip, src_mac, ht, p, event_time, 0,
- nullptr, nullptr, nullptr, cond_var);
+ nullptr, nullptr, nullptr, cond_var, nullptr);
}
bool RnaLogger::log(uint16_t type, uint16_t subtype, const struct in6_addr* src_ip,
const uint8_t* src_mac, RnaTracker* ht, const Packet* p, uint32_t event_time,
uint16_t proto, const HostMac* hm, const HostApplication* ha, const TcpFingerprint* tfp,
- void* cond_var)
+ void* cond_var, const HostClient* hc)
{
if ( !enabled )
return false;
assert(ht);
- RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var, ha, tfp);
+ RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var, ha, tfp, hc);
if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) )
rle.ip = src_ip;
else
{
RnaLoggerEvent (uint16_t t, uint16_t st, const uint8_t* mc, const RnaTracker* rt,
const snort::HostMac* hmp, uint16_t pr, void* cv, const snort::HostApplication* hap,
- const snort::TcpFingerprint* tf) : type(t), subtype(st), mac(mc), ht(rt), hm(hmp),
- proto(pr), cond_var(cv), ha(hap), tfp(tf) { }
+ const snort::TcpFingerprint* tf, const snort::HostClient* hcp) : type(t), subtype(st),
+ mac(mc), ht(rt), hm(hmp), proto(pr), cond_var(cv), ha(hap), tfp(tf), hc(hcp) { }
uint16_t type;
uint16_t subtype;
void* cond_var;
const snort::HostApplication* ha;
const snort::TcpFingerprint* tfp;
+ const snort::HostClient* hc;
};
class RnaLogger
void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::HostApplication* ha);
+ // for host client
+ void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+ const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::HostClient* hcp);
+
// for tcp fingerprint
void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::TcpFingerprint* tfp);
const uint8_t* src_mac, RnaTracker* ht, const snort::Packet* p = nullptr,
uint32_t event_time = 0, uint16_t proto = 0, const snort::HostMac* hm = nullptr,
const snort::HostApplication* ha = nullptr, const snort::TcpFingerprint* tfp = nullptr,
- void* cond_var = nullptr);
+ void* cond_var = nullptr, const snort::HostClient* hc = nullptr);
private:
const bool enabled;
#define NEW_NET_PROTOCOL 3
#define NEW_XPORT_PROTOCOL 4
#define NEW_UDP_SERVICE 6
+ #define NEW_CLIENT_APP 7
#define NEW_OS 8
#define RNA_EVENT_CHANGE 1001