mirror of
https://github.com/ChronosX88/netsukuku.git
synced 2024-11-29 21:52:18 +00:00
941 lines
27 KiB
C
941 lines
27 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 prevent_duplication;
|
|
|
|
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");
|
|
}
|
|
|
|
/*
|
|
* 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]);
|
|
}
|
|
|
|
/* 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);
|
|
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);
|
|
}
|
|
}
|
|
|
|
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'},
|
|
{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 'C':
|
|
ntk_thread_creatation();
|
|
break;
|
|
|
|
case 'v':
|
|
printf("%s\n",VERSION_STR);
|
|
exit(0);
|
|
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;
|
|
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);
|
|
}
|