netsukuku/src/netsukuku.c

941 lines
27 KiB
C
Raw Normal View History

2013-09-16 09:53:25 +00:00
/* 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
2013-09-16 09:53:25 +00:00
* 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>
2013-09-16 09:53:25 +00:00
extern int errno;
extern char *optarg;
extern int optind, opterr, optopt;
int destroy_netsukuku_mutex;
int pid_saved;
int prevent_duplication;
2014-06-02 03:58:16 +00:00
2013-09-16 09:53:25 +00:00
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",
2013-09-16 09:53:25 +00:00
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",
2013-09-16 09:53:25 +00:00
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) &&
2013-09-16 09:53:25 +00:00
(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
2013-09-16 09:53:25 +00:00
/* 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,
2013-09-16 09:53:25 +00:00
&me.bmap_nodes_opened);
if(file_exist(server_opt.ext_map_file) &&
(me.ext_map=load_extmap(server_opt.ext_map_file,
2013-09-16 09:53:25 +00:00
&me.cur_quadg)))
debug(DBG_NORMAL, "External map loaded");
else
me.ext_map=init_extmap(FAMILY_LVLS, 0);
2013-09-16 09:53:25 +00:00
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,
2013-09-16 09:53:25 +00:00
server_opt.bnode_map_file);
#endif
2013-09-16 09:53:25 +00:00
debug(DBG_NORMAL, "Saving the external map");
save_extmap(me.ext_map, MAXGROUPNODE, &me.cur_quadg,
2013-09-16 09:53:25 +00:00
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"
2013-09-16 09:53:25 +00:00
"\n"
" -r Runs in restricted mode\n"
" -I Share your internet connection with other nodes\n"
2013-09-16 09:53:25 +00:00
"\n"
" -c configuration file\n"
" -l Enables logging to file\n"
2013-09-16 09:53:25 +00:00
"\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");
2013-09-16 09:53:25 +00:00
}
/*
* fill_default_options: fills the default values in the server_opt struct
*/
void fill_default_options(void)
{
setzero(&server_opt, sizeof(server_opt));
2013-09-16 09:53:25 +00:00
server_opt.family=AF_INET;
2013-09-16 09:53:25 +00:00
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,
2013-09-16 09:53:25 +00:00
&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,
2013-09-16 09:53:25 +00:00
&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;
2013-09-16 09:53:25 +00:00
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]);
}
/* Checks and removes any existing interface which is intended to be excluded*/
void check_excluded(void) {
int i;
printf("Number of Interfaces in Use: %d\n", server_opt.ifs_n);
printf("Interface names in Use: %s", (char*)server_opt.ifs);
for(i=0; i<server_opt.ifs_n; i++) {
if(strcmp(server_opt.ifs[i], optarg) == 0) {
printf("Interface %s removed, And replaced with %s", server_opt.ifs[i], server_opt.ifs[server_opt.ifs_n]);
strncpy(server_opt.ifs[i], server_opt.ifs[server_opt.ifs_n], strlen(server_opt.ifs[server_opt.ifs_n]));
server_opt.ifs_n -= 1;
}
}
}
/* Adds all interfaces available which are up, And not the interface set by the user.
* -e eth0 would exclude eth0 from being used by netsukuku. It, Also, Excludes the
* loopback interface, And tunl0, and tunl1, If it exists.
*
* It iterates through a pointer to the getifaddrs struct, Using the ifa_name member
* for reading the interface name, And ifa_next to move to the next
* interface in the array.
*
* It commits every up interface name that is not the one specified to be excluded
* by the user, Nor the loop back interface to server_opt.ifs and to pointer
* to the struct interface in the member dev_name, And increments the server_opt.ifs_n member.
* It, Also, Sets the index of each interface to a pointer to the struct interface
* in the member dev_idx
*
* It checks if it has already been run, If it has, It just runs check_excluded()
* and then exits. check_excluded() is run at the end of the function
* to check for errors in excluding optarg.
*
* returns 0 on success, -1 on error, And 1 if it has already been run.
*/
void
exclude_interface()
{
if(prevent_duplication == 1) {
check_excluded();
return;
}
char *ifs = "null1";
char *old_tmp = "null2";
interface *ifs_a;
int ifs_n = 1;
struct ifaddrs *addrs,*tmp;
if (getifaddrs(&addrs) !=0) {
printf("%s\n", strerror(errno));
exit(-1);
}
tmp = addrs;
while(tmp) {
old_tmp = ifs;
if(tmp && tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_PACKET && tmp->ifa_flags & IFF_UP && !(tmp->ifa_flags & IFF_LOOPBACK && strncmp(tmp->ifa_name, "tunl0", (int)strlen(tmp->ifa_name)) != 0 && strncmp(tmp->ifa_name, "tunl1", (int)strlen(tmp->ifa_name)) != 0 && strcmp(optarg, tmp->ifa_name) != 0)) {
ifs = tmp->ifa_name;
ifs_n++;
}
printf("Good ifs is: %s\n", ifs);
if(strcmp(old_tmp, ifs) == 0) {
printf("Loop finished: %s\n", ifs);
2014-05-26 23:31:35 +00:00
check_excluded();
return;
}
tmp = tmp->ifa_next;
server_opt.ifs[server_opt.ifs_n++]=xstrndup(ifs, IFNAMSIZ-1);
printf("Using Interface: %s\n", ifs);
ifs_a[ifs_n].dev_idx = (int)tmp->ifa_flags;
strncpy(ifs_a[ifs_n].dev_name, ifs, (int)strlen(ifs));
}
check_excluded();
freeifaddrs(addrs);
}
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);
}
}
2013-09-16 09:53:25 +00:00
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'},
2013-09-16 09:53:25 +00:00
{"restricted", 0, 0, 'r'},
{"share-inet", 0, 0, 'I'},
2013-09-16 09:53:25 +00:00
{"debug", 0, 0, 'd'},
{"version", 0, 0, 'v'},
{"kill", 0, 0, 'k'},
{"exclude", 1, 0, 'e'},
{"console", 0, 0, 'C'},
2013-09-16 09:53:25 +00:00
{0, 0, 0, 0}
};
c = getopt_long (argc, argv,"i:c:l:e:hvd64DRrIakC", long_options,
2013-09-16 09:53:25 +00:00
&option_index);
if (c == -1)
break;
switch(c)
{
case 'C':
ntk_thread_creatation();
break;
case 'v':
2013-09-16 09:53:25 +00:00
printf("%s\n",VERSION_STR);
exit(0);
2013-09-16 09:53:25 +00:00
break;
case 'e':
prevent_duplication = -1;
prevent_duplication++;
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;
2013-09-16 09:53:25 +00:00
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':
2013-09-16 09:53:25 +00:00
server_opt.config_file=xstrndup(optarg, NAME_MAX-1);
break;
case 'l':
if(log_to_file(optarg) < 0)
fatal(0);
break;
case 'i':
break;
2013-09-16 09:53:25 +00:00
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
2013-09-16 09:53:25 +00:00
* 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)); \
2013-09-16 09:53:25 +00:00
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 &&
2013-09-16 09:53:25 +00:00
!file_exist(server_opt.ip_masq_script))
fatal("ip_masquerade_script \"%s\" is inexistent",
server_opt.ip_masq_script);
if(server_opt.shape_internet &&
2013-09-16 09:53:25 +00:00
!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 &&
2013-09-16 09:53:25 +00:00
(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) {
2013-09-16 09:53:25 +00:00
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.");
2013-09-16 09:53:25 +00:00
#ifdef IPV6_DISABLED
if(server_opt.inet_gw.family == AF_INET6)
fatal("Ipv6 is not supported");
#endif
}
void init_netsukuku(char **argv)
{
xsrand();
2013-09-16 09:53:25 +00:00
if(geteuid())
fatal("Need root privileges");
2013-09-16 09:53:25 +00:00
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();
2013-09-16 09:53:25 +00:00
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
2013-09-16 09:53:25 +00:00
*/
if(if_init_all(server_opt.ifs, server_opt.ifs_n,
2013-09-16 09:53:25 +00:00
me.cur_ifs, &me.cur_ifs_n) < 0)
fatal("Cannot initialize any network interfaces");
/*
2013-09-16 09:53:25 +00:00
* 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 +
2013-09-16 09:53:25 +00:00
server_opt.my_dnload_bw)/2);
init_internet_gateway_search();
2013-09-16 09:53:25 +00:00
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,
2013-09-16 09:53:25 +00:00
server_opt.max_accepts_per_host_time);
init_accept_tbl(server_opt.max_connections,
server_opt.max_accepts_per_host,
2013-09-16 09:53:25 +00:00
server_opt.max_accepts_per_host_time);
#endif
2013-09-16 09:53:25 +00:00
if(restricted_mode)
loginfo("NetsukukuD is in restricted mode. "
"Restricted class: %s",
2013-09-16 09:53:25 +00:00
server_opt.restricted_class?RESTRICTED_172_STR:RESTRICTED_10_STR);
2013-09-16 09:53:25 +00:00
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);
2013-09-16 09:53:25 +00:00
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);
2013-09-16 09:53:25 +00:00
if(!destroy_netsukuku())
fatal("Termination signal caught. Dying, bye, bye");
}
void *reload_hostname_thread(void *null)
{
/*
2013-09-16 09:53:25 +00:00
* 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;
2013-09-16 09:53:25 +00:00
time_t cur_t;
if(sighup_timestamp == (cur_t=time(0)))
return;
sighup_timestamp=time(0);
2013-09-16 09:53:25 +00:00
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)
{
/*
2013-09-16 09:53:25 +00:00
* 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;
2013-09-16 09:53:25 +00:00
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;
2013-09-16 09:53:25 +00:00
log_init(argv[0], 0, 1);
2013-09-16 09:53:25 +00:00
/* 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();
2013-09-16 09:53:25 +00:00
/* 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();
2013-09-16 09:53:25 +00:00
/* 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);
2013-09-16 09:53:25 +00:00
/* 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));
2013-09-16 09:53:25 +00:00
}
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));
/*
2013-09-16 09:53:25 +00:00
* These are the daemons, the main threads that keeps NetsukukuD
* up & running.
2013-09-16 09:53:25 +00:00
*/
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);
2013-09-16 09:53:25 +00:00
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);
2013-09-16 09:53:25 +00:00
/* Now we hook in Netsukuku */
netsukuku_hook(0, 0);
2013-09-16 09:53:25 +00:00
/*
* If not disabled, start the ANDNA daemon
2013-09-16 09:53:25 +00:00
*/
if(!server_opt.disable_andna)
pthread_create(&andna_thread, &t_attr, andna_main, 0);
2013-09-16 09:53:25 +00:00
xfree(port);
if(restricted_mode && (server_opt.share_internet ||
2013-09-16 09:53:25 +00:00
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);
}