1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
// 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 a uint64_t, value is service name (STRING)
#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
#define SIMPLE_HASHTABLE_NAME _SERVICENAMES_CACHE
#include "libnetdata/simple_hashtable.h"
typedef struct servicenames_cache {
SPINLOCK spinlock;
SIMPLE_HASHTABLE_SERVICENAMES_CACHE ht;
} SERVICENAMES_CACHE;
static inline uint64_t system_servicenames_key(uint16_t port, uint16_t ipproto) {
return ((uint64_t)ipproto << 16) | (uint64_t)port;
}
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) {
uint64_t key = system_servicenames_key(port, ipproto);
spinlock_lock(&sc->spinlock);
SIMPLE_HASHTABLE_SLOT_SERVICENAMES_CACHE *sl = simple_hashtable_get_slot_SERVICENAMES_CACHE(&sc->ht, key, &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, key, 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
|