summaryrefslogtreecommitdiffstats
path: root/src/libnetdata/os/system-maps/system-services.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnetdata/os/system-maps/system-services.h')
-rw-r--r--src/libnetdata/os/system-maps/system-services.h96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/libnetdata/os/system-maps/system-services.h b/src/libnetdata/os/system-maps/system-services.h
new file mode 100644
index 000000000..5d3592bbf
--- /dev/null
+++ b/src/libnetdata/os/system-maps/system-services.h
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef NETDATA_SYSTEM_SERVICES_H
+#define NETDATA_SYSTEM_SERVICES_H
+
+#include "libnetdata/libnetdata.h"
+#include <netdb.h>
+
+// --------------------------------------------------------------------------------------------------------------------
+// hashtable for caching port and protocol to service name mappings
+// key is the combination of protocol and port packed into an uint64_t, value is service name (STRING)
+
+#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
+#define SIMPLE_HASHTABLE_NAME _SERVICENAMES_CACHE
+#include "libnetdata/simple_hashtable/simple_hashtable.h"
+
+typedef struct servicenames_cache {
+ SPINLOCK spinlock;
+ SIMPLE_HASHTABLE_SERVICENAMES_CACHE ht;
+} SERVICENAMES_CACHE;
+
+static inline const char *system_servicenames_ipproto2str(uint16_t ipproto) {
+ return (ipproto == IPPROTO_TCP) ? "tcp" : "udp";
+}
+
+static inline const char *static_portnames(uint16_t port, uint16_t ipproto) {
+ if(port == 19999 && ipproto == IPPROTO_TCP)
+ return "netdata";
+
+ if(port == 8125)
+ return "statsd";
+
+ return NULL;
+}
+
+static inline STRING *system_servicenames_cache_lookup(SERVICENAMES_CACHE *sc, uint16_t port, uint16_t ipproto) {
+ struct {
+ uint16_t ipproto;
+ uint16_t port;
+ } key = {
+ .ipproto = ipproto,
+ .port = port,
+ };
+ XXH64_hash_t hash = XXH3_64bits(&key, sizeof(key));
+
+ spinlock_lock(&sc->spinlock);
+
+ SIMPLE_HASHTABLE_SLOT_SERVICENAMES_CACHE *sl = simple_hashtable_get_slot_SERVICENAMES_CACHE(&sc->ht, hash, &key, true);
+ STRING *s = SIMPLE_HASHTABLE_SLOT_DATA(sl);
+ if (!s) {
+ const char *st = static_portnames(port, ipproto);
+ if(st) {
+ s = string_strdupz(st);
+ }
+ else {
+ struct servent *se = getservbyport(htons(port), system_servicenames_ipproto2str(ipproto));
+
+ if (!se || !se->s_name) {
+ char name[50];
+ snprintfz(name, sizeof(name), "%u/%s", port, system_servicenames_ipproto2str(ipproto));
+ s = string_strdupz(name);
+ }
+ else
+ s = string_strdupz(se->s_name);
+ }
+
+ simple_hashtable_set_slot_SERVICENAMES_CACHE(&sc->ht, sl, hash, s);
+ }
+
+ s = string_dup(s);
+ spinlock_unlock(&sc->spinlock);
+ return s;
+}
+
+static inline SERVICENAMES_CACHE *system_servicenames_cache_init(void) {
+ SERVICENAMES_CACHE *sc = callocz(1, sizeof(*sc));
+ spinlock_init(&sc->spinlock);
+ simple_hashtable_init_SERVICENAMES_CACHE(&sc->ht, 100);
+ return sc;
+}
+
+static inline void system_servicenames_cache_destroy(SERVICENAMES_CACHE *sc) {
+ spinlock_lock(&sc->spinlock);
+
+ for (SIMPLE_HASHTABLE_SLOT_SERVICENAMES_CACHE *sl = simple_hashtable_first_read_only_SERVICENAMES_CACHE(&sc->ht);
+ sl;
+ sl = simple_hashtable_next_read_only_SERVICENAMES_CACHE(&sc->ht, sl)) {
+ STRING *s = SIMPLE_HASHTABLE_SLOT_DATA(sl);
+ string_freez(s);
+ }
+
+ simple_hashtable_destroy_SERVICENAMES_CACHE(&sc->ht);
+ freez(sc);
+}
+
+#endif //NETDATA_SYSTEM_SERVICES_H