1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276 |
- /*
- Copyright (c) 2007, 2008 by Juliusz Chroboczek
- Copyright (c) 2010 by Vincent Gross
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/time.h>
- #include <time.h>
- #include <signal.h>
- #include <assert.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <net/if.h>
- #include <arpa/inet.h>
- #include "babeld.h"
- #include "util.h"
- #include "net.h"
- #include "kernel.h"
- #include "interface.h"
- #include "source.h"
- #include "neighbour.h"
- #include "route.h"
- #include "xroute.h"
- #include "message.h"
- #include "resend.h"
- #include "configuration.h"
- #include "local.h"
- #include "rule.h"
- #include "version.h"
- #include "decrypt.h"
- #include "lorauth.h"
- struct timeval now;
- unsigned char myid[8];
- int have_id = 0;
- int debug = 0;
- int link_detect = 0;
- int all_wireless = 0;
- int has_ipv6_subtrees = 0;
- int default_wireless_hello_interval = -1;
- int default_wired_hello_interval = -1;
- int resend_delay = -1;
- int random_id = 0;
- int do_daemonise = 0;
- int skip_kernel_setup = 0;
- const char *logfile = NULL,
- *pidfile = "/var/run/babeld.pid",
- *state_file = "/var/lib/babel-state";
- unsigned char *receive_buffer = NULL;
- int receive_buffer_size = 0;
- const unsigned char zeroes[16] = {0};
- const unsigned char ones[16] =
- {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- int protocol_port;
- unsigned char protocol_group[16];
- int protocol_socket = -1;
- int kernel_socket = -1;
- static int kernel_routes_changed = 0;
- static int kernel_rules_changed = 0;
- static int kernel_link_changed = 0;
- static int kernel_addr_changed = 0;
- struct timeval check_neighbours_timeout, check_interfaces_timeout;
- static volatile sig_atomic_t exiting = 0, dumping = 0, reopening = 0;
- static int accept_local_connections(void);
- static void init_signals(void);
- static void dump_tables(FILE *out);
- // -- rsa decryption --
- mbedtls_rsa_context rsa_context;
- mbedtls_entropy_context rsa_entropy;
- mbedtls_ctr_drbg_context rsa_ctr_drbg;
- // ----
- static int
- kernel_route_notify(struct kernel_route *route, void *closure)
- {
- kernel_routes_changed = 1;
- return -1;
- }
- static int
- kernel_addr_notify(struct kernel_addr *addr, void *closure)
- {
- kernel_addr_changed = 1;
- return -1;
- }
- static int
- kernel_link_notify(struct kernel_link *link, void *closure)
- {
- struct interface *ifp;
- FOR_ALL_INTERFACES(ifp) {
- if(strcmp(ifp->name, link->ifname) == 0) {
- kernel_link_changed = 1;
- return -1;
- }
- }
- return 0;
- }
- static int
- kernel_rule_notify(struct kernel_rule *rule, void *closure)
- {
- int i;
- if(martian_prefix(rule->src, rule->src_plen))
- return 0;
- i = rule->priority - src_table_prio;
- if(i < 0 || SRC_TABLE_NUM <= i)
- return 0;
- kernel_rules_changed = 1;
- return -1;
- }
- static void lorauth_testings(void)
- {
- // -- quick rsa decrypt tests --
- printf("\n---- testing decrypt module ----\n");
- printf("rsa_init: %d \n" , (int)rsa_module_init("rsa_pub.txt",
- &rsa_context,
- &rsa_entropy,
- &rsa_ctr_drbg));
- printf("rsa_context:");
- printf(" N: %d \n E: %d\n", rsa_context.N, rsa_context.E);
- printf(" len: %d \n", (int)rsa_context.len);
- char *encrypted_message = calloc(1, 514);
- strcpy(encrypted_message, "0D329E2B5CA35A5487A35FCF8B91586011B2B3EA38CDACFD2E5A14F4B3681A740A9346E85C7227795D11B61513481C776330535E6BAF1EC856EE69343FD84569C2F1F9202FD572B9AC099D61F4AC68E094F3EA31B77B0FC205B14805868263366849F2E783529BDB57BDBB213660C66FD3BC8E43EB4F05992467AFC7F2CB14854D4A7DDFA615FD56472E34CED2B675282E68E9E90A36549B9EE6284B7CF5D59D7BD8CE05D9FF15BA07E6A7CEBAFA10538E6ACD97AB8708ED0A76749B97A7C5A1C02E83EF227918B9CE7DC986A5109F4DEDDD2BBB38C4E97801EBC937446806CBC46707E71853517BFF9779C78B1F0B9ACAE72CDB509E5CA52FE7B08576B9624C");
- printf("rsa_decrypt: %d \n", (int)rsa_decrypt(&rsa_context,
- &rsa_entropy,
- &rsa_ctr_drbg,
- encrypted_message,
- (unsigned char *)&rsa_result));
- printf("decrypted message: %s\n", rsa_result);
- printf("rsa_decrypt: %d \n", (int)rsa_decrypt(&rsa_context,
- &rsa_entropy,
- &rsa_ctr_drbg,
- "293FBB480F423A43FAA0F794B54682EB9593E81CC286E8135AF4F135E2275C9B09DFF5FDAD6052876E47A998AFF56318F0986E5467BE26C7ACECF8799825D93EB03BE9BC41B86AE66A99551FDAC66D10821AA5FE27391A534846297378A75D7386EAA285EB4A18CB1F0CC2B3BA5903D0E7166DCD9BE4BFEEEEB820F0524C492748084535C5D28500D77382437BEFAA1AD8347913D2F71D7EC725B61B6FAABDB4C1EA77BAEBDE37ED997990E49193A9FDAC772A0EAFFB735B128C593D15953AD75A310BDB95AAACF39229DF3634422DB3F97FDA095F21982F73AD3723844AC59E93EA0FC7C16EFD6723D2385A476818B5A2AC9363F59B13C3D4DFBB82B2AC0676",
- (unsigned char *)&rsa_result));
- printf("decrypted message: %s\n", rsa_result);
-
- printf("\n-----------\n");
- printf("\n----- Testing lorauth token ------");
- unsigned char *token = calloc(1, LORAUTH_CIPHER_LEN + 1);
-
- unsigned char id_testing[8] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
-
- printf("\nlorauth_token:\n");
- printf("ID: %s \n", format_eui64(id_testing));
- printf("seqno: 0x3214\n");
- printf("index: \t %d\n", lorauth_token_index(id_testing,
- 0x3214));
- lorauth_token(token, id_testing, 0x3214);
- printf("token:\n%s -- %d\n", token, strlen((char*)token));
- printf("reduced token: %s\n", reduced_lorauth_token(token));
- rsa_decrypt(&rsa_context, &rsa_entropy, &rsa_ctr_drbg, (char *)token,
- (unsigned char *)&rsa_result);
- printf("\n decrypted Token: %s\n", rsa_result);
- printf("\n ------ Tesiting lorauth check ----------- \n");
- unsigned char prefix_testing[16] = {80,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0};
- printf("check: %d\n", check_lorauth_token(id_testing,
- prefix_testing,
- 0x3214,
- strlen((char*)token),
- (char*)token));
- printf("new check\n");
- printf("\ncheck: %d\n", check_lorauth_token(id_testing,
- prefix_testing,
- 0x3214,
- 512,
- (char *)encrypted_message));
-
- printf("\n-----------\n");
- free(token);
- // ----
-
- }
- int
- main(int argc, char **argv)
- {
- lorauth_testings();
- struct sockaddr_in6 sin6;
- int rc, fd, i, opt;
- time_t expiry_time, source_expiry_time, kernel_dump_time;
- const char **config_files = NULL;
- int num_config_files = 0;
- void *vrc;
- unsigned int seed;
- struct interface *ifp;
- gettime(&now);
- rc = read_random_bytes(&seed, sizeof(seed));
- if(rc < 0) {
- perror("read(random)");
- seed = 42;
- }
- seed ^= (now.tv_sec ^ now.tv_usec);
- srandom(seed);
- parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
- protocol_port = 6696;
- change_smoothing_half_life(4);
- has_ipv6_subtrees = kernel_has_ipv6_subtrees();
- while(1) {
- opt = getopt(argc, argv,
- "m:p:h:H:i:k:A:sruS:d:g:G:lwz:M:t:T:c:C:DL:I:V");
- if(opt < 0)
- break;
- switch(opt) {
- case 'm':
- rc = parse_address(optarg, protocol_group, NULL);
- if(rc < 0)
- goto usage;
- if(protocol_group[0] != 0xff) {
- fprintf(stderr,
- "%s is not a multicast address\n", optarg);
- goto usage;
- }
- if(protocol_group[1] != 2) {
- fprintf(stderr,
- "Warning: %s is not a link-local multicast address\n",
- optarg);
- }
- break;
- case 'p':
- protocol_port = parse_nat(optarg);
- if(protocol_port <= 0 || protocol_port > 0xFFFF)
- goto usage;
- break;
- case 'h':
- default_wireless_hello_interval = parse_thousands(optarg);
- if(default_wireless_hello_interval <= 0 ||
- default_wireless_hello_interval > 0xFFFF * 10)
- goto usage;
- break;
- case 'H':
- default_wired_hello_interval = parse_thousands(optarg);
- if(default_wired_hello_interval <= 0 ||
- default_wired_hello_interval > 0xFFFF * 10)
- goto usage;
- break;
- case 'k':
- kernel_metric = parse_nat(optarg);
- if(kernel_metric < 0 || kernel_metric > 0xFFFF)
- goto usage;
- break;
- case 'A':
- allow_duplicates = parse_nat(optarg);
- if(allow_duplicates < 0 || allow_duplicates > 0xFFFF)
- goto usage;
- break;
- case 's':
- split_horizon = 0;
- break;
- case 'r':
- random_id = 1;
- break;
- case 'u':
- keep_unfeasible = 1;
- break;
- case 'S':
- state_file = optarg;
- break;
- case 'd':
- debug = parse_nat(optarg);
- if(debug < 0)
- goto usage;
- break;
- case 'g':
- case 'G':
- if(opt == 'g')
- local_server_write = 0;
- else
- local_server_write = 1;
- if(optarg[0] == '/') {
- local_server_port = -1;
- free(local_server_path);
- local_server_path = strdup(optarg);
- } else {
- local_server_port = parse_nat(optarg);
- free(local_server_path);
- local_server_path = NULL;
- if(local_server_port <= 0 || local_server_port > 0xFFFF)
- goto usage;
- }
- break;
- case 'l':
- link_detect = 1;
- break;
- case 'w':
- all_wireless = 1;
- break;
- case 'z':
- {
- char *comma;
- diversity_kind = (int)strtol(optarg, &comma, 0);
- if(*comma == '\0')
- diversity_factor = 128;
- else if(*comma == ',')
- diversity_factor = parse_nat(comma + 1);
- else
- goto usage;
- if(diversity_factor <= 0 || diversity_factor > 256)
- goto usage;
- }
- break;
- case 'M': {
- int l = parse_nat(optarg);
- if(l < 0 || l > 3600)
- goto usage;
- change_smoothing_half_life(l);
- break;
- }
- case 't':
- export_table = parse_nat(optarg);
- if(export_table < 0 || export_table > 0xFFFF)
- goto usage;
- break;
- case 'T':
- if(add_import_table(parse_nat(optarg)))
- goto usage;
- break;
- case 'c':
- config_files = realloc(config_files,
- (num_config_files + 1) * sizeof(char*));
- if(config_files == NULL) {
- fprintf(stderr, "Couldn't allocate config file.\n");
- exit(1);
- }
- config_files[num_config_files++] = optarg;
- break;
- case 'C':
- rc = parse_config_from_string(optarg, strlen(optarg), NULL);
- if(rc != CONFIG_ACTION_DONE) {
- fprintf(stderr,
- "Couldn't parse configuration from command line.\n");
- exit(1);
- }
- break;
- case 'D':
- do_daemonise = 1;
- break;
- case 'L':
- logfile = optarg;
- break;
- case 'I':
- pidfile = optarg;
- break;
- case 'V':
- fprintf(stderr, "%s\n", BABELD_VERSION);
- exit(0);
- break;
- default:
- goto usage;
- }
- }
- if(num_config_files == 0) {
- if(access("/etc/babeld.conf", F_OK) >= 0) {
- config_files = malloc(sizeof(char*));
- if(config_files == NULL) {
- fprintf(stderr, "Couldn't allocate config file.\n");
- exit(1);
- }
- config_files[num_config_files++] = "/etc/babeld.conf";
- }
- }
- for(i = 0; i < num_config_files; i++) {
- int line;
- rc = parse_config_from_file(config_files[i], &line);
- if(rc < 0) {
- fprintf(stderr,
- "Couldn't parse configuration from file %s "
- "(error at line %d).\n",
- config_files[i], line);
- exit(1);
- }
- }
- free(config_files);
- if(default_wireless_hello_interval <= 0)
- default_wireless_hello_interval = 4000;
- default_wireless_hello_interval = MAX(default_wireless_hello_interval, 5);
- if(default_wired_hello_interval <= 0)
- default_wired_hello_interval = 4000;
- default_wired_hello_interval = MAX(default_wired_hello_interval, 5);
- resend_delay = 2000;
- resend_delay = MIN(resend_delay, default_wireless_hello_interval / 2);
- resend_delay = MIN(resend_delay, default_wired_hello_interval / 2);
- resend_delay = MAX(resend_delay, 20);
- if(do_daemonise) {
- if(logfile == NULL)
- logfile = "/var/log/babeld.log";
- }
- rc = reopen_logfile();
- if(rc < 0) {
- perror("reopen_logfile()");
- exit(1);
- }
-
- fd = open("/dev/null", O_RDONLY);
- if(fd < 0) {
- perror("open(null)");
- exit(1);
- }
- rc = dup2(fd, 0);
- if(rc < 0) {
- perror("dup2(null, 0)");
- exit(1);
- }
- close(fd);
- if(do_daemonise) {
- rc = daemonise();
- if(rc < 0) {
- perror("daemonise");
- exit(1);
- }
- }
-
- if(pidfile && pidfile[0] != '\0') {
- int pfd, len;
- char buf[100];
- len = snprintf(buf, 100, "%lu", (unsigned long)getpid());
- if(len < 0 || len >= 100) {
- perror("snprintf(getpid)");
- exit(1);
- }
- pfd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644);
- if(pfd < 0) {
- char buf[40];
- snprintf(buf, 40, "creat(%s)", pidfile);
- buf[39] = '\0';
- perror(buf);
- exit(1);
- }
- rc = write(pfd, buf, len);
- if(rc < len) {
- perror("write(pidfile)");
- goto fail_pid;
- }
- close(pfd);
- }
- rc = kernel_setup(1);
- if(rc < 0) {
- fprintf(stderr, "kernel_setup failed.\n");
- goto fail_pid;
- }
- rc = kernel_setup_socket(1);
- if(rc < 0) {
- fprintf(stderr, "kernel_setup_socket failed.\n");
- kernel_setup(0);
- goto fail_pid;
- }
- rc = finalise_config();
- if(rc < 0) {
- fprintf(stderr, "Couldn't finalise configuration.\n");
- goto fail;
- }
- for(i = optind; i < argc; i++) {
- vrc = add_interface(argv[i], NULL);
- if(vrc == NULL)
- goto fail;
- }
- if(interfaces == NULL) {
- fprintf(stderr, "Eek... asked to run on no interfaces!\n");
- goto fail;
- }
- if(!have_id && !random_id) {
- /* We use all available interfaces here, since this increases the
- chances of getting a stable router-id in case the set of Babel
- interfaces changes. */
- for(i = 1; i < 256; i++) {
- char buf[IF_NAMESIZE], *ifname;
- unsigned char eui[8];
- ifname = if_indextoname(i, buf);
- if(ifname == NULL)
- continue;
- rc = if_eui64(ifname, i, eui);
- if(rc < 0)
- continue;
- memcpy(myid, eui, 8);
- have_id = 1;
- break;
- }
- }
- if(!have_id) {
- if(!random_id)
- fprintf(stderr,
- "Warning: couldn't find router id -- "
- "using random value.\n");
- rc = read_random_bytes(myid, 8);
- if(rc < 0) {
- perror("read(random)");
- goto fail;
- }
- /* Clear group and global bits */
- myid[0] &= ~3;
- }
- myseqno = (random() & 0xFFFF);
- fd = open(state_file, O_RDONLY);
- if(fd < 0 && errno != ENOENT)
- perror("open(babel-state)");
- rc = unlink(state_file);
- if(fd >= 0 && rc < 0) {
- perror("unlink(babel-state)");
- /* If we couldn't unlink it, it's probably stale. */
- close(fd);
- fd = -1;
- }
- if(fd >= 0) {
- char buf[100];
- int s;
- rc = read(fd, buf, 99);
- if(rc < 0) {
- perror("read(babel-state)");
- } else {
- buf[rc] = '\0';
- rc = sscanf(buf, "%d\n", &s);
- if(rc == 1 && s >= 0 && s <= 0xFFFF) {
- myseqno = seqno_plus(s, 1);
- } else {
- fprintf(stderr, "Couldn't parse babel-state.\n");
- }
- }
- close(fd);
- fd = -1;
- }
- protocol_socket = babel_socket(protocol_port);
- if(protocol_socket < 0) {
- perror("Couldn't create link local socket");
- goto fail;
- }
- if(local_server_port >= 0) {
- local_server_socket = tcp_server_socket(local_server_port, 1);
- if(local_server_socket < 0) {
- perror("local_server_socket");
- goto fail;
- }
- } else if(local_server_path) {
- local_server_socket = unix_server_socket(local_server_path);
- if(local_server_socket < 0) {
- perror("local_server_socket");
- goto fail;
- }
- }
- init_signals();
- rc = resize_receive_buffer(1500);
- if(rc < 0)
- goto fail;
- if(receive_buffer == NULL)
- goto fail;
- debugf("before check interfaces..\n");
- check_interfaces();
- debugf("after check interfaces..\n");
- // first check_xroutes
- rc = check_xroutes(0);
- if(rc < 0)
- fprintf(stderr, "Warning: couldn't check exported routes.\n");
- rc = check_rules();
- if(rc < 0)
- fprintf(stderr, "Warning: couldn't check rules.\n");
- kernel_routes_changed = 0;
- kernel_rules_changed = 0;
- kernel_link_changed = 0;
- kernel_addr_changed = 0;
- kernel_dump_time = now.tv_sec + roughly(30);
- schedule_neighbours_check(5000, 1);
- schedule_interfaces_check(30000, 1);
- expiry_time = now.tv_sec + roughly(30);
- source_expiry_time = now.tv_sec + roughly(300);
- /* Make some noise so that others notice us, and send retractions in
- case we were restarted recently */
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- /* Apply jitter before we send the first message. */
- usleep(roughly(10000));
- gettime(&now);
- send_hello(ifp);
- send_wildcard_retraction(ifp);
- }
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- usleep(roughly(10000));
- gettime(&now);
- send_hello(ifp);
- send_wildcard_retraction(ifp);
- send_self_update(ifp);
- send_request(ifp, NULL, 0, NULL, 0);
- flushupdates(ifp);
- flushbuf(ifp);
- }
- debugf("Entering main loop.\n");
- while(1) {
- struct timeval tv;
- fd_set readfds;
- gettime(&now);
- tv = check_neighbours_timeout;
- timeval_min(&tv, &check_interfaces_timeout);
- timeval_min_sec(&tv, expiry_time);
- timeval_min_sec(&tv, source_expiry_time);
- timeval_min_sec(&tv, kernel_dump_time);
- timeval_min(&tv, &resend_time);
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- timeval_min(&tv, &ifp->flush_timeout);
- timeval_min(&tv, &ifp->hello_timeout);
- timeval_min(&tv, &ifp->update_timeout);
- timeval_min(&tv, &ifp->update_flush_timeout);
- }
- timeval_min(&tv, &unicast_flush_timeout);
- FD_ZERO(&readfds);
- if(timeval_compare(&tv, &now) > 0) {
- int maxfd = 0;
- timeval_minus(&tv, &tv, &now);
- FD_SET(protocol_socket, &readfds);
- maxfd = MAX(maxfd, protocol_socket);
- if(kernel_socket < 0) kernel_setup_socket(1);
- if(kernel_socket >= 0) {
- FD_SET(kernel_socket, &readfds);
- maxfd = MAX(maxfd, kernel_socket);
- }
- if(local_server_socket >= 0 &&
- num_local_sockets < MAX_LOCAL_SOCKETS) {
- FD_SET(local_server_socket, &readfds);
- maxfd = MAX(maxfd, local_server_socket);
- }
- for(i = 0; i < num_local_sockets; i++) {
- FD_SET(local_sockets[i].fd, &readfds);
- maxfd = MAX(maxfd, local_sockets[i].fd);
- }
- rc = select(maxfd + 1, &readfds, NULL, NULL, &tv);
- if(rc < 0) {
- if(errno != EINTR) {
- perror("select");
- sleep(1);
- }
- rc = 0;
- FD_ZERO(&readfds);
- }
- }
- gettime(&now);
- if(exiting)
- break;
- if(kernel_socket >= 0 && FD_ISSET(kernel_socket, &readfds)) {
- struct kernel_filter filter = {0};
- filter.route = kernel_route_notify;
- filter.addr = kernel_addr_notify;
- filter.link = kernel_link_notify;
- filter.rule = kernel_rule_notify;
- kernel_callback(&filter);
- }
- if(FD_ISSET(protocol_socket, &readfds)) {
- rc = babel_recv(protocol_socket,
- receive_buffer, receive_buffer_size,
- (struct sockaddr*)&sin6, sizeof(sin6));
- if(rc < 0) {
- if(errno != EAGAIN && errno != EINTR) {
- perror("recv");
- sleep(1);
- }
- } else {
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- if(ifp->ifindex == sin6.sin6_scope_id) {
- parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
- receive_buffer, rc);
- VALGRIND_MAKE_MEM_UNDEFINED(receive_buffer,
- receive_buffer_size);
- break;
- }
- }
- }
- }
- if(local_server_socket >= 0 && FD_ISSET(local_server_socket, &readfds))
- accept_local_connections();
- i = 0;
- while(i < num_local_sockets) {
- if(FD_ISSET(local_sockets[i].fd, &readfds)) {
- rc = local_read(&local_sockets[i]);
- if(rc <= 0) {
- if(rc < 0) {
- if(errno == EINTR || errno == EAGAIN)
- continue;
- perror("read(local_socket)");
- }
- local_socket_destroy(i);
- }
- }
- i++;
- }
- if(reopening) {
- kernel_dump_time = now.tv_sec;
- check_neighbours_timeout = now;
- expiry_time = now.tv_sec;
- rc = reopen_logfile();
- if(rc < 0) {
- perror("reopen_logfile");
- break;
- }
- reopening = 0;
- }
- if(kernel_link_changed || kernel_addr_changed) {
- check_interfaces();
- kernel_link_changed = 0;
- }
- if(kernel_routes_changed || kernel_addr_changed ||
- kernel_rules_changed || now.tv_sec >= kernel_dump_time) {
- // --mark
- rc = check_xroutes(1);
- if(rc < 0)
- fprintf(stderr, "Warning: couldn't check exported routes.\n");
- rc = check_rules();
- if(rc < 0)
- fprintf(stderr, "Warning: couldn't check rules.\n");
- kernel_routes_changed = kernel_rules_changed =
- kernel_addr_changed = 0;
- if(kernel_socket >= 0)
- kernel_dump_time = now.tv_sec + roughly(300);
- else
- kernel_dump_time = now.tv_sec + roughly(30);
- }
- if(timeval_compare(&check_neighbours_timeout, &now) < 0) {
- int msecs;
- msecs = check_neighbours();
- /* Multiply by 3/2 to allow neighbours to expire. */
- msecs = MAX(3 * msecs / 2, 10);
- schedule_neighbours_check(msecs, 1);
- }
- if(timeval_compare(&check_interfaces_timeout, &now) < 0) {
- check_interfaces();
- schedule_interfaces_check(30000, 1);
- }
- if(now.tv_sec >= expiry_time) {
- expire_routes();
- expire_resend();
- expiry_time = now.tv_sec + roughly(30);
- }
- if(now.tv_sec >= source_expiry_time) {
- expire_sources();
- source_expiry_time = now.tv_sec + roughly(300);
- }
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- if(timeval_compare(&now, &ifp->hello_timeout) >= 0)
- send_hello(ifp);
- if(timeval_compare(&now, &ifp->update_timeout) >= 0)
- send_update(ifp, 0, NULL, 0, NULL, 0, NULL, 0); // -- lorauth
- if(timeval_compare(&now, &ifp->update_flush_timeout) >= 0)
- flushupdates(ifp);
- }
- if(resend_time.tv_sec != 0) {
- if(timeval_compare(&now, &resend_time) >= 0)
- {
- printf("\n llamando a do_resen()\n");
- do_resend();
- }
- }
- if(unicast_flush_timeout.tv_sec != 0) {
- if(timeval_compare(&now, &unicast_flush_timeout) >= 0)
- flush_unicast(1);
- }
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- if(ifp->flush_timeout.tv_sec != 0) {
- if(timeval_compare(&now, &ifp->flush_timeout) >= 0)
- flushbuf(ifp);
- }
- }
- if(UNLIKELY(debug || dumping)) {
- dump_tables(stdout);
- dumping = 0;
- }
- } // end while(1)
- debugf("Exiting...\n");
- usleep(roughly(10000));
- gettime(&now);
- /* We need to flush so interface_up won't try to reinstall. */
- flush_all_routes();
- // -- mark
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- send_wildcard_retraction(ifp);
- /* Make sure that we expire quickly from our neighbours'
- association caches. */
- send_hello_noupdate(ifp, 10);
- flushbuf(ifp);
- usleep(roughly(1000));
- gettime(&now);
- }
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- /* Make sure they got it. */
- send_wildcard_retraction(ifp);
- send_hello_noupdate(ifp, 1);
- flushbuf(ifp);
- usleep(roughly(10000));
- gettime(&now);
- interface_up(ifp, 0);
- }
- release_tables();
- kernel_setup_socket(0);
- kernel_setup(0);
- fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
- if(fd < 0) {
- perror("creat(babel-state)");
- unlink(state_file);
- } else {
- char buf[10];
- rc = snprintf(buf, 10, "%d\n", (int)myseqno);
- if(rc < 0 || rc >= 10) {
- fprintf(stderr, "write(babel-state): overflow.\n");
- unlink(state_file);
- } else {
- rc = write(fd, buf, rc);
- if(rc < 0) {
- perror("write(babel-state)");
- unlink(state_file);
- }
- fsync(fd);
- }
- close(fd);
- }
- if(local_server_socket >= 0 && local_server_path) {
- unlink(local_server_path);
- free(local_server_path);
- }
- if(pidfile)
- unlink(pidfile);
- debugf("Done.\n");
- return 0;
- usage:
- fprintf(stderr,
- "%s\n"
- "Syntax: babeld "
- "[-V] [-m multicast_address] [-p port] [-S state-file]\n"
- " "
- "[-h hello] [-H wired_hello] [-z kind[,factor]]\n"
- " "
- "[-g port] [-G port] [-k metric] [-A metric] [-s] [-l] [-w] [-r]\n"
- " "
- "[-u] [-t table] [-T table] [-c file] [-C statement]\n"
- " "
- "[-d level] [-D] [-L logfile] [-I pidfile]\n"
- " "
- "interface...\n",
- BABELD_VERSION);
- exit(1);
- fail:
- FOR_ALL_INTERFACES(ifp) {
- if(!if_up(ifp))
- continue;
- interface_up(ifp, 0);
- }
- kernel_setup_socket(0);
- kernel_setup(0);
- fail_pid:
- if(pidfile)
- unlink(pidfile);
- exit(1);
- }
- static int
- accept_local_connections()
- {
- int rc, s;
- struct local_socket *ls;
- if(local_server_socket < 0)
- return 0;
- s = accept(local_server_socket, NULL, NULL);
- if(s < 0) {
- if(errno != EINTR && errno != EAGAIN) {
- perror("accept(local_server_socket)");
- return -1;
- }
- return 0;
- }
- if(num_local_sockets >= MAX_LOCAL_SOCKETS) {
- /* This should never happen, since we don't select for
- the server socket in this case. But I'm paranoid. */
- fprintf(stderr, "Internal error: too many local sockets.\n");
- close(s);
- return -1;
- }
- rc = fcntl(s, F_GETFL, 0);
- if(rc < 0) {
- fprintf(stderr, "Unable to get flags of local socket.\n");
- close(s);
- return -1;
- }
- rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
- if(rc < 0) {
- fprintf(stderr, "Unable to set flags of local socket.\n");
- close(s);
- return -1;
- }
- ls = local_socket_create(s);
- if(ls == NULL) {
- fprintf(stderr, "Unable create local socket.\n");
- close(s);
- return -1;
- }
- local_header(ls);
- return 1;
- }
- void
- schedule_neighbours_check(int msecs, int override)
- {
- struct timeval timeout;
- timeval_add_msec(&timeout, &now, roughly(msecs));
- if(override)
- check_neighbours_timeout = timeout;
- else
- timeval_min(&check_neighbours_timeout, &timeout);
- }
- void
- schedule_interfaces_check(int msecs, int override)
- {
- struct timeval timeout;
- timeval_add_msec(&timeout, &now, roughly(msecs));
- if(override)
- check_interfaces_timeout = timeout;
- else
- timeval_min(&check_interfaces_timeout, &timeout);
- }
- int
- resize_receive_buffer(int size)
- {
- unsigned char *new;
- if(size <= receive_buffer_size)
- return 0;
- new = realloc(receive_buffer, size);
- if(new == NULL) {
- perror("realloc(receive_buffer)");
- return -1;
- }
- receive_buffer = new;
- receive_buffer_size = size;
- return 1;
- }
- static void
- sigexit(int signo)
- {
- exiting = 1;
- }
- static void
- sigdump(int signo)
- {
- dumping = 1;
- }
- static void
- sigreopening(int signo)
- {
- reopening = 1;
- }
- static void
- init_signals(void)
- {
- struct sigaction sa;
- sigset_t ss;
- sigemptyset(&ss);
- sa.sa_handler = sigexit;
- sa.sa_mask = ss;
- sa.sa_flags = 0;
- sigaction(SIGTERM, &sa, NULL);
- sigemptyset(&ss);
- sa.sa_handler = sigexit;
- sa.sa_mask = ss;
- sa.sa_flags = 0;
- sigaction(SIGHUP, &sa, NULL);
- sigemptyset(&ss);
- sa.sa_handler = sigexit;
- sa.sa_mask = ss;
- sa.sa_flags = 0;
- sigaction(SIGINT, &sa, NULL);
- sigemptyset(&ss);
- sa.sa_handler = SIG_IGN;
- sa.sa_mask = ss;
- sa.sa_flags = 0;
- sigaction(SIGPIPE, &sa, NULL);
- sigemptyset(&ss);
- sa.sa_handler = sigdump;
- sa.sa_mask = ss;
- sa.sa_flags = 0;
- sigaction(SIGUSR1, &sa, NULL);
- sigemptyset(&ss);
- sa.sa_handler = sigreopening;
- sa.sa_mask = ss;
- sa.sa_flags = 0;
- sigaction(SIGUSR2, &sa, NULL);
- #ifdef SIGINFO
- sigemptyset(&ss);
- sa.sa_handler = sigdump;
- sa.sa_mask = ss;
- sa.sa_flags = 0;
- sigaction(SIGINFO, &sa, NULL);
- #endif
- }
- static void
- dump_route(FILE *out, struct babel_route *route)
- {
- const unsigned char *nexthop =
- memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
- NULL : route->nexthop;
- char channels[100];
- if(route->channels_len == 0) {
- channels[0] = '\0';
- } else {
- int k, j = 0;
- snprintf(channels, 100, " chan (");
- j = strlen(channels);
- for(k = 0; k < route->channels_len; k++) {
- if(k > 0)
- channels[j++] = ',';
- snprintf(channels + j, 100 - j, "%u", (unsigned)route->channels[k]);
- j = strlen(channels);
- }
- snprintf(channels + j, 100 - j, ")");
- }
- fprintf(out, "%s%s%s metric %d (%d) refmetric %d id %s "
- "seqno %d%s age %d via %s neigh %s%s%s%s\n"
- "cipher: %s\n",
- format_prefix(route->src->prefix, route->src->plen),
- route->src->src_plen > 0 ? " from " : "",
- route->src->src_plen > 0 ?
- format_prefix(route->src->src_prefix, route->src->src_plen) : "",
- route_metric(route), route_smoothed_metric(route), route->refmetric,
- format_eui64(route->src->id),
- (int)route->seqno,
- channels,
- (int)(now.tv_sec - route->time),
- route->neigh->ifp->name,
- format_address(route->neigh->address),
- nexthop ? " nexthop " : "",
- nexthop ? format_address(nexthop) : "",
- route->installed ? " (installed)" :
- route_feasible(route) ? " (feasible)" : "",
- // -- lorauth --
- reduced_lorauth_token(route->src->cipher));
- }
- static void
- dump_xroute(FILE *out, struct xroute *xroute)
- {
- fprintf(out, "%s%s%s metric %d cipher %c%c%c%c...%c%c (exported)\n",
- format_prefix(xroute->prefix, xroute->plen),
- xroute->src_plen > 0 ? " from " : "",
- xroute->src_plen > 0 ?
- format_prefix(xroute->src_prefix, xroute->src_plen) : "",
- xroute->metric,
- // -- lorauth --
- xroute->cipher[0],xroute->cipher[1],xroute->cipher[2],xroute->cipher[3],
- xroute->cipher[LORAUTH_CIPHER_LEN-2],
- xroute->cipher[LORAUTH_CIPHER_LEN-1]);
- }
- static void
- dump_tables(FILE *out)
- {
- struct neighbour *neigh;
- struct xroute_stream *xroutes;
- struct route_stream *routes;
- fprintf(out, "\n");
- fprintf(out, "My id %s seqno %d\n", format_eui64(myid), myseqno);
- FOR_ALL_NEIGHBOURS(neigh) {
- fprintf(out, "Neighbour %s dev %s reach %04x rxcost %d txcost %d "
- "rtt %s rttcost %d chan %d%s.\n",
- format_address(neigh->address),
- neigh->ifp->name,
- neigh->reach,
- neighbour_rxcost(neigh),
- neigh->txcost,
- format_thousands(neigh->rtt),
- neighbour_rttcost(neigh),
- neigh->ifp->channel,
- if_up(neigh->ifp) ? "" : " (down)");
- }
- xroutes = xroute_stream();
- if(xroutes) {
- while(1) {
- struct xroute *xroute = xroute_stream_next(xroutes);
- if(xroute == NULL) break;
- dump_xroute(out, xroute);
- }
- xroute_stream_done(xroutes);
- }
- routes = route_stream(ROUTE_ALL);
- if(routes) {
- while(1) {
- struct babel_route *route = route_stream_next(routes);
- if(route == NULL) break;
- dump_route(out, route);
- }
- route_stream_done(routes);
- }
- fflush(out);
- }
- int
- reopen_logfile()
- {
- int lfd, rc;
- if(logfile == NULL)
- return 0;
- lfd = open(logfile, O_CREAT | O_WRONLY | O_APPEND, 0644);
- if(lfd < 0)
- return -1;
- fflush(stdout);
- fflush(stderr);
- rc = dup2(lfd, 1);
- if(rc < 0)
- return -1;
- rc = dup2(lfd, 2);
- if(rc < 0)
- return -1;
- if(lfd > 2)
- close(lfd);
- return 1;
- }
|