Annotation of embedaddon/quagga/babeld/babel_main.c, revision 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>