summaryrefslogtreecommitdiff
path: root/other/bootstrap_daemon/src/tox-bootstrapd.c
diff options
context:
space:
mode:
authorMaxim Biro <nurupo.contributions@gmail.com>2015-12-30 23:43:04 -0500
committerMaxim Biro <nurupo.contributions@gmail.com>2015-12-30 23:43:04 -0500
commitbfc3c4eaac4eec6a2e714b7483b646d8ee21efc9 (patch)
tree058ddcea305ed664e6bb015f294bd33cc926ec3c /other/bootstrap_daemon/src/tox-bootstrapd.c
parent78d6e2d58b4e4e18e6a3045e0d8b3b29392d8238 (diff)
Add logger object to be able to support multiple logging backends
Diffstat (limited to 'other/bootstrap_daemon/src/tox-bootstrapd.c')
-rw-r--r--other/bootstrap_daemon/src/tox-bootstrapd.c730
1 files changed, 730 insertions, 0 deletions
diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c
new file mode 100644
index 00000000..71b1386d
--- /dev/null
+++ b/other/bootstrap_daemon/src/tox-bootstrapd.c
@@ -0,0 +1,730 @@
1/* tox-bootstrapd.c
2 *
3 * Tox DHT bootstrap daemon.
4 *
5 * Copyright (C) 2014 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24// system provided
25#include <arpa/inet.h>
26#include <syslog.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <unistd.h>
30
31// C
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36// 3rd party
37#include <libconfig.h>
38
39// ./configure
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44// toxcore
45#include "../../toxcore/LAN_discovery.h"
46#include "../../toxcore/onion_announce.h"
47#include "../../toxcore/TCP_server.h"
48#include "../../toxcore/util.h"
49
50// misc
51#include "../bootstrap_node_packets.c"
52#include "../../testing/misc_tools.c"
53
54
55#define DAEMON_NAME "tox-bootstrapd"
56#define DAEMON_VERSION_NUMBER 2014101200UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day
57
58#define SLEEP_TIME_MILLISECONDS 30
59#define sleep usleep(1000*SLEEP_TIME_MILLISECONDS)
60
61#define DEFAULT_PID_FILE_PATH "tox-bootstrapd.pid"
62#define DEFAULT_KEYS_FILE_PATH "tox-bootstrapd.keys"
63#define DEFAULT_PORT 33445
64#define DEFAULT_ENABLE_IPV6 1 // 1 - true, 0 - false
65#define DEFAULT_ENABLE_IPV4_FALLBACK 1 // 1 - true, 0 - false
66#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false
67#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false
68#define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly
69#define DEFAULT_TCP_RELAY_PORTS_COUNT 3
70#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false
71#define DEFAULT_MOTD DAEMON_NAME
72
73#define MIN_ALLOWED_PORT 1
74#define MAX_ALLOWED_PORT 65535
75
76
77// Uses the already existing key or creates one if it didn't exist
78//
79// retirns 1 on success
80// 0 on failure - no keys were read or stored
81
82int manage_keys(DHT *dht, char *keys_file_path)
83{
84 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
85 uint8_t keys[KEYS_SIZE];
86 FILE *keys_file;
87
88 // Check if file exits, proceed to open and load keys
89 keys_file = fopen(keys_file_path, "r");
90
91 if (keys_file != NULL) {
92 const size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
93
94 if (read_size != KEYS_SIZE) {
95 fclose(keys_file);
96 return 0;
97 }
98
99 memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES);
100 memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES);
101 } else {
102 // Otherwise save new keys
103 memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
104 memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES);
105
106 keys_file = fopen(keys_file_path, "w");
107
108 if (!keys_file)
109 return 0;
110
111 const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
112
113 if (write_size != KEYS_SIZE) {
114 fclose(keys_file);
115 return 0;
116 }
117 }
118
119 fclose(keys_file);
120
121 return 1;
122}
123
124// Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array
125//
126// Supposed to be called from get_general_config only
127//
128// Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports`
129
130void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count)
131{
132 const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports";
133
134 *tcp_relay_port_count = 0;
135
136 config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS);
137
138 if (ports_array == NULL) {
139 syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS);
140 syslog(LOG_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS);
141
142 uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS};
143
144 int i;
145
146 for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) {
147 syslog(LOG_INFO, "Port #%d: %u\n", i, default_ports[i]);
148 }
149
150 // similar procedure to the one of reading config file below
151 *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t));
152
153 for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) {
154
155 (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i];
156
157 if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT
158 || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) {
159 syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i,
160 (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
161 continue;
162 }
163
164 (*tcp_relay_port_count) ++;
165 }
166
167 // the loop above skips invalid ports, so we adjust the allocated memory size
168 if ((*tcp_relay_port_count) > 0) {
169 *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
170 } else {
171 free(*tcp_relay_ports);
172 *tcp_relay_ports = NULL;
173 }
174
175 return;
176 }
177
178 if (config_setting_is_array(ports_array) == CONFIG_FALSE) {
179 syslog(LOG_ERR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n",
180 NAME_TCP_RELAY_PORTS);
181 return;
182 }
183
184 int config_port_count = config_setting_length(ports_array);
185
186 if (config_port_count == 0) {
187 syslog(LOG_ERR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS);
188 return;
189 }
190
191 *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t));
192
193 int i;
194
195 for (i = 0; i < config_port_count; i ++) {
196 config_setting_t *elem = config_setting_get_elem(ports_array, i);
197
198 if (elem == NULL) {
199 // it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be
200 syslog(LOG_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i);
201 break;
202 }
203
204 if (config_setting_is_number(elem) == CONFIG_FALSE) {
205 syslog(LOG_WARNING, "Port #%d: Not a number. Skipping.\n", i);
206 continue;
207 }
208
209 (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem);
210
211 if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT
212 || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) {
213 syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i,
214 (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
215 continue;
216 }
217
218 (*tcp_relay_port_count) ++;
219 }
220
221 // the loop above skips invalid ports, so we adjust the allocated memory size
222 if ((*tcp_relay_port_count) > 0) {
223 *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
224 } else {
225 free(*tcp_relay_ports);
226 *tcp_relay_ports = NULL;
227 }
228}
229
230// Gets general config options
231//
232// Important: you are responsible for freeing `pid_file_path` and `keys_file_path`
233// also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports`
234// and also `motd` iff `enable_motd` is set
235//
236// returns 1 on success
237// 0 on failure, doesn't modify any data pointed by arguments
238
239int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port,
240 int *enable_ipv6,
241 int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports,
242 int *tcp_relay_port_count, int *enable_motd, char **motd)
243{
244 config_t cfg;
245
246 const char *NAME_PORT = "port";
247 const char *NAME_PID_FILE_PATH = "pid_file_path";
248 const char *NAME_KEYS_FILE_PATH = "keys_file_path";
249 const char *NAME_ENABLE_IPV6 = "enable_ipv6";
250 const char *NAME_ENABLE_IPV4_FALLBACK = "enable_ipv4_fallback";
251 const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery";
252 const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay";
253 const char *NAME_ENABLE_MOTD = "enable_motd";
254 const char *NAME_MOTD = "motd";
255
256 config_init(&cfg);
257
258 // Read the file. If there is an error, report it and exit.
259 if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) {
260 syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
261 config_destroy(&cfg);
262 return 0;
263 }
264
265 // Get port
266 if (config_lookup_int(&cfg, NAME_PORT, port) == CONFIG_FALSE) {
267 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT);
268 syslog(LOG_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT);
269 *port = DEFAULT_PORT;
270 }
271
272 // Get PID file location
273 const char *tmp_pid_file;
274
275 if (config_lookup_string(&cfg, NAME_PID_FILE_PATH, &tmp_pid_file) == CONFIG_FALSE) {
276 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH);
277 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH);
278 tmp_pid_file = DEFAULT_PID_FILE_PATH;
279 }
280
281 *pid_file_path = malloc(strlen(tmp_pid_file) + 1);
282 strcpy(*pid_file_path, tmp_pid_file);
283
284 // Get keys file location
285 const char *tmp_keys_file;
286
287 if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) {
288 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH);
289 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH);
290 tmp_keys_file = DEFAULT_KEYS_FILE_PATH;
291 }
292
293 *keys_file_path = malloc(strlen(tmp_keys_file) + 1);
294 strcpy(*keys_file_path, tmp_keys_file);
295
296 // Get IPv6 option
297 if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) {
298 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6);
299 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false");
300 *enable_ipv6 = DEFAULT_ENABLE_IPV6;
301 }
302
303 // Get IPv4 fallback option
304 if (config_lookup_bool(&cfg, NAME_ENABLE_IPV4_FALLBACK, enable_ipv4_fallback) == CONFIG_FALSE) {
305 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK);
306 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK,
307 DEFAULT_ENABLE_IPV4_FALLBACK ? "true" : "false");
308 *enable_ipv4_fallback = DEFAULT_ENABLE_IPV4_FALLBACK;
309 }
310
311 // Get LAN discovery option
312 if (config_lookup_bool(&cfg, NAME_ENABLE_LAN_DISCOVERY, enable_lan_discovery) == CONFIG_FALSE) {
313 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY);
314 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY,
315 DEFAULT_ENABLE_LAN_DISCOVERY ? "true" : "false");
316 *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY;
317 }
318
319 // Get TCP relay option
320 if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) {
321 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY);
322 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY,
323 DEFAULT_ENABLE_TCP_RELAY ? "true" : "false");
324 *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY;
325 }
326
327 if (*enable_tcp_relay) {
328 parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count);
329 } else {
330 *tcp_relay_port_count = 0;
331 }
332
333 // Get MOTD option
334 if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) {
335 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD);
336 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD,
337 DEFAULT_ENABLE_MOTD ? "true" : "false");
338 *enable_motd = DEFAULT_ENABLE_MOTD;
339 }
340
341 if (*enable_motd) {
342 // Get MOTD
343 const char *tmp_motd;
344
345 if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) {
346 syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD);
347 syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD);
348 tmp_motd = DEFAULT_MOTD;
349 }
350
351 size_t tmp_motd_length = strlen(tmp_motd) + 1;
352 size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length;
353 *motd = malloc(motd_length);
354 strncpy(*motd, tmp_motd, motd_length);
355 (*motd)[motd_length - 1] = '\0';
356 }
357
358 config_destroy(&cfg);
359
360 syslog(LOG_INFO, "Successfully read:\n");
361 syslog(LOG_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path);
362 syslog(LOG_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path);
363 syslog(LOG_INFO, "'%s': %d\n", NAME_PORT, *port);
364 syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false");
365 syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false");
366 syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false");
367
368 syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false");
369
370 // show info about tcp ports only if tcp relay is enabled
371 if (*enable_tcp_relay) {
372 if (*tcp_relay_port_count == 0) {
373 syslog(LOG_ERR, "No TCP ports could be read.\n");
374 } else {
375 syslog(LOG_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count);
376 int i;
377
378 for (i = 0; i < *tcp_relay_port_count; i ++) {
379 syslog(LOG_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]);
380 }
381 }
382 }
383
384 syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false");
385
386 if (*enable_motd) {
387 syslog(LOG_INFO, "'%s': %s\n", NAME_MOTD, *motd);
388 }
389
390 return 1;
391}
392
393// Bootstraps nodes listed in the config file
394//
395// returns 1 on success, some or no bootstrap nodes were added
396// 0 on failure, a error accured while parsing config file
397
398int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6)
399{
400 const char *NAME_BOOTSTRAP_NODES = "bootstrap_nodes";
401
402 const char *NAME_PUBLIC_KEY = "public_key";
403 const char *NAME_PORT = "port";
404 const char *NAME_ADDRESS = "address";
405
406 config_t cfg;
407
408 config_init(&cfg);
409
410 if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) {
411 syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
412 config_destroy(&cfg);
413 return 0;
414 }
415
416 config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES);
417
418 if (node_list == NULL) {
419 syslog(LOG_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", NAME_BOOTSTRAP_NODES);
420 config_destroy(&cfg);
421 return 1;
422 }
423
424 if (config_setting_length(node_list) == 0) {
425 syslog(LOG_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n");
426 config_destroy(&cfg);
427 return 1;
428 }
429
430 int bs_port;
431 const char *bs_address;
432 const char *bs_public_key;
433
434 config_setting_t *node;
435
436 int i = 0;
437
438 while (config_setting_length(node_list)) {
439
440 node = config_setting_get_elem(node_list, 0);
441
442 if (node == NULL) {
443 config_destroy(&cfg);
444 return 0;
445 }
446
447 // Check that all settings are present
448 if (config_setting_lookup_string(node, NAME_PUBLIC_KEY, &bs_public_key) == CONFIG_FALSE) {
449 syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PUBLIC_KEY);
450 goto next;
451 }
452
453 if (config_setting_lookup_int(node, NAME_PORT, &bs_port) == CONFIG_FALSE) {
454 syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT);
455 goto next;
456 }
457
458 if (config_setting_lookup_string(node, NAME_ADDRESS, &bs_address) == CONFIG_FALSE) {
459 syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS);
460 goto next;
461 }
462
463 // Process settings
464 if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES * 2) {
465 syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY,
466 bs_public_key);
467 goto next;
468 }
469
470 if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) {
471 syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT,
472 bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
473 goto next;
474 }
475
476 uint8_t *bs_public_key_bin = hex_string_to_bin((char *)bs_public_key);
477 const int address_resolved = DHT_bootstrap_from_address(dht, bs_address, enable_ipv6, htons(bs_port),
478 bs_public_key_bin);
479 free(bs_public_key_bin);
480
481 if (!address_resolved) {
482 syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address);
483 goto next;
484 }
485
486 syslog(LOG_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key);
487
488next:
489 // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly
490 // though it's freed when the element is removed, so we free it right away in order to keep memory
491 // consumption minimal
492 config_setting_remove_elem(node_list, 0);
493 i++;
494 }
495
496 config_destroy(&cfg);
497
498 return 1;
499}
500
501// Prints public key
502
503void print_public_key(const uint8_t *public_key)
504{
505 char buffer[2 * crypto_box_PUBLICKEYBYTES + 1];
506 int index = 0;
507
508 size_t i;
509
510 for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) {
511 index += sprintf(buffer + index, "%02hhX", public_key[i]);
512 }
513
514 syslog(LOG_INFO, "Public Key: %s\n", buffer);
515
516 return;
517}
518
519int main(int argc, char *argv[])
520{
521 openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON);
522
523 syslog(LOG_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER);
524
525 if (argc < 2) {
526 syslog(LOG_ERR, "Please specify a path to a configuration file as the first argument. Exiting.\n");
527 return 1;
528 }
529
530 const char *cfg_file_path = argv[1];
531 char *pid_file_path, *keys_file_path;
532 int port;
533 int enable_ipv6;
534 int enable_ipv4_fallback;
535 int enable_lan_discovery;
536 int enable_tcp_relay;
537 uint16_t *tcp_relay_ports;
538 int tcp_relay_port_count;
539 int enable_motd;
540 char *motd;
541
542 if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_ipv4_fallback,
543 &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) {
544 syslog(LOG_INFO, "General config read successfully\n");
545 } else {
546 syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path);
547 return 1;
548 }
549
550 if (port < MIN_ALLOWED_PORT || port > MAX_ALLOWED_PORT) {
551 syslog(LOG_ERR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
552 return 1;
553 }
554
555 // Check if the PID file exists
556 FILE *pid_file;
557
558 if ((pid_file = fopen(pid_file_path, "r"))) {
559 syslog(LOG_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path);
560 fclose(pid_file);
561 }
562
563 IP ip;
564 ip_init(&ip, enable_ipv6);
565
566 Networking_Core *net = new_networking(ip, port);
567
568 if (net == NULL) {
569 if (enable_ipv6 && enable_ipv4_fallback) {
570 syslog(LOG_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n");
571 enable_ipv6 = 0;
572 ip_init(&ip, enable_ipv6);
573 net = new_networking(ip, port);
574
575 if (net == NULL) {
576 syslog(LOG_ERR, "Couldn't fallback to IPv4. Exiting.\n");
577 return 1;
578 }
579 } else {
580 syslog(LOG_ERR, "Couldn't initialize networking. Exiting.\n");
581 return 1;
582 }
583 }
584
585
586 DHT *dht = new_DHT(net);
587
588 if (dht == NULL) {
589 syslog(LOG_ERR, "Couldn't initialize Tox DHT instance. Exiting.\n");
590 return 1;
591 }
592
593 Onion *onion = new_onion(dht);
594 Onion_Announce *onion_a = new_onion_announce(dht);
595
596 if (!(onion && onion_a)) {
597 syslog(LOG_ERR, "Couldn't initialize Tox Onion. Exiting.\n");
598 return 1;
599 }
600
601 if (enable_motd) {
602 if (bootstrap_set_callbacks(dht->net, DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) {
603 syslog(LOG_INFO, "Set MOTD successfully.\n");
604 } else {
605 syslog(LOG_ERR, "Couldn't set MOTD: %s. Exiting.\n", motd);
606 return 1;
607 }
608
609 free(motd);
610 }
611
612 if (manage_keys(dht, keys_file_path)) {
613 syslog(LOG_INFO, "Keys are managed successfully.\n");
614 } else {
615 syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path);
616 return 1;
617 }
618
619 TCP_Server *tcp_server = NULL;
620
621 if (enable_tcp_relay) {
622 if (tcp_relay_port_count == 0) {
623 syslog(LOG_ERR, "No TCP relay ports read. Exiting.\n");
624 return 1;
625 }
626
627 tcp_server = new_TCP_server(enable_ipv6, tcp_relay_port_count, tcp_relay_ports, dht->self_secret_key, onion);
628
629 // tcp_relay_port_count != 0 at this point
630 free(tcp_relay_ports);
631
632 if (tcp_server != NULL) {
633 syslog(LOG_INFO, "Initialized Tox TCP server successfully.\n");
634 } else {
635 syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n");
636 return 1;
637 }
638 }
639
640 if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) {
641 syslog(LOG_INFO, "List of bootstrap nodes read successfully.\n");
642 } else {
643 syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path);
644 return 1;
645 }
646
647 print_public_key(dht->self_public_key);
648
649 // Write the PID file
650 FILE *pidf = fopen(pid_file_path, "a+");
651
652 if (pidf == NULL) {
653 syslog(LOG_ERR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path);
654 return 1;
655 }
656
657 free(pid_file_path);
658 free(keys_file_path);
659
660 // Fork off from the parent process
661 const pid_t pid = fork();
662
663 if (pid > 0) {
664 fprintf(pidf, "%d", pid);
665 fclose(pidf);
666 syslog(LOG_INFO, "Forked successfully: PID: %d.\n", pid);
667 return 0;
668 } else {
669 fclose(pidf);
670 }
671
672 if (pid < 0) {
673 syslog(LOG_ERR, "Forking failed. Exiting.\n");
674 return 1;
675 }
676
677 // Change the file mode mask
678 umask(0);
679
680 // Create a new SID for the child process
681 if (setsid() < 0) {
682 syslog(LOG_ERR, "SID creation failure. Exiting.\n");
683 return 1;
684 }
685
686 // Change the current working directory
687 if ((chdir("/")) < 0) {
688 syslog(LOG_ERR, "Couldn't change working directory to '/'. Exiting.\n");
689 return 1;
690 }
691
692 // Go quiet
693 close(STDOUT_FILENO);
694 close(STDIN_FILENO);
695 close(STDERR_FILENO);
696
697 uint64_t last_LANdiscovery = 0;
698 const uint16_t htons_port = htons(port);
699
700 int waiting_for_dht_connection = 1;
701
702 if (enable_lan_discovery) {
703 LANdiscovery_init(dht);
704 syslog(LOG_INFO, "Initialized LAN discovery.\n");
705 }
706
707 while (1) {
708 do_DHT(dht);
709
710 if (enable_lan_discovery && is_timeout(last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) {
711 send_LANdiscovery(htons_port, dht);
712 last_LANdiscovery = unix_time();
713 }
714
715 if (enable_tcp_relay) {
716 do_TCP_server(tcp_server);
717 }
718
719 networking_poll(dht->net);
720
721 if (waiting_for_dht_connection && DHT_isconnected(dht)) {
722 syslog(LOG_INFO, "Connected to other bootstrap node successfully.\n");
723 waiting_for_dht_connection = 0;
724 }
725
726 sleep;
727 }
728
729 return 1;
730}