Annotation of embedaddon/bird2/sysdep/unix/main.c, revision 1.1.1.1

1.1       misho       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>