File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / sysdep / unix / main.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 16:03:56 2019 UTC (5 years, 5 months ago) by misho
Branches: bird2, MAIN
CVS tags: v2_0_7p0, HEAD
bird2 ver 2.0.7

    1: /*
    2:  *	BIRD Internet Routing Daemon -- Unix Entry Point
    3:  *
    4:  *	(c) 1998--2000 Martin Mares <mj@ucw.cz>
    5:  *
    6:  *	Can be freely distributed and used under the terms of the GNU GPL.
    7:  */
    8: 
    9: #undef LOCAL_DEBUG
   10: 
   11: #ifndef _GNU_SOURCE
   12: #define _GNU_SOURCE
   13: #endif
   14: 
   15: #include <stdio.h>
   16: #include <stdlib.h>
   17: #include <fcntl.h>
   18: #include <unistd.h>
   19: #include <signal.h>
   20: #include <pwd.h>
   21: #include <grp.h>
   22: #include <sys/stat.h>
   23: #include <libgen.h>
   24: 
   25: #include "nest/bird.h"
   26: #include "lib/lists.h"
   27: #include "lib/resource.h"
   28: #include "lib/socket.h"
   29: #include "lib/event.h"
   30: #include "lib/timer.h"
   31: #include "lib/string.h"
   32: #include "nest/route.h"
   33: #include "nest/protocol.h"
   34: #include "nest/iface.h"
   35: #include "nest/cli.h"
   36: #include "nest/locks.h"
   37: #include "conf/conf.h"
   38: #include "filter/filter.h"
   39: #include "filter/data.h"
   40: 
   41: #include "unix.h"
   42: #include "krt.h"
   43: 
   44: /*
   45:  *	Debugging
   46:  */
   47: 
   48: void
   49: async_dump(void)
   50: {
   51:   debug("INTERNAL STATE DUMP\n\n");
   52: 
   53:   rdump(&root_pool);
   54:   sk_dump_all();
   55:   // XXXX tm_dump_all();
   56:   if_dump_all();
   57:   neigh_dump_all();
   58:   rta_dump_all();
   59:   rt_dump_all();
   60:   protos_dump_all();
   61: 
   62:   debug("\n");
   63: }
   64: 
   65: /*
   66:  *	Dropping privileges
   67:  */
   68: 
   69: #ifdef CONFIG_RESTRICTED_PRIVILEGES
   70: #include CONFIG_INCLUDE_SYSPRIV_H
   71: #else
   72: 
   73: static inline void
   74: drop_uid(uid_t uid UNUSED)
   75: {
   76:   die("Cannot change user on this platform");
   77: }
   78: 
   79: #endif
   80: 
   81: static inline void
   82: drop_gid(gid_t gid)
   83: {
   84:   if (setgid(gid) < 0)
   85:     die("setgid: %m");
   86: 
   87:   if (setgroups(0, NULL) < 0)
   88:     die("setgroups: %m");
   89: }
   90: 
   91: /*
   92:  *	Reading the Configuration
   93:  */
   94: 
   95: #ifdef PATH_IPROUTE_DIR
   96: 
   97: static inline void
   98: add_num_const(char *name, int val)
   99: {
  100:   struct f_val *v = cfg_alloc(sizeof(struct f_val));
  101:   *v = (struct f_val) { .type = T_INT, .val.i = val };
  102:   cf_define_symbol(cf_get_symbol(name), SYM_CONSTANT | T_INT, val, v);
  103: }
  104: 
  105: /* the code of read_iproute_table() is based on
  106:    rtnl_tab_initialize() from iproute2 package */
  107: static void
  108: read_iproute_table(char *file, char *prefix, int max)
  109: {
  110:   char buf[512], namebuf[512];
  111:   char *name;
  112:   int val;
  113:   FILE *fp;
  114: 
  115:   strcpy(namebuf, prefix);
  116:   name = namebuf + strlen(prefix);
  117: 
  118:   fp = fopen(file, "r");
  119:   if (!fp)
  120:     return;
  121: 
  122:   while (fgets(buf, sizeof(buf), fp))
  123:   {
  124:     char *p = buf;
  125: 
  126:     while (*p == ' ' || *p == '\t')
  127:       p++;
  128: 
  129:     if (*p == '#' || *p == '\n' || *p == 0)
  130:       continue;
  131: 
  132:     if (sscanf(p, "0x%x %s\n", &val, name) != 2 &&
  133: 	sscanf(p, "0x%x %s #", &val, name) != 2 &&
  134: 	sscanf(p, "%d %s\n", &val, name) != 2 &&
  135: 	sscanf(p, "%d %s #", &val, name) != 2)
  136:       continue;
  137: 
  138:     if (val < 0 || val > max)
  139:       continue;
  140: 
  141:     for(p = name; *p; p++)
  142:       if ((*p < 'a' || *p > 'z') && (*p < '0' || *p > '9') && (*p != '_'))
  143: 	*p = '_';
  144: 
  145:     add_num_const(namebuf, val);
  146:   }
  147: 
  148:   fclose(fp);
  149: }
  150: 
  151: #endif // PATH_IPROUTE_DIR
  152: 
  153: 
  154: static char *config_name = PATH_CONFIG_FILE;
  155: 
  156: static int
  157: cf_read(byte *dest, uint len, int fd)
  158: {
  159:   int l = read(fd, dest, len);
  160:   if (l < 0)
  161:     cf_error("Read error");
  162:   return l;
  163: }
  164: 
  165: void
  166: sysdep_preconfig(struct config *c)
  167: {
  168:   init_list(&c->logfiles);
  169: 
  170:   c->latency_limit = UNIX_DEFAULT_LATENCY_LIMIT;
  171:   c->watchdog_warning = UNIX_DEFAULT_WATCHDOG_WARNING;
  172: 
  173: #ifdef PATH_IPROUTE_DIR
  174:   read_iproute_table(PATH_IPROUTE_DIR "/rt_protos", "ipp_", 256);
  175:   read_iproute_table(PATH_IPROUTE_DIR "/rt_realms", "ipr_", 256);
  176:   read_iproute_table(PATH_IPROUTE_DIR "/rt_scopes", "ips_", 256);
  177:   read_iproute_table(PATH_IPROUTE_DIR "/rt_tables", "ipt_", 256);
  178: #endif
  179: }
  180: 
  181: int
  182: sysdep_commit(struct config *new, struct config *old UNUSED)
  183: {
  184:   log_switch(0, &new->logfiles, new->syslog_name);
  185:   return 0;
  186: }
  187: 
  188: static int
  189: unix_read_config(struct config **cp, char *name)
  190: {
  191:   struct config *conf = config_alloc(name);
  192:   int ret;
  193: 
  194:   *cp = conf;
  195:   conf->file_fd = open(name, O_RDONLY);
  196:   if (conf->file_fd < 0)
  197:     return 0;
  198:   cf_read_hook = cf_read;
  199:   ret = config_parse(conf);
  200:   close(conf->file_fd);
  201:   return ret;
  202: }
  203: 
  204: static struct config *
  205: read_config(void)
  206: {
  207:   struct config *conf;
  208: 
  209:   if (!unix_read_config(&conf, config_name))
  210:     {
  211:       if (conf->err_msg)
  212: 	die("%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
  213:       else
  214: 	die("Unable to open configuration file %s: %m", config_name);
  215:     }
  216: 
  217:   return conf;
  218: }
  219: 
  220: void
  221: async_config(void)
  222: {
  223:   struct config *conf;
  224: 
  225:   log(L_INFO "Reconfiguration requested by SIGHUP");
  226:   if (!unix_read_config(&conf, config_name))
  227:     {
  228:       if (conf->err_msg)
  229: 	log(L_ERR "%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
  230:       else
  231: 	log(L_ERR "Unable to open configuration file %s: %m", config_name);
  232:       config_free(conf);
  233:     }
  234:   else
  235:     config_commit(conf, RECONFIG_HARD, 0);
  236: }
  237: 
  238: static struct config *
  239: cmd_read_config(char *name)
  240: {
  241:   struct config *conf;
  242: 
  243:   if (!name)
  244:     name = config_name;
  245: 
  246:   cli_msg(-2, "Reading configuration from %s", name);
  247:   if (!unix_read_config(&conf, name))
  248:     {
  249:       if (conf->err_msg)
  250: 	cli_msg(8002, "%s:%d:%d %s", conf->err_file_name, conf->err_lino, conf->err_chno, conf->err_msg);
  251:       else
  252: 	cli_msg(8002, "%s: %m", name);
  253:       config_free(conf);
  254:       conf = NULL;
  255:     }
  256: 
  257:   return conf;
  258: }
  259: 
  260: void
  261: cmd_check_config(char *name)
  262: {
  263:   struct config *conf = cmd_read_config(name);
  264:   if (!conf)
  265:     return;
  266: 
  267:   cli_msg(20, "Configuration OK");
  268:   config_free(conf);
  269: }
  270: 
  271: static void
  272: cmd_reconfig_msg(int r)
  273: {
  274:   switch (r)
  275:     {
  276:     case CONF_DONE:	cli_msg( 3, "Reconfigured"); break;
  277:     case CONF_PROGRESS: cli_msg( 4, "Reconfiguration in progress"); break;
  278:     case CONF_QUEUED:	cli_msg( 5, "Reconfiguration already in progress, queueing new config"); break;
  279:     case CONF_UNQUEUED:	cli_msg(17, "Reconfiguration already in progress, removing queued config"); break;
  280:     case CONF_CONFIRM:	cli_msg(18, "Reconfiguration confirmed"); break;
  281:     case CONF_SHUTDOWN:	cli_msg( 6, "Reconfiguration ignored, shutting down"); break;
  282:     case CONF_NOTHING:	cli_msg(19, "Nothing to do"); break;
  283:     default:		break;
  284:     }
  285: }
  286: 
  287: /* Hack for scheduled undo notification */
  288: cli *cmd_reconfig_stored_cli;
  289: 
  290: void
  291: cmd_reconfig_undo_notify(void)
  292: {
  293:   if (cmd_reconfig_stored_cli)
  294:     {
  295:       cli *c = cmd_reconfig_stored_cli;
  296:       cli_printf(c, CLI_ASYNC_CODE, "Config timeout expired, starting undo");
  297:       cli_write_trigger(c);
  298:     }
  299: }
  300: 
  301: void
  302: cmd_reconfig(char *name, int type, uint timeout)
  303: {
  304:   if (cli_access_restricted())
  305:     return;
  306: 
  307:   struct config *conf = cmd_read_config(name);
  308:   if (!conf)
  309:     return;
  310: 
  311:   int r = config_commit(conf, type, timeout);
  312: 
  313:   if ((r >= 0) && (timeout > 0))
  314:     {
  315:       cmd_reconfig_stored_cli = this_cli;
  316:       cli_msg(-22, "Undo scheduled in %d s", timeout);
  317:     }
  318: 
  319:   cmd_reconfig_msg(r);
  320: }
  321: 
  322: void
  323: cmd_reconfig_confirm(void)
  324: {
  325:   if (cli_access_restricted())
  326:     return;
  327: 
  328:   int r = config_confirm();
  329:   cmd_reconfig_msg(r);
  330: }
  331: 
  332: void
  333: cmd_reconfig_undo(void)
  334: {
  335:   if (cli_access_restricted())
  336:     return;
  337: 
  338:   cli_msg(-21, "Undo requested");
  339: 
  340:   int r = config_undo();
  341:   cmd_reconfig_msg(r);
  342: }
  343: 
  344: void
  345: cmd_reconfig_status(void)
  346: {
  347:   int s = config_status();
  348:   btime t = config_timer_status();
  349: 
  350:   switch (s)
  351:   {
  352:   case CONF_DONE:	cli_msg(-3, "Daemon is up and running"); break;
  353:   case CONF_PROGRESS:	cli_msg(-4, "Reconfiguration in progress"); break;
  354:   case CONF_QUEUED:	cli_msg(-5, "Reconfiguration in progress, next one enqueued"); break;
  355:   case CONF_SHUTDOWN:	cli_msg(-6, "Shutdown in progress"); break;
  356:   default:		break;
  357:   }
  358: 
  359:   if (t >= 0)
  360:     cli_msg(-22, "Configuration unconfirmed, undo in %t s", t);
  361: 
  362:   cli_msg(0, "");
  363: }
  364: 
  365: 
  366: /*
  367:  *	Command-Line Interface
  368:  */
  369: 
  370: static sock *cli_sk;
  371: static char *path_control_socket = PATH_CONTROL_SOCKET;
  372: 
  373: 
  374: static void
  375: cli_write(cli *c)
  376: {
  377:   sock *s = c->priv;
  378: 
  379:   while (c->tx_pos)
  380:     {
  381:       struct cli_out *o = c->tx_pos;
  382: 
  383:       int len = o->wpos - o->outpos;
  384:       s->tbuf = o->outpos;
  385:       o->outpos = o->wpos;
  386: 
  387:       if (sk_send(s, len) <= 0)
  388: 	return;
  389: 
  390:       c->tx_pos = o->next;
  391:     }
  392: 
  393:   /* Everything is written */
  394:   s->tbuf = NULL;
  395:   cli_written(c);
  396: }
  397: 
  398: void
  399: cli_write_trigger(cli *c)
  400: {
  401:   sock *s = c->priv;
  402: 
  403:   if (s->tbuf == NULL)
  404:     cli_write(c);
  405: }
  406: 
  407: static void
  408: cli_tx(sock *s)
  409: {
  410:   cli_write(s->data);
  411: }
  412: 
  413: int
  414: cli_get_command(cli *c)
  415: {
  416:   sock *s = c->priv;
  417:   byte *t = c->rx_aux ? : s->rbuf;
  418:   byte *tend = s->rpos;
  419:   byte *d = c->rx_pos;
  420:   byte *dend = c->rx_buf + CLI_RX_BUF_SIZE - 2;
  421: 
  422:   while (t < tend)
  423:     {
  424:       if (*t == '\r')
  425: 	t++;
  426:       else if (*t == '\n')
  427: 	{
  428: 	  t++;
  429: 	  c->rx_pos = c->rx_buf;
  430: 	  c->rx_aux = t;
  431: 	  *d = 0;
  432: 	  return (d < dend) ? 1 : -1;
  433: 	}
  434:       else if (d < dend)
  435: 	*d++ = *t++;
  436:     }
  437:   c->rx_aux = s->rpos = s->rbuf;
  438:   c->rx_pos = d;
  439:   return 0;
  440: }
  441: 
  442: static int
  443: cli_rx(sock *s, uint size UNUSED)
  444: {
  445:   cli_kick(s->data);
  446:   return 0;
  447: }
  448: 
  449: static void
  450: cli_err(sock *s, int err)
  451: {
  452:   if (config->cli_debug)
  453:     {
  454:       if (err)
  455: 	log(L_INFO "CLI connection dropped: %s", strerror(err));
  456:       else
  457: 	log(L_INFO "CLI connection closed");
  458:     }
  459:   cli_free(s->data);
  460: }
  461: 
  462: static int
  463: cli_connect(sock *s, uint size UNUSED)
  464: {
  465:   cli *c;
  466: 
  467:   if (config->cli_debug)
  468:     log(L_INFO "CLI connect");
  469:   s->rx_hook = cli_rx;
  470:   s->tx_hook = cli_tx;
  471:   s->err_hook = cli_err;
  472:   s->data = c = cli_new(s);
  473:   s->pool = c->pool;		/* We need to have all the socket buffers allocated in the cli pool */
  474:   s->fast_rx = 1;
  475:   c->rx_pos = c->rx_buf;
  476:   c->rx_aux = NULL;
  477:   rmove(s, c->pool);
  478:   return 1;
  479: }
  480: 
  481: static void
  482: cli_init_unix(uid_t use_uid, gid_t use_gid)
  483: {
  484:   sock *s;
  485: 
  486:   cli_init();
  487:   s = cli_sk = sk_new(cli_pool);
  488:   s->type = SK_UNIX_PASSIVE;
  489:   s->rx_hook = cli_connect;
  490:   s->rbsize = 1024;
  491:   s->fast_rx = 1;
  492: 
  493:   /* Return value intentionally ignored */
  494:   unlink(path_control_socket);
  495: 
  496:   if (sk_open_unix(s, path_control_socket) < 0)
  497:     die("Cannot create control socket %s: %m", path_control_socket);
  498: 
  499:   if (use_uid || use_gid)
  500:     if (chown(path_control_socket, use_uid, use_gid) < 0)
  501:       die("chown: %m");
  502: 
  503:   if (chmod(path_control_socket, 0660) < 0)
  504:     die("chmod: %m");
  505: }
  506: 
  507: /*
  508:  *	PID file
  509:  */
  510: 
  511: static char *pid_file;
  512: static int pid_fd;
  513: 
  514: static inline void
  515: open_pid_file(void)
  516: {
  517:   if (!pid_file)
  518:     return;
  519: 
  520:   pid_fd = open(pid_file, O_WRONLY|O_CREAT, 0664);
  521:   if (pid_fd < 0)
  522:     die("Cannot create PID file %s: %m", pid_file);
  523: }
  524: 
  525: static inline void
  526: write_pid_file(void)
  527: {
  528:   int pl, rv;
  529:   char ps[24];
  530: 
  531:   if (!pid_file)
  532:     return;
  533: 
  534:   /* We don't use PID file for uniqueness, so no need for locking */
  535: 
  536:   pl = bsnprintf(ps, sizeof(ps), "%ld\n", (s64) getpid());
  537:   if (pl < 0)
  538:     bug("PID buffer too small");
  539: 
  540:   rv = ftruncate(pid_fd, 0);
  541:   if (rv < 0)
  542:     die("fruncate: %m");
  543: 
  544:   rv = write(pid_fd, ps, pl);
  545:   if(rv < 0)
  546:     die("write: %m");
  547: 
  548:   close(pid_fd);
  549: }
  550: 
  551: static inline void
  552: unlink_pid_file(void)
  553: {
  554:   if (pid_file)
  555:     unlink(pid_file);
  556: }
  557: 
  558: 
  559: /*
  560:  *	Shutdown
  561:  */
  562: 
  563: void
  564: cmd_shutdown(void)
  565: {
  566:   if (cli_access_restricted())
  567:     return;
  568: 
  569:   cli_msg(7, "Shutdown requested");
  570:   order_shutdown(0);
  571: }
  572: 
  573: void
  574: async_shutdown(void)
  575: {
  576:   DBG("Shutting down...\n");
  577:   order_shutdown(0);
  578: }
  579: 
  580: void
  581: sysdep_shutdown_done(void)
  582: {
  583:   unlink_pid_file();
  584:   unlink(path_control_socket);
  585:   log_msg(L_FATAL "Shutdown completed");
  586:   exit(0);
  587: }
  588: 
  589: void
  590: cmd_graceful_restart(void)
  591: {
  592:   if (cli_access_restricted())
  593:     return;
  594: 
  595:   cli_msg(25, "Graceful restart requested");
  596:   order_shutdown(1);
  597: }
  598: 
  599: 
  600: /*
  601:  *	Signals
  602:  */
  603: 
  604: volatile sig_atomic_t async_config_flag;
  605: volatile sig_atomic_t async_dump_flag;
  606: volatile sig_atomic_t async_shutdown_flag;
  607: 
  608: static void
  609: handle_sighup(int sig UNUSED)
  610: {
  611:   DBG("Caught SIGHUP...\n");
  612:   async_config_flag = 1;
  613: }
  614: 
  615: static void
  616: handle_sigusr(int sig UNUSED)
  617: {
  618:   DBG("Caught SIGUSR...\n");
  619:   async_dump_flag = 1;
  620: }
  621: 
  622: static void
  623: handle_sigterm(int sig UNUSED)
  624: {
  625:   DBG("Caught SIGTERM...\n");
  626:   async_shutdown_flag = 1;
  627: }
  628: 
  629: void watchdog_sigalrm(int sig UNUSED);
  630: 
  631: static void
  632: signal_init(void)
  633: {
  634:   struct sigaction sa;
  635: 
  636:   bzero(&sa, sizeof(sa));
  637:   sa.sa_handler = handle_sigusr;
  638:   sa.sa_flags = SA_RESTART;
  639:   sigaction(SIGUSR1, &sa, NULL);
  640:   sa.sa_handler = handle_sighup;
  641:   sa.sa_flags = SA_RESTART;
  642:   sigaction(SIGHUP, &sa, NULL);
  643:   sa.sa_handler = handle_sigterm;
  644:   sa.sa_flags = SA_RESTART;
  645:   sigaction(SIGTERM, &sa, NULL);
  646:   sa.sa_handler = watchdog_sigalrm;
  647:   sa.sa_flags = 0;
  648:   sigaction(SIGALRM, &sa, NULL);
  649:   signal(SIGPIPE, SIG_IGN);
  650: }
  651: 
  652: /*
  653:  *	Parsing of command-line arguments
  654:  */
  655: 
  656: static char *opt_list = "bc:dD:ps:P:u:g:flRh";
  657: static int parse_and_exit;
  658: char *bird_name;
  659: static char *use_user;
  660: static char *use_group;
  661: static int run_in_foreground = 0;
  662: 
  663: static void
  664: display_usage(void)
  665: {
  666:   fprintf(stderr, "Usage: %s [--version] [--help] [-c <config-file>] [OPTIONS]\n", bird_name);
  667: }
  668: 
  669: static void
  670: display_help(void)
  671: {
  672:   display_usage();
  673: 
  674:   fprintf(stderr,
  675:     "\n"
  676:     "Options: \n"
  677:     "  -c <config-file>     Use given configuration file instead of\n"
  678:     "                       "  PATH_CONFIG_FILE "\n"
  679:     "  -d                   Enable debug messages and run bird in foreground\n"
  680:     "  -D <debug-file>      Log debug messages to given file instead of stderr\n"
  681:     "  -f                   Run bird in foreground\n"
  682:     "  -g <group>           Use given group ID\n"
  683:     "  -h, --help           Display this information\n"
  684:     "  -l                   Look for a configuration file and a control socket\n"
  685:     "                       in the current working directory\n"
  686:     "  -p                   Test configuration file and exit without start\n"
  687:     "  -P <pid-file>        Create a PID file with given filename\n"
  688:     "  -R                   Apply graceful restart recovery after start\n"
  689:     "  -s <control-socket>  Use given filename for a control socket\n"
  690:     "  -u <user>            Drop privileges and use given user ID\n"
  691:     "  --version            Display version of BIRD\n");
  692: 
  693:   exit(0);
  694: }
  695: 
  696: static void
  697: display_version(void)
  698: {
  699:   fprintf(stderr, "BIRD version " BIRD_VERSION "\n");
  700:   exit(0);
  701: }
  702: 
  703: static inline char *
  704: get_bird_name(char *s, char *def)
  705: {
  706:   char *t;
  707:   if (!s)
  708:     return def;
  709:   t = strrchr(s, '/');
  710:   if (!t)
  711:     return s;
  712:   if (!t[1])
  713:     return def;
  714:   return t+1;
  715: }
  716: 
  717: static inline uid_t
  718: get_uid(const char *s)
  719: {
  720:   struct passwd *pw;
  721:   char *endptr;
  722:   long int rv;
  723: 
  724:   if (!s)
  725:     return 0;
  726: 
  727:   errno = 0;
  728:   rv = strtol(s, &endptr, 10);
  729: 
  730:   if (!errno && !*endptr)
  731:     return rv;
  732: 
  733:   pw = getpwnam(s);
  734:   if (!pw)
  735:     die("Cannot find user '%s'", s);
  736: 
  737:   return pw->pw_uid;
  738: }
  739: 
  740: static inline gid_t
  741: get_gid(const char *s)
  742: {
  743:   struct group *gr;
  744:   char *endptr;
  745:   long int rv;
  746: 
  747:   if (!s)
  748:     return 0;
  749: 
  750:   errno = 0;
  751:   rv = strtol(s, &endptr, 10);
  752: 
  753:   if (!errno && !*endptr)
  754:     return rv;
  755: 
  756:   gr = getgrnam(s);
  757:   if (!gr)
  758:     die("Cannot find group '%s'", s);
  759: 
  760:   return gr->gr_gid;
  761: }
  762: 
  763: static void
  764: parse_args(int argc, char **argv)
  765: {
  766:   int config_changed = 0;
  767:   int socket_changed = 0;
  768:   int c;
  769: 
  770:   bird_name = get_bird_name(argv[0], "bird");
  771:   if (argc == 2)
  772:     {
  773:       if (!strcmp(argv[1], "--version"))
  774: 	display_version();
  775:       if (!strcmp(argv[1], "--help"))
  776: 	display_help();
  777:     }
  778:   while ((c = getopt(argc, argv, opt_list)) >= 0)
  779:     switch (c)
  780:       {
  781:       case 'c':
  782: 	config_name = optarg;
  783: 	config_changed = 1;
  784: 	break;
  785:       case 'd':
  786: 	log_init_debug("");
  787: 	run_in_foreground = 1;
  788: 	break;
  789:       case 'D':
  790: 	log_init_debug(optarg);
  791: 	break;
  792:       case 'p':
  793: 	parse_and_exit = 1;
  794: 	break;
  795:       case 's':
  796: 	path_control_socket = optarg;
  797: 	socket_changed = 1;
  798: 	break;
  799:       case 'P':
  800: 	pid_file = optarg;
  801: 	break;
  802:       case 'u':
  803: 	use_user = optarg;
  804: 	break;
  805:       case 'g':
  806: 	use_group = optarg;
  807: 	break;
  808:       case 'f':
  809: 	run_in_foreground = 1;
  810: 	break;
  811:       case 'l':
  812: 	if (!config_changed)
  813: 	  config_name = xbasename(config_name);
  814: 	if (!socket_changed)
  815: 	  path_control_socket = xbasename(path_control_socket);
  816: 	break;
  817:       case 'R':
  818: 	graceful_restart_recovery();
  819: 	break;
  820:       case 'h':
  821: 	display_help();
  822: 	break;
  823:       default:
  824: 	fputc('\n', stderr);
  825: 	display_usage();
  826: 	exit(1);
  827:       }
  828:   if (optind < argc)
  829:    {
  830:      display_usage();
  831:      exit(1);
  832:    }
  833: }
  834: 
  835: /*
  836:  *	Hic Est main()
  837:  */
  838: 
  839: int
  840: main(int argc, char **argv)
  841: {
  842: #ifdef HAVE_LIBDMALLOC
  843:   if (!getenv("DMALLOC_OPTIONS"))
  844:     dmalloc_debug(0x2f03d00);
  845: #endif
  846: 
  847:   parse_args(argc, argv);
  848:   log_switch(1, NULL, NULL);
  849: 
  850:   net_init();
  851:   resource_init();
  852:   timer_init();
  853:   olock_init();
  854:   io_init();
  855:   rt_init();
  856:   if_init();
  857: //  roa_init();
  858:   config_init();
  859: 
  860:   uid_t use_uid = get_uid(use_user);
  861:   gid_t use_gid = get_gid(use_group);
  862: 
  863:   if (!parse_and_exit)
  864:   {
  865:     test_old_bird(path_control_socket);
  866:     cli_init_unix(use_uid, use_gid);
  867:   }
  868: 
  869:   if (use_gid)
  870:     drop_gid(use_gid);
  871: 
  872:   if (use_uid)
  873:     drop_uid(use_uid);
  874: 
  875:   if (!parse_and_exit)
  876:     open_pid_file();
  877: 
  878:   protos_build();
  879:   proto_build(&proto_unix_kernel);
  880:   proto_build(&proto_unix_iface);
  881: 
  882:   struct config *conf = read_config();
  883: 
  884:   if (parse_and_exit)
  885:     exit(0);
  886: 
  887:   if (!run_in_foreground)
  888:     {
  889:       pid_t pid = fork();
  890:       if (pid < 0)
  891: 	die("fork: %m");
  892:       if (pid)
  893: 	return 0;
  894:       setsid();
  895:       close(0);
  896:       if (open("/dev/null", O_RDWR) < 0)
  897: 	die("Cannot open /dev/null: %m");
  898:       dup2(0, 1);
  899:       dup2(0, 2);
  900:     }
  901: 
  902:   main_thread_init();
  903: 
  904:   write_pid_file();
  905: 
  906:   signal_init();
  907: 
  908:   config_commit(conf, RECONFIG_HARD, 0);
  909: 
  910:   graceful_restart_init();
  911: 
  912: #ifdef LOCAL_DEBUG
  913:   async_dump_flag = 1;
  914: #endif
  915: 
  916:   log(L_INFO "Started");
  917:   DBG("Entering I/O loop.\n");
  918: 
  919:   io_loop();
  920:   bug("I/O loop died");
  921: }

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