Annotation of embedaddon/quagga/babeld/babel_main.c, revision 1.1.1.1

1.1       misho       1: /*  
                      2:  *  This file is free software: you may copy, redistribute and/or modify it  
                      3:  *  under the terms of the GNU General Public License as published by the  
                      4:  *  Free Software Foundation, either version 2 of the License, or (at your  
                      5:  *  option) any later version.  
                      6:  *  
                      7:  *  This file is distributed in the hope that it will be useful, but  
                      8:  *  WITHOUT ANY WARRANTY; without even the implied warranty of  
                      9:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
                     10:  *  General Public License for more details.  
                     11:  *  
                     12:  *  You should have received a copy of the GNU General Public License  
                     13:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
                     14:  *  
                     15:  * This file incorporates work covered by the following copyright and  
                     16:  * permission notice:  
                     17:  *  
                     18: 
                     19: Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
                     20: 
                     21: Permission is hereby granted, free of charge, to any person obtaining a copy
                     22: of this software and associated documentation files (the "Software"), to deal
                     23: in the Software without restriction, including without limitation the rights
                     24: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     25: copies of the Software, and to permit persons to whom the Software is
                     26: furnished to do so, subject to the following conditions:
                     27: 
                     28: The above copyright notice and this permission notice shall be included in
                     29: all copies or substantial portions of the Software.
                     30: 
                     31: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     32: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     33: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
                     34: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     35: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     36: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     37: THE SOFTWARE.
                     38: */
                     39: 
                     40: /* include zebra library */
                     41: #include <zebra.h>
                     42: #include "getopt.h"
                     43: #include "if.h"
                     44: #include "log.h"
                     45: #include "thread.h"
                     46: #include "privs.h"
                     47: #include "sigevent.h"
                     48: #include "version.h"
                     49: #include "command.h"
                     50: #include "vty.h"
                     51: #include "memory.h"
                     52: 
                     53: #include "babel_main.h"
                     54: #include "babeld.h"
                     55: #include "util.h"
                     56: #include "kernel.h"
                     57: #include "babel_interface.h"
                     58: #include "neighbour.h"
                     59: #include "route.h"
                     60: #include "xroute.h"
                     61: #include "message.h"
                     62: #include "resend.h"
                     63: #include "babel_zebra.h"
                     64: 
                     65: 
                     66: static void babel_init (int argc, char **argv);
                     67: static char *babel_get_progname(char *argv_0);
                     68: static void babel_fail(void);
                     69: static void babel_init_random(void);
                     70: static void babel_replace_by_null(int fd);
                     71: static void babel_init_signals(void);
                     72: static void babel_exit_properly(void);
                     73: static void babel_save_state_file(void);
                     74: 
                     75: 
                     76: struct thread_master *master;     /* quagga's threads handler */
                     77: struct timeval babel_now;         /* current time             */
                     78: 
                     79: unsigned char myid[8];            /* unique id (mac address of an interface) */
                     80: int debug = 0;
                     81: 
                     82: int resend_delay = -1;
                     83: static const char *pidfile = PATH_BABELD_PID;
                     84: 
                     85: const unsigned char zeroes[16] = {0};
                     86: const unsigned char ones[16] =
                     87:     {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                     88:      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
                     89: 
                     90: static const char *state_file = DAEMON_VTY_DIR "/babel-state";
                     91: 
                     92: unsigned char protocol_group[16]; /* babel's link-local multicast address */
                     93: int protocol_port;                /* babel's port */
                     94: int protocol_socket = -1;         /* socket: communicate with others babeld */
                     95: 
                     96: static char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
                     97: static char *babel_config_file = NULL;
                     98: static char *babel_vty_addr = NULL;
                     99: static int babel_vty_port = BABEL_VTY_PORT;
                    100: 
                    101: /* Babeld options. */
                    102: struct option longopts[] =
                    103: {
                    104:     { "daemon",      no_argument,       NULL, 'd'},
                    105:     { "config_file", required_argument, NULL, 'f'},
                    106:     { "pid_file",    required_argument, NULL, 'i'},
                    107:     { "socket",      required_argument, NULL, 'z'},
                    108:     { "help",        no_argument,       NULL, 'h'},
                    109:     { "vty_addr",    required_argument, NULL, 'A'},
                    110:     { "vty_port",    required_argument, NULL, 'P'},
                    111:     { "user",        required_argument, NULL, 'u'},
                    112:     { "group",       required_argument, NULL, 'g'},
                    113:     { "version",     no_argument,       NULL, 'v'},
                    114:     { 0 }
                    115: };
                    116: 
                    117: /* babeld privileges */
                    118: static zebra_capabilities_t _caps_p [] =
                    119: {
                    120:     ZCAP_NET_RAW,
                    121:     ZCAP_BIND
                    122: };
                    123: static struct zebra_privs_t babeld_privs =
                    124: {
                    125: #if defined(QUAGGA_USER)
                    126:     .user = QUAGGA_USER,
                    127: #endif
                    128: #if defined QUAGGA_GROUP
                    129:     .group = QUAGGA_GROUP,
                    130: #endif
                    131: #ifdef VTY_GROUP
                    132:     .vty_group = VTY_GROUP,
                    133: #endif
                    134:     .caps_p = _caps_p,
                    135:     .cap_num_p = 2,
                    136:     .cap_num_i = 0
                    137: };
                    138: 
                    139: 
                    140: int
                    141: main(int argc, char **argv)
                    142: {
                    143:     struct thread thread;
                    144:     /* and print banner too */
                    145:     babel_init(argc, argv);
                    146:     while (thread_fetch (master, &thread)) {
                    147:         thread_call (&thread);
                    148:     }
                    149:     return 0;
                    150: }
                    151: 
                    152: static void
                    153: babel_usage (char *progname, int status)
                    154: {
                    155:   if (status != 0)
                    156:     fprintf (stderr, "Try `%s --help' for more information.\n", progname);
                    157:   else
                    158:     {
                    159:       printf ("Usage : %s [OPTION...]\n\
                    160: Daemon which manages Babel routing protocol.\n\n\
                    161: -d, --daemon       Runs in daemon mode\n\
                    162: -f, --config_file  Set configuration file name\n\
                    163: -i, --pid_file     Set process identifier file name\n\
                    164: -z, --socket       Set path of zebra socket\n\
                    165: -A, --vty_addr     Set vty's bind address\n\
                    166: -P, --vty_port     Set vty's port number\n\
                    167: -u, --user         User to run as\n\
                    168: -g, --group        Group to run as\n\
                    169: -v, --version      Print program version\n\
                    170: -h, --help         Display this help and exit\n\
                    171: \n\
                    172: Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
                    173:     }
                    174:   exit (status);
                    175: }
                    176: 
                    177: /* make initialisations witch don't need infos about kernel(interfaces, etc.) */
                    178: static void
                    179: babel_init(int argc, char **argv)
                    180: {
                    181:     int rc, opt;
                    182:     int do_daemonise = 0;
                    183:     char *progname = NULL;
                    184: 
                    185:     /* Set umask before anything for security */
                    186:     umask (0027);
                    187:     progname = babel_get_progname(argv[0]);
                    188: 
                    189:     /* set default log (lib/log.h) */
                    190:     zlog_default = openzlog(progname, ZLOG_BABEL,
                    191:                             LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
                    192:     /* set log destination as stdout until the config file is read */
                    193:     zlog_set_level(NULL, ZLOG_DEST_STDOUT, LOG_WARNING);
                    194: 
                    195:     babel_init_random();
                    196: 
                    197:     /* set the Babel's default link-local multicast address and Babel's port */
                    198:     parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
                    199:     protocol_port = 6696;
                    200: 
                    201:     /* get options */
                    202:     while(1) {
                    203:         opt = getopt_long(argc, argv, "df:i:z:hA:P:u:g:v", longopts, 0);
                    204:         if(opt < 0)
                    205:             break;
                    206: 
                    207:         switch(opt) {
                    208:             case 0:
                    209:                 break;
                    210:             case 'd':
                    211:                 do_daemonise = -1;
                    212:                 break;
                    213:             case 'f':
                    214:                 babel_config_file = optarg;
                    215:                 break;
                    216:             case 'i':
                    217:                 pidfile = optarg;
                    218:                 break;
                    219:             case 'z':
                    220:                 zclient_serv_path_set (optarg);
                    221:                 break;
                    222:             case 'A':
                    223:                 babel_vty_addr = optarg;
                    224:                 break;
                    225:             case 'P':
                    226:                 babel_vty_port = atoi (optarg);
                    227:                 if (babel_vty_port <= 0 || babel_vty_port > 0xffff)
                    228:                     babel_vty_port = BABEL_VTY_PORT;
                    229:                 break;
                    230:             case 'u':
                    231:                 babeld_privs.user = optarg;
                    232:                 break;
                    233:             case 'g':
                    234:                 babeld_privs.group = optarg;
                    235:                 break;
                    236:             case 'v':
                    237:                 print_version (progname);
                    238:                 exit (0);
                    239:                 break;
                    240:             case 'h':
                    241:                 babel_usage (progname, 0);
                    242:                 break;
                    243:             default:
                    244:                 babel_usage (progname, 1);
                    245:                 break;
                    246:         }
                    247:     }
                    248: 
                    249:     /* create the threads handler */
                    250:     master = thread_master_create ();
                    251: 
                    252:     /* Library inits. */
                    253:     zprivs_init (&babeld_privs);
                    254:     babel_init_signals();
                    255:     cmd_init (1);
                    256:     vty_init (master);
                    257:     memory_init ();
                    258: 
                    259:     resend_delay = BABEL_DEFAULT_RESEND_DELAY;
                    260: 
                    261:     babel_replace_by_null(STDIN_FILENO);
                    262: 
                    263:     if (do_daemonise && daemonise() < 0) {
                    264:         zlog_err("daemonise: %s", safe_strerror(errno));
                    265:         exit (1);
                    266:     }
                    267: 
                    268:     /* write pid file */
                    269:     if (pid_output(pidfile) < 0) {
                    270:         zlog_err("error while writing pidfile");
                    271:         exit (1);
                    272:     };
                    273: 
                    274:     /* init some quagga's dependencies, and babeld's commands */
                    275:     babeld_quagga_init();
                    276:     /* init zebra client's structure and it's commands */
                    277:     /* this replace kernel_setup && kernel_setup_socket */
                    278:     babelz_zebra_init ();
                    279: 
                    280:     /* Sort all installed commands. */
                    281:     sort_node ();
                    282: 
                    283:     /* Get zebra configuration file. */
                    284:     zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
                    285:     vty_read_config (babel_config_file, babel_config_default);
                    286: 
                    287:     /* Create VTY socket */
                    288:     vty_serv_sock (babel_vty_addr, babel_vty_port, BABEL_VTYSH_PATH);
                    289: 
                    290:     /* init buffer */
                    291:     rc = resize_receive_buffer(1500);
                    292:     if(rc < 0)
                    293:         babel_fail();
                    294: 
                    295:     schedule_neighbours_check(5000, 1);
                    296: 
                    297:     zlog_notice ("BABELd %s starting: vty@%d", BABEL_VERSION, babel_vty_port);
                    298: }
                    299: 
                    300: /* return the progname (without path, example: "./x/progname" --> "progname") */
                    301: static char *
                    302: babel_get_progname(char *argv_0) {
                    303:     char *p = strrchr (argv_0, '/');
                    304:     return (p ? ++p : argv_0);
                    305: }
                    306: 
                    307: static void
                    308: babel_fail(void)
                    309: {
                    310:     exit(1);
                    311: }
                    312: 
                    313: /* initialize random value, and set 'babel_now' by the way. */
                    314: static void
                    315: babel_init_random(void)
                    316: {
                    317:     gettime(&babel_now);
                    318:     int rc;
                    319:     unsigned int seed;
                    320: 
                    321:     rc = read_random_bytes(&seed, sizeof(seed));
                    322:     if(rc < 0) {
                    323:         zlog_err("read(random): %s", safe_strerror(errno));
                    324:         seed = 42;
                    325:     }
                    326: 
                    327:     seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
                    328:     srandom(seed);
                    329: }
                    330: 
                    331: /*
                    332:  close fd, and replace it by "/dev/null"
                    333:  exit if error
                    334:  */
                    335: static void
                    336: babel_replace_by_null(int fd)
                    337: {
                    338:     int fd_null;
                    339:     int rc;
                    340: 
                    341:     fd_null = open("/dev/null", O_RDONLY);
                    342:     if(fd_null < 0) {
                    343:         zlog_err("open(null): %s", safe_strerror(errno));
                    344:         exit(1);
                    345:     }
                    346: 
                    347:     rc = dup2(fd_null, fd);
                    348:     if(rc < 0) {
                    349:         zlog_err("dup2(null, 0): %s", safe_strerror(errno));
                    350:         exit(1);
                    351:     }
                    352: 
                    353:     close(fd_null);
                    354: }
                    355: 
                    356: /*
                    357:  Load the state file: check last babeld's running state, usefull in case of
                    358:  "/etc/init.d/babeld restart"
                    359:  */
                    360: void
                    361: babel_load_state_file(void)
                    362: {
                    363:     int fd;
                    364:     int rc;
                    365: 
                    366:     fd = open(state_file, O_RDONLY);
                    367:     if(fd < 0 && errno != ENOENT)
                    368:         zlog_err("open(babel-state: %s)", safe_strerror(errno));
                    369:     rc = unlink(state_file);
                    370:     if(fd >= 0 && rc < 0) {
                    371:         zlog_err("unlink(babel-state): %s", safe_strerror(errno));
                    372:         /* If we couldn't unlink it, it's probably stale. */
                    373:         close(fd);
                    374:         fd = -1;
                    375:     }
                    376:     if(fd >= 0) {
                    377:         char buf[100];
                    378:         char buf2[100];
                    379:         int s;
                    380:         long t;
                    381:         rc = read(fd, buf, 99);
                    382:         if(rc < 0) {
                    383:             zlog_err("read(babel-state): %s", safe_strerror(errno));
                    384:         } else {
                    385:             buf[rc] = '\0';
                    386:             rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
                    387:             if(rc == 3 && s >= 0 && s <= 0xFFFF) {
                    388:                 unsigned char sid[8];
                    389:                 rc = parse_eui64(buf2, sid);
                    390:                 if(rc < 0) {
                    391:                     zlog_err("Couldn't parse babel-state.");
                    392:                 } else {
                    393:                     struct timeval realnow;
                    394:                     debugf(BABEL_DEBUG_COMMON,
                    395:                            "Got %s %d %ld from babel-state.",
                    396:                            format_eui64(sid), s, t);
                    397:                     gettimeofday(&realnow, NULL);
                    398:                     if(memcmp(sid, myid, 8) == 0)
                    399:                         myseqno = seqno_plus(s, 1);
                    400:                     else
                    401:                         zlog_err("ID mismatch in babel-state. id=%s; old=%s",
                    402:                                  format_eui64(myid),
                    403:                                  format_eui64(sid));
                    404:                 }
                    405:             } else {
                    406:                 zlog_err("Couldn't parse babel-state.");
                    407:             }
                    408:         }
                    409:         close(fd);
                    410:         fd = -1;
                    411:     }
                    412: }
                    413: 
                    414: static void
                    415: babel_sigexit(void)
                    416: {
                    417:     zlog_notice("Terminating on signal");
                    418: 
                    419:     babel_exit_properly();
                    420: }
                    421: 
                    422: static void
                    423: babel_sigusr1 (void)
                    424: {
                    425:     zlog_rotate (NULL);
                    426: }
                    427: 
                    428: static void
                    429: babel_init_signals(void)
                    430: {
                    431:     static struct quagga_signal_t babel_signals[] =
                    432:     {
                    433:         {
                    434:             .signal = SIGUSR1,
                    435:             .handler = &babel_sigusr1,
                    436:         },
                    437:         {
                    438:             .signal = SIGINT,
                    439:             .handler = &babel_sigexit,
                    440:         },
                    441:         {
                    442:             .signal = SIGTERM,
                    443:             .handler = &babel_sigexit,
                    444:         },
                    445:     };
                    446: 
                    447:     signal_init (master, Q_SIGC(babel_signals), babel_signals);
                    448: }
                    449: 
                    450: static void
                    451: babel_exit_properly(void)
                    452: {
                    453:     debugf(BABEL_DEBUG_COMMON, "Exiting...");
                    454:     usleep(roughly(10000));
                    455:     gettime(&babel_now);
                    456: 
                    457:     /* Uninstall and flush all routes. */
                    458:     debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
                    459:     flush_all_routes();
                    460:     babel_interface_close_all();
                    461:     babel_zebra_close_connexion();
                    462:     babel_save_state_file();
                    463:     debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
                    464:     if(pidfile)
                    465:         unlink(pidfile);
                    466:     debugf(BABEL_DEBUG_COMMON, "Done.");
                    467: 
                    468:     exit(0);
                    469: }
                    470: 
                    471: static void
                    472: babel_save_state_file(void)
                    473: {
                    474:     int fd;
                    475:     int rc;
                    476: 
                    477:     debugf(BABEL_DEBUG_COMMON, "Save state file.");
                    478:     fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
                    479:     if(fd < 0) {
                    480:         zlog_err("creat(babel-state): %s", safe_strerror(errno));
                    481:         unlink(state_file);
                    482:     } else {
                    483:         struct timeval realnow;
                    484:         char buf[100];
                    485:         gettimeofday(&realnow, NULL);
                    486:         rc = snprintf(buf, 100, "%s %d %ld\n",
                    487:                       format_eui64(myid), (int)myseqno,
                    488:                       (long)realnow.tv_sec);
                    489:         if(rc < 0 || rc >= 100) {
                    490:             zlog_err("write(babel-state): overflow.");
                    491:             unlink(state_file);
                    492:         } else {
                    493:             rc = write(fd, buf, rc);
                    494:             if(rc < 0) {
                    495:                 zlog_err("write(babel-state): %s", safe_strerror(errno));
                    496:                 unlink(state_file);
                    497:             }
                    498:             fsync(fd);
                    499:         }
                    500:         close(fd);
                    501:     }
                    502: }
                    503: 
                    504: void
                    505: show_babel_main_configuration (struct vty *vty)
                    506: {
                    507:     vty_out(vty,
                    508:             "pid file                = %s%s"
                    509:             "state file              = %s%s"
                    510:             "configuration file      = %s%s"
                    511:             "protocol informations:%s"
                    512:             "  multicast address     = %s%s"
                    513:             "  port                  = %d%s"
                    514:             "vty address             = %s%s"
                    515:             "vty port                = %d%s"
                    516:             "id                      = %s%s"
                    517:             "allow_duplicates        = %s%s"
                    518:             "kernel_metric           = %d%s",
                    519:             pidfile, VTY_NEWLINE,
                    520:             state_file, VTY_NEWLINE,
                    521:             babel_config_file ? babel_config_file : babel_config_default,
                    522:             VTY_NEWLINE,
                    523:             VTY_NEWLINE,
                    524:             format_address(protocol_group), VTY_NEWLINE,
                    525:             protocol_port, VTY_NEWLINE,
                    526:             babel_vty_addr ? babel_vty_addr : "None",
                    527:             VTY_NEWLINE,
                    528:             babel_vty_port, VTY_NEWLINE,
                    529:             format_eui64(myid), VTY_NEWLINE,
                    530:             format_bool(allow_duplicates), VTY_NEWLINE,
                    531:             kernel_metric, VTY_NEWLINE);
                    532: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>