mirror of
https://github.com/ChronosX88/netsukuku.git
synced 2024-11-26 04:02:19 +00:00
914 lines
24 KiB
C
914 lines
24 KiB
C
/* This file is part of Netsukuku
|
|
* (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
|
|
*
|
|
* This source code is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as published
|
|
* by the Free Software Foundation; either version 2 of the License,
|
|
* or (at your option) any later version.
|
|
*
|
|
* This source code is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* Please refer to the GNU Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Public License along with
|
|
* this source code; if not, write to:
|
|
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* --
|
|
* netsukuku.c:
|
|
* Where main() resides.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
#include "common.h"
|
|
#include "conf.h"
|
|
#include "libnetlink.h"
|
|
#include "ll_map.h"
|
|
#include "request.h"
|
|
#include "pkts.h"
|
|
#include "if.h"
|
|
#include "bmap.h"
|
|
#include "netsukuku.h"
|
|
#include "qspn.h"
|
|
#include "accept.h"
|
|
#include "daemon.h"
|
|
#include "crypto.h"
|
|
#include "andna_cache.h"
|
|
#include "andna.h"
|
|
#include "radar.h"
|
|
#include "hook.h"
|
|
#include "rehook.h"
|
|
#include "ntk-console-server.h"
|
|
#include <pthread.h>
|
|
|
|
|
|
extern int errno;
|
|
extern char *optarg;
|
|
extern int optind, opterr, optopt;
|
|
|
|
int destroy_netsukuku_mutex;
|
|
int pid_saved;
|
|
|
|
int options_parsed = 0; /* How many times parse_options() has been called */
|
|
|
|
void
|
|
save_pid(void)
|
|
{
|
|
FILE *fd;
|
|
|
|
if (!(fd = fopen(server_opt.pid_file, "w")))
|
|
error("Couldn't create pid file \"%s\": %s",
|
|
server_opt.pid_file, strerror(errno));
|
|
fprintf(fd, "ntkd %ld\n", (long) getpid());
|
|
|
|
fclose(fd);
|
|
pid_saved = 1;
|
|
}
|
|
|
|
/*
|
|
* is_ntkd_already_running
|
|
*
|
|
* Returns 1 if there's already a ntkd running
|
|
*/
|
|
int
|
|
is_ntkd_already_running(void)
|
|
{
|
|
pid_t oldpid;
|
|
FILE *fd;
|
|
|
|
if (!(fd = fopen(server_opt.pid_file, "r"))) {
|
|
if (errno != ENOENT)
|
|
error("Cannot read pid file \"%s\": %s",
|
|
server_opt.pid_file, strerror(errno));
|
|
return 0;
|
|
}
|
|
|
|
fscanf(fd, "ntkd %d\n", &oldpid);
|
|
if (ferror(fd)) {
|
|
error("error reading pid file \"%s\": %s\n",
|
|
server_opt.pid_file, strerror(errno));
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
fclose(fd);
|
|
|
|
return !kill(oldpid, 0);
|
|
}
|
|
|
|
int
|
|
ntk_load_maps(void)
|
|
{
|
|
if (file_exist(server_opt.int_map_file) &&
|
|
(me.int_map = load_map(server_opt.int_map_file, &me.cur_node)))
|
|
debug(DBG_NORMAL, "Internal map loaded");
|
|
else
|
|
me.int_map = init_map(0);
|
|
|
|
#if 0
|
|
/* Don't load the bnode map, it's useless */
|
|
if ((me.bnode_map = load_bmap(server_opt.bnode_map_file, me.ext_map,
|
|
FAMILY_LVLS, &me.bmap_nodes))) {
|
|
debug(DBG_NORMAL, "Bnode map loaded");
|
|
} else
|
|
#endif
|
|
bmap_levels_init(BMAP_LEVELS(FAMILY_LVLS), &me.bnode_map,
|
|
&me.bmap_nodes);
|
|
bmap_counter_init(BMAP_LEVELS(FAMILY_LVLS), &me.bmap_nodes_closed,
|
|
&me.bmap_nodes_opened);
|
|
|
|
if (file_exist(server_opt.ext_map_file) &&
|
|
(me.ext_map = load_extmap(server_opt.ext_map_file, &me.cur_quadg)))
|
|
debug(DBG_NORMAL, "External map loaded");
|
|
else
|
|
me.ext_map = init_extmap(FAMILY_LVLS, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ntk_save_maps(void)
|
|
{
|
|
debug(DBG_NORMAL, "Saving the internal map");
|
|
save_map(me.int_map, me.cur_node, server_opt.int_map_file);
|
|
|
|
#ifdef DEBUG
|
|
debug(DBG_NORMAL, "Saving the border nodes map");
|
|
save_bmap(me.bnode_map, me.bmap_nodes, me.ext_map, me.cur_quadg,
|
|
server_opt.bnode_map_file);
|
|
#endif
|
|
|
|
debug(DBG_NORMAL, "Saving the external map");
|
|
save_extmap(me.ext_map, MAXGROUPNODE, &me.cur_quadg,
|
|
server_opt.ext_map_file);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ntk_free_maps(void)
|
|
{
|
|
bmap_levels_free(me.bnode_map, me.bmap_nodes);
|
|
bmap_counter_free(me.bmap_nodes_closed, me.bmap_nodes_opened);
|
|
free_extmap(me.ext_map, FAMILY_LVLS, 0);
|
|
free_map(me.int_map, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
printf("Usage:\n"
|
|
" ntkd [-hvaldrRD46] [-i net_interface] [-c conf_file] [-l logfile]\n\n"
|
|
" -4 ipv4\n"
|
|
" -6 ipv6\n"
|
|
" -i Specify the interface after this\n\n"
|
|
" -a Prevents running the ANDNA daemon\n"
|
|
" -R Prevents editting /etc/resolv.conf\n"
|
|
" -D Prevents running as daemon (Does not fork to the background)\n"
|
|
"\n"
|
|
" -r Runs in restricted mode\n"
|
|
" -I Share your internet connection with other nodes\n"
|
|
"\n"
|
|
" -c configuration file\n"
|
|
" -l Enables logging to file\n"
|
|
"\n"
|
|
" -d Debug (Add more ds to get more info)\n"
|
|
" -h Shows this help\n"
|
|
" -v Shows the version you are using\n"
|
|
" -k Kills the running instance of ntkd\n"
|
|
" -C Runs the console server for Ntk-Console to connect to\n"
|
|
" -e Excludes an interface from usage I.E all interfaces except this one\n"
|
|
" -n Experimental, Currently meaningless argument\n to implement ntk netsplit\n http://netsukuku.freaknet.org/docs/main_doc/ntk_rfc/Ntk_net_split\n");
|
|
}
|
|
|
|
/*
|
|
* fill_default_options: fills the default values in the server_opt struct
|
|
*/
|
|
void
|
|
fill_default_options(void)
|
|
{
|
|
setzero(&server_opt, sizeof(server_opt));
|
|
|
|
server_opt.family = AF_INET;
|
|
|
|
server_opt.config_file = NTK_CONFIG_FILE;
|
|
server_opt.pid_file = NTK_PID_FILE;
|
|
|
|
server_opt.int_map_file = INT_MAP_FILE;
|
|
server_opt.ext_map_file = EXT_MAP_FILE;
|
|
server_opt.bnode_map_file = BNODE_MAP_FILE;
|
|
|
|
server_opt.andna_hnames_file = ANDNA_HNAMES_FILE;
|
|
server_opt.snsd_nodes_file = SNSD_NODES_FILE;
|
|
server_opt.andna_cache_file = ANDNA_CACHE_FILE;
|
|
server_opt.lclkey_file = LCLKEY_FILE;
|
|
server_opt.lcl_file = LCL_FILE;
|
|
server_opt.rhc_file = RHC_FILE;
|
|
server_opt.counter_c_file = COUNTER_C_FILE;
|
|
|
|
server_opt.daemon = 1;
|
|
server_opt.dbg_lvl = 0;
|
|
|
|
server_opt.disable_andna = 0;
|
|
server_opt.disable_resolvconf = 0;
|
|
server_opt.restricted = 0;
|
|
server_opt.restricted_class = 0;
|
|
|
|
server_opt.use_shared_inet = 1;
|
|
|
|
server_opt.ip_masq_script = IPMASQ_SCRIPT_FILE;
|
|
server_opt.tc_shaper_script = TCSHAPER_SCRIPT_FILE;
|
|
|
|
server_opt.max_connections = MAX_CONNECTIONS;
|
|
server_opt.max_accepts_per_host = MAX_ACCEPTS;
|
|
server_opt.max_accepts_per_host_time = FREE_ACCEPT_TIME;
|
|
}
|
|
|
|
/*
|
|
* fill_loaded_cfg_options
|
|
*
|
|
* stores in server_opt the options loaded from the configuration file
|
|
*/
|
|
void
|
|
fill_loaded_cfg_options(void)
|
|
{
|
|
char *value;
|
|
|
|
CONF_GET_STRN_VALUE(CONF_NTK_INT_MAP_FILE, &server_opt.int_map_file,
|
|
NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_NTK_BNODE_MAP_FILE,
|
|
&server_opt.bnode_map_file, NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_NTK_EXT_MAP_FILE, &server_opt.ext_map_file,
|
|
NAME_MAX - 1);
|
|
|
|
CONF_GET_STRN_VALUE(CONF_ANDNA_HNAMES_FILE,
|
|
&server_opt.andna_hnames_file, NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_SNSD_NODES_FILE, &server_opt.snsd_nodes_file,
|
|
NAME_MAX - 1);
|
|
|
|
CONF_GET_STRN_VALUE(CONF_ANDNA_CACHE_FILE,
|
|
&server_opt.andna_cache_file, NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_ANDNA_LCLKEY_FILE, &server_opt.lclkey_file,
|
|
NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_ANDNA_LCL_FILE, &server_opt.lcl_file,
|
|
NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_ANDNA_RHC_FILE, &server_opt.rhc_file,
|
|
NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_ANDNA_COUNTER_C_FILE,
|
|
&server_opt.counter_c_file, NAME_MAX - 1);
|
|
|
|
CONF_GET_STRN_VALUE(CONF_NTK_PID_FILE, &server_opt.pid_file,
|
|
NAME_MAX - 1);
|
|
CONF_GET_INT_VALUE(CONF_NTK_MAX_CONNECTIONS,
|
|
server_opt.max_connections);
|
|
CONF_GET_INT_VALUE(CONF_NTK_MAX_ACCEPTS_PER_HOST,
|
|
server_opt.max_accepts_per_host);
|
|
CONF_GET_INT_VALUE(CONF_NTK_MAX_ACCEPTS_PER_HOST_TIME,
|
|
server_opt.max_accepts_per_host_time);
|
|
|
|
CONF_GET_INT_VALUE(CONF_DISABLE_ANDNA, server_opt.disable_andna);
|
|
CONF_GET_INT_VALUE(CONF_DISABLE_RESOLVCONF,
|
|
server_opt.disable_resolvconf);
|
|
CONF_GET_INT_VALUE(CONF_NTK_RESTRICTED_MODE, server_opt.restricted);
|
|
CONF_GET_INT_VALUE(CONF_NTK_RESTRICTED_CLASS,
|
|
server_opt.restricted_class);
|
|
|
|
CONF_GET_INT_VALUE(CONF_NTK_INTERNET_CONNECTION,
|
|
server_opt.inet_connection);
|
|
if ((value = CONF_GET_VALUE(CONF_NTK_INTERNET_GW))) {
|
|
if (str_to_inet_gw(value, &server_opt.inet_gw,
|
|
&server_opt.inet_gw_dev))
|
|
fatal
|
|
("Malformed `%s' option: \"%s\". Its syntax is \"IP:dev\"",
|
|
config_str[CONF_NTK_INTERNET_GW], value);
|
|
}
|
|
CONF_GET_INT_VALUE(CONF_NTK_INTERNET_UPLOAD, server_opt.my_upload_bw);
|
|
CONF_GET_INT_VALUE(CONF_NTK_INTERNET_DOWNLOAD,
|
|
server_opt.my_dnload_bw);
|
|
if (server_opt.my_upload_bw && server_opt.my_dnload_bw)
|
|
me.my_bandwidth =
|
|
bandwidth_in_8bit((server_opt.my_upload_bw +
|
|
server_opt.my_dnload_bw) / 2);
|
|
|
|
if ((value = CONF_GET_VALUE(CONF_NTK_INTERNET_PING_HOSTS))) {
|
|
server_opt.inet_hosts = parse_internet_hosts(value,
|
|
&server_opt.
|
|
inet_hosts_counter);
|
|
if (!server_opt.inet_hosts)
|
|
fatal("Malformed `%s' option: \"%s\". "
|
|
"Its syntax is host1:host2:...",
|
|
config_str[CONF_NTK_INTERNET_PING_HOSTS], value);
|
|
}
|
|
CONF_GET_INT_VALUE(CONF_SHARE_INTERNET, server_opt.share_internet);
|
|
CONF_GET_INT_VALUE(CONF_SHAPE_INTERNET, server_opt.shape_internet);
|
|
CONF_GET_INT_VALUE(CONF_USE_SHARED_INET, server_opt.use_shared_inet);
|
|
CONF_GET_STRN_VALUE(CONF_NTK_IP_MASQ_SCRIPT,
|
|
&server_opt.ip_masq_script, NAME_MAX - 1);
|
|
CONF_GET_STRN_VALUE(CONF_NTK_TC_SHAPER_SCRIPT,
|
|
&server_opt.tc_shaper_script, NAME_MAX - 1);
|
|
|
|
/* Clean the enviroment */
|
|
clear_config_env();
|
|
}
|
|
|
|
void
|
|
free_server_opt(void)
|
|
{
|
|
int i;
|
|
|
|
if (server_opt.config_file != NTK_CONFIG_FILE)
|
|
xfree(server_opt.config_file);
|
|
if (server_opt.pid_file != NTK_PID_FILE)
|
|
xfree(server_opt.pid_file);
|
|
|
|
if (server_opt.int_map_file != INT_MAP_FILE)
|
|
xfree(server_opt.int_map_file);
|
|
if (server_opt.ext_map_file != EXT_MAP_FILE)
|
|
xfree(server_opt.ext_map_file);
|
|
if (server_opt.bnode_map_file != BNODE_MAP_FILE)
|
|
xfree(server_opt.bnode_map_file);
|
|
|
|
if (server_opt.andna_hnames_file != ANDNA_HNAMES_FILE)
|
|
xfree(server_opt.andna_hnames_file);
|
|
if (server_opt.snsd_nodes_file != SNSD_NODES_FILE)
|
|
xfree(server_opt.snsd_nodes_file);
|
|
if (server_opt.andna_cache_file != ANDNA_CACHE_FILE)
|
|
xfree(server_opt.andna_cache_file);
|
|
if (server_opt.lclkey_file != LCLKEY_FILE)
|
|
xfree(server_opt.lclkey_file);
|
|
if (server_opt.lcl_file != LCL_FILE)
|
|
xfree(server_opt.lcl_file);
|
|
if (server_opt.rhc_file != RHC_FILE)
|
|
xfree(server_opt.rhc_file);
|
|
if (server_opt.counter_c_file != COUNTER_C_FILE)
|
|
xfree(server_opt.counter_c_file);
|
|
|
|
if (server_opt.ip_masq_script != IPMASQ_SCRIPT_FILE)
|
|
xfree(server_opt.ip_masq_script);
|
|
if (server_opt.tc_shaper_script != TCSHAPER_SCRIPT_FILE)
|
|
xfree(server_opt.tc_shaper_script);
|
|
|
|
if (server_opt.inet_gw_dev)
|
|
xfree(server_opt.inet_gw_dev);
|
|
|
|
for (i = 0; i < MAX_INTERFACES && server_opt.ifs[i]; i++)
|
|
xfree(server_opt.ifs[i]);
|
|
}
|
|
|
|
/* Removes specified existing interface, Ntkd should populate the device list
|
|
* prior to this.
|
|
* returns 0 on success, And closes ntkd on error.
|
|
*/
|
|
|
|
int
|
|
exclude_interface(void)
|
|
{
|
|
int i;
|
|
|
|
printf("Number of Interfaces in Use: %d\n", me.cur_ifs_n);
|
|
|
|
for (i = 0; i < me.cur_ifs_n; i++)
|
|
printf("Interface names in Use: %s", me.cur_ifs[i].dev_name);
|
|
|
|
for (i = 0; i < me.cur_ifs_n; i++) {
|
|
if (strcmp(me.cur_ifs[i].dev_name, optarg) == 0) {
|
|
printf("Interface %s removed, And replaced with %s",
|
|
me.cur_ifs[i].dev_name, me.cur_ifs[me.cur_ifs_n].dev_name);
|
|
ifs_del(me.cur_ifs, &me.cur_ifs_n, i);
|
|
return 0;
|
|
}
|
|
else
|
|
fatal("Interface %s not found!", optarg);
|
|
}
|
|
}
|
|
|
|
void
|
|
ntk_thread_creatation(void)
|
|
{
|
|
int x;
|
|
pthread_t console_recv_send_thread;
|
|
if (pthread_create
|
|
(&console_recv_send_thread, NULL, &console_recv_send, &x)) {
|
|
fprintf(stderr, "Error creating thread\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
void
|
|
parse_options(int argc, char **argv)
|
|
{
|
|
int c, saved_argc = argc;
|
|
optind = 0;
|
|
|
|
while (1) {
|
|
int option_index = 0;
|
|
static struct option long_options[] = {
|
|
{"help", 0, 0, 'h'},
|
|
{"iface", 1, 0, 'i'},
|
|
{"ipv6", 0, 0, '6'},
|
|
{"ipv4", 0, 0, '4'},
|
|
|
|
{"conf", 1, 0, 'c'},
|
|
{"logfile", 1, 0, 'l'},
|
|
|
|
{"no_andna", 0, 0, 'a'},
|
|
{"no_daemon", 0, 0, 'D'},
|
|
{"no_resolv", 0, 0, 'R'},
|
|
|
|
{"restricted", 0, 0, 'r'},
|
|
{"share-inet", 0, 0, 'I'},
|
|
|
|
{"debug", 0, 0, 'd'},
|
|
{"version", 0, 0, 'v'},
|
|
{"kill", 0, 0, 'k'},
|
|
{"exclude", 1, 0, 'e'},
|
|
{"console", 0, 0, 'C'},
|
|
{"netsplit", 1, 0, 'n'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
c = getopt_long(argc, argv, "i:c:l:e:hvd64DRrIakC", long_options,
|
|
&option_index);
|
|
if (c == -1)
|
|
break;
|
|
|
|
switch (c) {
|
|
case 'n':
|
|
|
|
break;
|
|
case 'C':
|
|
ntk_thread_creatation();
|
|
break;
|
|
|
|
case 'v':
|
|
printf("%s\n", VERSION_STR);
|
|
exit(0);
|
|
break;
|
|
case 'e':
|
|
exclude_interface();
|
|
break;
|
|
case 'k':
|
|
if (is_ntkd_already_running() == 1) {
|
|
char process_name[256] = { 0 };
|
|
pid_t pid;
|
|
printf("...Closing ntkd...\n");
|
|
FILE *fd = fopen(server_opt.pid_file, "r");
|
|
while (fscanf(fd, "%s %d", process_name, &pid) != EOF) {
|
|
if (strcmp(process_name, "ntkd") == 0) {
|
|
kill(pid, SIGINT);
|
|
}
|
|
}
|
|
fclose(fd);
|
|
exit(0);
|
|
} else if (is_ntkd_already_running() == 0) {
|
|
printf("ntkd is not running\n ...Exiting...\n");
|
|
exit(0);
|
|
}
|
|
break;
|
|
case 'h':
|
|
usage();
|
|
exit(0);
|
|
break;
|
|
case '4':
|
|
server_opt.family = AF_INET;
|
|
break;
|
|
case '6':
|
|
#ifdef IPV6_DISABLED
|
|
fatal("The ipv6 is still not supported");
|
|
#endif
|
|
loginfo
|
|
("WARNING: The ipv6 support is still experimental and under "
|
|
"development, nothing is assured to work.");
|
|
server_opt.family = AF_INET6;
|
|
break;
|
|
case 'c':
|
|
server_opt.config_file = xstrndup(optarg, NAME_MAX - 1);
|
|
break;
|
|
case 'l':
|
|
if (log_to_file(optarg) < 0)
|
|
fatal(0);
|
|
break;
|
|
case 'i':
|
|
break;
|
|
case 'D':
|
|
server_opt.daemon = 0;
|
|
break;
|
|
case 'a':
|
|
server_opt.disable_andna = 1;
|
|
break;
|
|
case 'R':
|
|
server_opt.disable_resolvconf = 1;
|
|
break;
|
|
case 'r':
|
|
server_opt.restricted = 1;
|
|
|
|
/***
|
|
* This is a very dirty hack, but it handles
|
|
* the optional argument better than getopt.
|
|
*
|
|
* This is the problem:
|
|
* ntkd -abcrdefg
|
|
* If 'r' is an element that specifies an
|
|
* optional argument, then the "defg" string
|
|
* is taken as its arg, but this is not what
|
|
* we want because in this case '-r' is
|
|
* specified without its argument.
|
|
*
|
|
* So, what we do is checking if the argv
|
|
* next to the arg of 'r' begins with a '-'
|
|
* or not. If not, it is the option of '-r'
|
|
*
|
|
* The only thing that won't work is:
|
|
* ntkd -rOPTION
|
|
* it has to be specified in this way:
|
|
* ntkd -r OPTION
|
|
*/
|
|
if (argc > optind && argv[optind][0] != '-') {
|
|
server_opt.restricted_class = atoi(argv[optind]);
|
|
saved_argc--;
|
|
}
|
|
/**/ break;
|
|
case 'I':
|
|
server_opt.share_internet = 1;
|
|
if (!server_opt.restricted) {
|
|
loginfo("Share_internet=1. Assuming restricted=1");
|
|
server_opt.restricted = 1;
|
|
}
|
|
if (!server_opt.inet_connection) {
|
|
loginfo("Share_internet=1. Assuming inet_connection=1");
|
|
server_opt.inet_connection = 1;
|
|
}
|
|
break;
|
|
case 'd':
|
|
server_opt.dbg_lvl++;
|
|
break;
|
|
default:
|
|
usage();
|
|
exit(1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (optind < saved_argc && !options_parsed) {
|
|
usage();
|
|
exit(1);
|
|
}
|
|
|
|
options_parsed++;
|
|
}
|
|
|
|
void
|
|
check_conflicting_options(void)
|
|
{
|
|
#define FATAL_NOT_SPECIFIED(str) fatal("You didn't specified the `%s' " \
|
|
"option in netsukuku.conf", \
|
|
(str)); \
|
|
|
|
if (!server_opt.pid_file)
|
|
FATAL_NOT_SPECIFIED("pid_file");
|
|
|
|
if (!server_opt.inet_hosts && server_opt.restricted)
|
|
FATAL_NOT_SPECIFIED("internet_ping_hosts");
|
|
|
|
|
|
if (server_opt.restricted && server_opt.share_internet &&
|
|
!file_exist(server_opt.ip_masq_script))
|
|
fatal("ip_masquerade_script \"%s\" is inexistent",
|
|
server_opt.ip_masq_script);
|
|
|
|
if (server_opt.shape_internet &&
|
|
!file_exist(server_opt.tc_shaper_script))
|
|
fatal("tc_shaper_script \"%s\" is inexistent",
|
|
server_opt.ip_masq_script);
|
|
|
|
if (!server_opt.restricted && server_opt.inet_connection)
|
|
fatal("inet_connection=1 but ntk_restricted_mode=0. If you "
|
|
"want to be compatible with the Internet, "
|
|
"set the restricted mode in the options");
|
|
|
|
if (!server_opt.restricted && (server_opt.share_internet))
|
|
fatal("You want to share your Internet connection,"
|
|
"but I am not running in restricted mode (-r), "
|
|
"'cause I'm not sure of what you want... " "I'm aborting.");
|
|
|
|
if (server_opt.share_internet && me.my_bandwidth < MIN_CONN_BANDWIDTH)
|
|
fatal("You want to share your Internet connection but "
|
|
"your bandwidth is just TOO small. Do not share "
|
|
"it, or your connection will be saturated");
|
|
|
|
if (!server_opt.inet_connection && server_opt.share_internet) {
|
|
loginfo("You want to share your Internet connection,"
|
|
"but `internet_connection' is set to 0."
|
|
"We are assuming it is 1");
|
|
server_opt.inet_connection = 1;
|
|
}
|
|
|
|
if (server_opt.shape_internet && !server_opt.inet_connection)
|
|
fatal("The Internet traffic shaping option is set, but "
|
|
"the `internet_connection' is set to 0, please check "
|
|
"your options.");
|
|
|
|
#ifdef IPV6_DISABLED
|
|
if (server_opt.inet_gw.family == AF_INET6)
|
|
fatal("Ipv6 is not supported");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
init_netsukuku(char **argv)
|
|
{
|
|
xsrand();
|
|
|
|
if (geteuid())
|
|
fatal("Need root privileges");
|
|
|
|
destroy_netsukuku_mutex = pid_saved = 0;
|
|
sigterm_timestamp = sighup_timestamp = sigalrm_timestamp = 0;
|
|
setzero(&me, sizeof(struct current_globals));
|
|
|
|
if (is_ntkd_already_running())
|
|
fatal("ntkd is already running. If it is not, remove \"%s\"",
|
|
server_opt.pid_file);
|
|
else
|
|
save_pid();
|
|
|
|
my_family = server_opt.family;
|
|
restricted_mode = server_opt.restricted;
|
|
restricted_class =
|
|
server_opt.restricted_class ? RESTRICTED_172 : RESTRICTED_10;
|
|
|
|
/* Check if the DATA_DIR exists, if not create it */
|
|
if (check_and_create_dir(DATA_DIR))
|
|
fatal("Cannot access to the %s directory. Exiting.", DATA_DIR);
|
|
|
|
/*
|
|
* Device initialization
|
|
*/
|
|
if (if_init_all(server_opt.ifs, server_opt.ifs_n,
|
|
me.cur_ifs, &me.cur_ifs_n) < 0)
|
|
fatal("Cannot initialize any network interfaces");
|
|
|
|
/*
|
|
* ANDNA init
|
|
*/
|
|
if (!server_opt.disable_andna)
|
|
andna_init();
|
|
|
|
/*
|
|
* Initialize the Internet gateway stuff
|
|
*/
|
|
if (server_opt.my_upload_bw && server_opt.my_dnload_bw)
|
|
me.my_bandwidth = bandwidth_in_8bit((server_opt.my_upload_bw +
|
|
server_opt.my_dnload_bw) / 2);
|
|
init_internet_gateway_search();
|
|
|
|
pkts_init(me.cur_ifs, me.cur_ifs_n, 0);
|
|
qspn_init(FAMILY_LVLS);
|
|
|
|
me.cur_erc = e_rnode_init(&me.cur_erc_counter);
|
|
|
|
/* Radar init */
|
|
rq_wait_idx_init(rq_wait_idx);
|
|
first_init_radar();
|
|
total_radars = 0;
|
|
|
|
ntk_load_maps();
|
|
|
|
#if 0
|
|
/* TODO: activate and test it !! */
|
|
debug(DBG_NORMAL, "ACPT: Initializing the accept_tbl: \n"
|
|
" max_connections: %d,\n"
|
|
" max_accepts_per_host: %d,\n"
|
|
" max_accept_per_host_time: %d",
|
|
server_opt.max_connections,
|
|
server_opt.max_accepts_per_host,
|
|
server_opt.max_accepts_per_host_time);
|
|
init_accept_tbl(server_opt.max_connections,
|
|
server_opt.max_accepts_per_host,
|
|
server_opt.max_accepts_per_host_time);
|
|
#endif
|
|
|
|
if (restricted_mode)
|
|
loginfo("NetsukukuD is in restricted mode. "
|
|
"Restricted class: %s",
|
|
server_opt.
|
|
restricted_class ? RESTRICTED_172_STR : RESTRICTED_10_STR);
|
|
|
|
hook_init();
|
|
rehook_init();
|
|
|
|
me.uptime = time(0);
|
|
}
|
|
|
|
int
|
|
destroy_netsukuku(void)
|
|
{
|
|
if (destroy_netsukuku_mutex)
|
|
return -1;
|
|
destroy_netsukuku_mutex = 1;
|
|
|
|
unlink(server_opt.pid_file);
|
|
|
|
ntk_save_maps();
|
|
ntk_free_maps();
|
|
if (!server_opt.disable_andna)
|
|
andna_close();
|
|
|
|
close_internet_gateway_search();
|
|
last_close_radar();
|
|
e_rnode_free(&me.cur_erc, &me.cur_erc_counter);
|
|
destroy_accept_tbl();
|
|
if_close_all();
|
|
qspn_free();
|
|
free_server_opt();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
sigterm_handler(int sig)
|
|
{
|
|
time_t cur_t;
|
|
|
|
if (sigterm_timestamp == (cur_t = time(0)))
|
|
return;
|
|
sigterm_timestamp = time(0);
|
|
|
|
if (!destroy_netsukuku())
|
|
fatal("Termination signal caught. Dying, bye, bye");
|
|
}
|
|
|
|
void *
|
|
reload_hostname_thread(void *null)
|
|
{
|
|
/*
|
|
* Reload the file where the hostnames to be registered are and
|
|
* register the new ones
|
|
*/
|
|
loginfo("Reloading the andna hostnames file");
|
|
load_hostnames(server_opt.andna_hnames_file, &andna_lcl, &lcl_counter);
|
|
load_snsd(server_opt.snsd_nodes_file, andna_lcl);
|
|
andna_update_hnames(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
sighup_handler(int sig)
|
|
{
|
|
pthread_t thread;
|
|
pthread_attr_t t_attr;
|
|
|
|
time_t cur_t;
|
|
|
|
if (sighup_timestamp == (cur_t = time(0)))
|
|
return;
|
|
sighup_timestamp = time(0);
|
|
|
|
pthread_attr_init(&t_attr);
|
|
pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
|
|
pthread_create(&thread, &t_attr, reload_hostname_thread, 0);
|
|
}
|
|
|
|
void *
|
|
rh_cache_flush_thread(void *null)
|
|
{
|
|
/*
|
|
* Flush the resolved hostnames cache.
|
|
*/
|
|
loginfo("Flush the resolved hostnames cache");
|
|
rh_cache_flush();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
sigalrm_handler(int sig)
|
|
{
|
|
pthread_t thread;
|
|
pthread_attr_t t_attr;
|
|
|
|
time_t cur_t;
|
|
|
|
if (sigalrm_timestamp == (cur_t = time(0)))
|
|
return;
|
|
sigalrm_timestamp = time(0);
|
|
|
|
pthread_attr_init(&t_attr);
|
|
pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
|
|
pthread_create(&thread, &t_attr, rh_cache_flush_thread, 0);
|
|
}
|
|
|
|
/*
|
|
* The main flow shall never be stopped, and the sand of time will be
|
|
* revealed.
|
|
*/
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
struct udp_daemon_argv ud_argv;
|
|
u_short *port;
|
|
pthread_t daemon_tcp_thread, daemon_udp_thread, andna_thread;
|
|
pthread_t ping_igw_thread;
|
|
pthread_attr_t t_attr;
|
|
|
|
log_init(argv[0], 0, 1);
|
|
|
|
/* Options loading... */
|
|
fill_default_options();
|
|
parse_options(argc, argv);
|
|
|
|
/* reinit the logs using the new `dbg_lvl' value */
|
|
log_init(argv[0], server_opt.dbg_lvl, 1);
|
|
log_to_file(0);
|
|
|
|
/* Load the option from the config file */
|
|
load_config_file(server_opt.config_file);
|
|
fill_loaded_cfg_options();
|
|
|
|
/* If a same option was specified in the config file and in the
|
|
* command line, give priority to the latter */
|
|
parse_options(argc, argv);
|
|
|
|
check_conflicting_options();
|
|
|
|
/* Initialize the whole netsukuku source code */
|
|
init_netsukuku(argv);
|
|
|
|
signal(SIGALRM, sigalrm_handler);
|
|
signal(SIGHUP, sighup_handler);
|
|
signal(SIGINT, sigterm_handler);
|
|
signal(SIGTERM, sigterm_handler);
|
|
signal(SIGQUIT, sigterm_handler);
|
|
|
|
/* Angelic foreground or Daemonic background ? */
|
|
if (server_opt.daemon) {
|
|
loginfo("Forking to background");
|
|
log_init(argv[0], server_opt.dbg_lvl, 0);
|
|
if (daemon(0, 0) == -1)
|
|
error("Impossible to daemonize: %s.", strerror(errno));
|
|
|
|
}
|
|
|
|
pthread_attr_init(&t_attr);
|
|
pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
|
|
setzero(&ud_argv, sizeof(struct udp_daemon_argv));
|
|
port = xmalloc(sizeof(u_short));
|
|
|
|
/*
|
|
* These are the daemons, the main threads that keeps NetsukukuD
|
|
* up & running.
|
|
*/
|
|
debug(DBG_NORMAL, "Activating all daemons");
|
|
|
|
pthread_mutex_init(&udp_daemon_lock, 0);
|
|
pthread_mutex_init(&tcp_daemon_lock, 0);
|
|
|
|
debug(DBG_SOFT, "Evoking the netsukuku udp radar daemon.");
|
|
ud_argv.port = ntk_udp_radar_port;
|
|
pthread_mutex_lock(&udp_daemon_lock);
|
|
pthread_create(&daemon_udp_thread, &t_attr, udp_daemon,
|
|
(void *) &ud_argv);
|
|
pthread_mutex_lock(&udp_daemon_lock);
|
|
pthread_mutex_unlock(&udp_daemon_lock);
|
|
|
|
debug(DBG_SOFT, "Evoking the netsukuku tcp daemon.");
|
|
*port = ntk_tcp_port;
|
|
pthread_mutex_lock(&tcp_daemon_lock);
|
|
pthread_create(&daemon_tcp_thread, &t_attr, tcp_daemon, (void *) port);
|
|
pthread_mutex_lock(&tcp_daemon_lock);
|
|
pthread_mutex_unlock(&tcp_daemon_lock);
|
|
|
|
|
|
/* Now we hook in Netsukuku */
|
|
netsukuku_hook(0, 0);
|
|
|
|
/*
|
|
* If not disabled, start the ANDNA daemon
|
|
*/
|
|
if (!server_opt.disable_andna)
|
|
pthread_create(&andna_thread, &t_attr, andna_main, 0);
|
|
|
|
xfree(port);
|
|
|
|
if (restricted_mode && (server_opt.share_internet ||
|
|
server_opt.use_shared_inet)) {
|
|
debug(DBG_SOFT, "Evoking the Internet Gateway Pinger daemon");
|
|
pthread_create(&ping_igw_thread, &t_attr, igw_monitor_igws_t, 0);
|
|
}
|
|
|
|
/* We use this same process for the radar_daemon. */
|
|
debug(DBG_SOFT, "Evoking radar daemon.");
|
|
radar_daemon(0);
|
|
|
|
/* Not reached, hahaha */
|
|
loginfo("Cya m8");
|
|
pthread_attr_destroy(&t_attr);
|
|
destroy_netsukuku();
|
|
|
|
exit(0);
|
|
}
|