master
h 96 lines 3.01 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef NETDATA_SYSTEM_SERVICES_H
4 #define NETDATA_SYSTEM_SERVICES_H
5
6 #include "libnetdata/libnetdata.h"
7 #include <netdb.h>
8
9 // --------------------------------------------------------------------------------------------------------------------
10 // hashtable for caching port and protocol to service name mappings
11 // key is the combination of protocol and port packed into an uint64_t, value is service name (STRING)
12
13 #define SIMPLE_HASHTABLE_VALUE_TYPE STRING *
14 #define SIMPLE_HASHTABLE_NAME _SERVICENAMES_CACHE
15 #include "libnetdata/simple_hashtable/simple_hashtable.h"
16
17 typedef struct servicenames_cache {
18 SPINLOCK spinlock;
19 SIMPLE_HASHTABLE_SERVICENAMES_CACHE ht;
20 } SERVICENAMES_CACHE;
21
22 static inline const char *system_servicenames_ipproto2str(uint16_t ipproto) {
23 return (ipproto == IPPROTO_TCP) ? "tcp" : "udp";
24 }
25
26 static inline const char *static_portnames(uint16_t port, uint16_t ipproto) {
27 if(port == 19999 && ipproto == IPPROTO_TCP)
28 return "netdata";
29
30 if(port == 8125)
31 return "statsd";
32
33 return NULL;
34 }
35
36 static inline STRING *system_servicenames_cache_lookup(SERVICENAMES_CACHE *sc, uint16_t port, uint16_t ipproto) {
37 struct {
38 uint16_t ipproto;
39 uint16_t port;
40 } key = {
41 .ipproto = ipproto,
42 .port = port,
43 };
44 XXH64_hash_t hash = XXH3_64bits(&key, sizeof(key));
45
46 spinlock_lock(&sc->spinlock);
47
48 SIMPLE_HASHTABLE_SLOT_SERVICENAMES_CACHE *sl = simple_hashtable_get_slot_SERVICENAMES_CACHE(&sc->ht, hash, &key, true);
49 STRING *s = SIMPLE_HASHTABLE_SLOT_DATA(sl);
50 if (!s) {
51 const char *st = static_portnames(port, ipproto);
52 if(st) {
53 s = string_strdupz(st);
54 }
55 else {
56 struct servent *se = getservbyport(htons(port), system_servicenames_ipproto2str(ipproto));
57
58 if (!se || !se->s_name) {
59 char name[50];
60 snprintfz(name, sizeof(name), "%u/%s", port, system_servicenames_ipproto2str(ipproto));
61 s = string_strdupz(name);
62 }
63 else
64 s = string_strdupz(se->s_name);
65 }
66
67 simple_hashtable_set_slot_SERVICENAMES_CACHE(&sc->ht, sl, hash, s);
68 }
69
70 s = string_dup(s);
71 spinlock_unlock(&sc->spinlock);
72 return s;
73 }
74
75 static inline SERVICENAMES_CACHE *system_servicenames_cache_init(void) {
76 SERVICENAMES_CACHE *sc = callocz(1, sizeof(*sc));
77 spinlock_init(&sc->spinlock);
78 simple_hashtable_init_SERVICENAMES_CACHE(&sc->ht, 100);
79 return sc;
80 }
81
82 static inline void system_servicenames_cache_destroy(SERVICENAMES_CACHE *sc) {
83 spinlock_lock(&sc->spinlock);
84
85 for (SIMPLE_HASHTABLE_SLOT_SERVICENAMES_CACHE *sl = simple_hashtable_first_read_only_SERVICENAMES_CACHE(&sc->ht);
86 sl;
87 sl = simple_hashtable_next_read_only_SERVICENAMES_CACHE(&sc->ht, sl)) {
88 STRING *s = SIMPLE_HASHTABLE_SLOT_DATA(sl);
89 string_freez(s);
90 }
91
92 simple_hashtable_destroy_SERVICENAMES_CACHE(&sc->ht);
93 freez(sc);
94 }
95
96 #endif //NETDATA_SYSTEM_SERVICES_H