summaryrefslogtreecommitdiffstats
path: root/libnetdata/socket/socket.h
blob: e4ca08d47fede385983321f853d349686ed1be0e (plain)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef NETDATA_SOCKET_H
#define NETDATA_SOCKET_H

#include "../libnetdata.h"

#ifndef MAX_LISTEN_FDS
#define MAX_LISTEN_FDS 50
#endif

typedef enum web_client_acl {
    WEB_CLIENT_ACL_NONE         = (0),
    WEB_CLIENT_ACL_NOCHECK      = (1 << 0),          // Don't check anything - this should work on all channels
    WEB_CLIENT_ACL_DASHBOARD    = (1 << 1),
    WEB_CLIENT_ACL_REGISTRY     = (1 << 2),
    WEB_CLIENT_ACL_BADGE        = (1 << 3),
    WEB_CLIENT_ACL_MGMT         = (1 << 4),
    WEB_CLIENT_ACL_STREAMING    = (1 << 5),
    WEB_CLIENT_ACL_NETDATACONF  = (1 << 6),
    WEB_CLIENT_ACL_SSL_OPTIONAL = (1 << 7),
    WEB_CLIENT_ACL_SSL_FORCE    = (1 << 8),
    WEB_CLIENT_ACL_SSL_DEFAULT  = (1 << 9),
    WEB_CLIENT_ACL_ACLK         = (1 << 10),
    WEB_CLIENT_ACL_WEBRTC       = (1 << 11),
    WEB_CLIENT_ACL_BEARER_OPTIONAL = (1 << 12), // allow unprotected access if bearer is not enabled in netdata
    WEB_CLIENT_ACL_BEARER_REQUIRED = (1 << 13), // allow access only if a valid bearer is used
} WEB_CLIENT_ACL;

#define WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC (WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_ACLK | WEB_CLIENT_ACL_WEBRTC | WEB_CLIENT_ACL_BEARER_OPTIONAL)
#define WEB_CLIENT_ACL_ACLK_WEBRTC_DASHBOARD_WITH_BEARER (WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_ACLK | WEB_CLIENT_ACL_WEBRTC | WEB_CLIENT_ACL_BEARER_REQUIRED)

#ifdef NETDATA_DEV_MODE
#define ACL_DEV_OPEN_ACCESS WEB_CLIENT_ACL_NOCHECK
#else
#define ACL_DEV_OPEN_ACCESS 0
#endif

#define WEB_CLIENT_ACL_ALL 0xFFFF

#define web_client_can_access_dashboard(w) ((w)->acl & WEB_CLIENT_ACL_DASHBOARD)
#define web_client_can_access_registry(w) ((w)->acl & WEB_CLIENT_ACL_REGISTRY)
#define web_client_can_access_badges(w) ((w)->acl & WEB_CLIENT_ACL_BADGE)
#define web_client_can_access_mgmt(w) ((w)->acl & WEB_CLIENT_ACL_MGMT)
#define web_client_can_access_stream(w) ((w)->acl & WEB_CLIENT_ACL_STREAMING)
#define web_client_can_access_netdataconf(w) ((w)->acl & WEB_CLIENT_ACL_NETDATACONF)
#define web_client_is_using_ssl_optional(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_OPTIONAL)
#define web_client_is_using_ssl_force(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_FORCE)
#define web_client_is_using_ssl_default(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_DEFAULT)

typedef struct listen_sockets {
    struct config *config;              // the config file to use
    const char *config_section;         // the netdata configuration section to read settings from
    const char *default_bind_to;        // the default bind to configuration string
    uint16_t default_port;              // the default port to use
    int backlog;                        // the default listen backlog to use

    size_t opened;                      // the number of sockets opened
    size_t failed;                      // the number of sockets attempted to open, but failed
    int fds[MAX_LISTEN_FDS];            // the open sockets
    char *fds_names[MAX_LISTEN_FDS];    // descriptions for the open sockets
    int fds_types[MAX_LISTEN_FDS];      // the socktype for the open sockets (SOCK_STREAM, SOCK_DGRAM)
    int fds_families[MAX_LISTEN_FDS];   // the family of the open sockets (AF_UNIX, AF_INET, AF_INET6)
    WEB_CLIENT_ACL fds_acl_flags[MAX_LISTEN_FDS];  // the acl to apply to the open sockets (dashboard, badges, streaming, netdata.conf, management)
} LISTEN_SOCKETS;

char *strdup_client_description(int family, const char *protocol, const char *ip, uint16_t port);

int listen_sockets_setup(LISTEN_SOCKETS *sockets);
void listen_sockets_close(LISTEN_SOCKETS *sockets);

void foreach_entry_in_connection_string(const char *destination, bool (*callback)(char *entry, void *data), void *data);
int connect_to_this_ip46(int protocol, int socktype, const char *host, uint32_t scope_id, const char *service, struct timeval *timeout);
int connect_to_this(const char *definition, int default_port, struct timeval *timeout);
int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size);
int connect_to_one_of_urls(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size);


#ifdef ENABLE_HTTPS
ssize_t recv_timeout(NETDATA_SSL *ssl,int sockfd, void *buf, size_t len, int flags, int timeout);
ssize_t send_timeout(NETDATA_SSL *ssl,int sockfd, void *buf, size_t len, int flags, int timeout);
#else
ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout);
ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout);
#endif

bool fd_is_socket(int fd);
bool sock_has_output_error(int fd);

int sock_setnonblock(int fd);
int sock_delnonblock(int fd);
int sock_setreuse(int fd, int reuse);
int sock_setreuse_port(int fd, int reuse);
int sock_enlarge_in(int fd);
int sock_enlarge_out(int fd);

int connection_allowed(int fd, char *client_ip, char *client_host, size_t hostsize,
                              SIMPLE_PATTERN *access_list, const char *patname, int allow_dns);
int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *client_port, size_t portsize,
                         char *client_host, size_t hostsize, SIMPLE_PATTERN *access_list, int allow_dns);

#ifndef HAVE_ACCEPT4
int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags);

#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK 00004000
#endif  /* #ifndef SOCK_NONBLOCK */

#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 02000000
#endif /* #ifndef SOCK_CLOEXEC */

#endif /* #ifndef HAVE_ACCEPT4 */


// ----------------------------------------------------------------------------
// poll() based listener

#define POLLINFO_FLAG_SERVER_SOCKET 0x00000001
#define POLLINFO_FLAG_CLIENT_SOCKET 0x00000002
#define POLLINFO_FLAG_DONT_CLOSE    0x00000004

typedef struct poll POLLJOB;

typedef struct pollinfo {
    POLLJOB *p;             // the parent
    size_t slot;            // the slot id

    int fd;                 // the file descriptor
    int socktype;           // the client socket type
    WEB_CLIENT_ACL port_acl; // the access lists permitted on this web server port (it's -1 for client sockets)
    char *client_ip;         // Max INET6_ADDRSTRLEN bytes
    char *client_port;       // Max NI_MAXSERV bytes
    char *client_host;       // Max NI_MAXHOST bytes

    time_t connected_t;     // the time the socket connected
    time_t last_received_t; // the time the socket last received data
    time_t last_sent_t;     // the time the socket last sent data

    size_t recv_count;      // the number of times the socket was ready for inbound traffic
    size_t send_count;      // the number of times the socket was ready for outbound traffic

    uint32_t flags;         // internal flags

    // callbacks for this socket
    void  (*del_callback)(struct pollinfo *pi);
    int   (*rcv_callback)(struct pollinfo *pi, short int *events);
    int   (*snd_callback)(struct pollinfo *pi, short int *events);

    // the user data
    void *data;

    // linking of free pollinfo structures
    // for quickly finding the next available
    // this is like a stack, it grows and shrinks
    // (with gaps - lower empty slots are preferred)
    struct pollinfo *next;
} POLLINFO;

struct poll {
    size_t slots;
    size_t used;
    size_t min;
    size_t max;

    size_t limit;

    time_t complete_request_timeout;
    time_t idle_timeout;
    time_t checks_every;

    time_t timer_milliseconds;
    void *timer_data;

    struct pollfd *fds;
    struct pollinfo *inf;
    struct pollinfo *first_free;

    SIMPLE_PATTERN *access_list;
    int allow_dns;

    void *(*add_callback)(POLLINFO *pi, short int *events, void *data);
    void  (*del_callback)(POLLINFO *pi);
    int   (*rcv_callback)(POLLINFO *pi, short int *events);
    int   (*snd_callback)(POLLINFO *pi, short int *events);
    void  (*tmr_callback)(void *timer_data);
};

#define pollinfo_from_slot(p, slot) (&((p)->inf[(slot)]))

int poll_default_snd_callback(POLLINFO *pi, short int *events);
int poll_default_rcv_callback(POLLINFO *pi, short int *events);
void poll_default_del_callback(POLLINFO *pi);
void *poll_default_add_callback(POLLINFO *pi, short int *events, void *data);

POLLINFO *poll_add_fd(POLLJOB *p
                             , int fd
                             , int socktype
                             , WEB_CLIENT_ACL port_acl
                             , uint32_t flags
                             , const char *client_ip
                             , const char *client_port
                             , const char *client_host
                             , void *(*add_callback)(POLLINFO *pi, short int *events, void *data)
                             , void  (*del_callback)(POLLINFO *pi)
                             , int   (*rcv_callback)(POLLINFO *pi, short int *events)
                             , int   (*snd_callback)(POLLINFO *pi, short int *events)
                             , void *data
);
void poll_close_fd(POLLINFO *pi);

void poll_events(LISTEN_SOCKETS *sockets
        , void *(*add_callback)(POLLINFO *pi, short int *events, void *data)
        , void  (*del_callback)(POLLINFO *pi)
        , int   (*rcv_callback)(POLLINFO *pi, short int *events)
        , int   (*snd_callback)(POLLINFO *pi, short int *events)
        , void  (*tmr_callback)(void *timer_data)
        , bool  (*check_to_stop_callback)(void)
        , SIMPLE_PATTERN *access_list
        , int allow_dns
        , void *data
        , time_t tcp_request_timeout_seconds
        , time_t tcp_idle_timeout_seconds
        , time_t timer_milliseconds
        , void *timer_data
        , size_t max_tcp_sockets
);

#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif

typedef struct socket_peers {
    struct {
        char ip[INET6_ADDRSTRLEN];
        int port;
    } local;

    struct {
        char ip[INET6_ADDRSTRLEN];
        int port;
    } peer;
} SOCKET_PEERS;

SOCKET_PEERS socket_peers(int sock_fd);
bool ip_to_hostname(const char *ip, char *dst, size_t dst_len);

#endif //NETDATA_SOCKET_H