diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command.c | 33 | ||||
| -rw-r--r-- | lib/command.h | 1 | ||||
| -rw-r--r-- | lib/command_match.c | 1 | ||||
| -rw-r--r-- | lib/imsg.c | 5 | ||||
| -rw-r--r-- | lib/libfrr.c | 47 | ||||
| -rw-r--r-- | lib/libfrr.h | 5 | ||||
| -rw-r--r-- | lib/plist.c | 5 | ||||
| -rw-r--r-- | lib/sockopt.c | 9 | ||||
| -rw-r--r-- | lib/sockunion.c | 3 | ||||
| -rw-r--r-- | lib/vty.c | 10 | ||||
| -rw-r--r-- | lib/vty.h | 2 |
11 files changed, 105 insertions, 16 deletions
diff --git a/lib/command.c b/lib/command.c index a8e61c6bb4..4ab47e5fc2 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2429,7 +2429,8 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel) XFREE(MTYPE_TMP, p); if (!ret) { - vty_out(vty, "can't open logfile %s\n", fname); + if (vty) + vty_out(vty, "can't open logfile %s\n", fname); return CMD_WARNING_CONFIG_FAILED; } @@ -2445,6 +2446,36 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel) return CMD_SUCCESS; } +void command_setup_early_logging(const char *dest, const char *level) +{ + char *token; + + if (level) { + int nlevel = level_match(level); + + if (nlevel != ZLOG_DISABLED) + zlog_default->default_lvl = nlevel; + } + + if (!dest) + return; + + if (strcmp(dest, "stdout") == 0) { + zlog_set_level(ZLOG_DEST_STDOUT, zlog_default->default_lvl); + return; + } + + if (strcmp(dest, "syslog") == 0) { + zlog_set_level(ZLOG_DEST_SYSLOG, zlog_default->default_lvl); + return; + } + + token = strstr(dest, ":"); + token++; + + set_log_file(NULL, token, zlog_default->default_lvl); +} + DEFUN (config_log_file, config_log_file_cmd, "log file FILENAME [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]", diff --git a/lib/command.h b/lib/command.h index 9bf482f41b..395c971c55 100644 --- a/lib/command.h +++ b/lib/command.h @@ -479,4 +479,5 @@ extern void cmd_variable_handler_register(const struct cmd_variable_handler *cvh); extern char *cmd_variable_comp2str(vector comps, unsigned short cols); +extern void command_setup_early_logging(const char *dest, const char *level); #endif /* _ZEBRA_COMMAND_H */ diff --git a/lib/command_match.c b/lib/command_match.c index 99ec03e0c2..4893ead042 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -609,6 +609,7 @@ static struct list *disambiguate(struct list *first, struct list *second, vector vline, unsigned int n) { // doesn't make sense for these to be inequal length + assert(first && second); assert(first->count == second->count); assert(first->count == vector_active(vline) - n + 1); diff --git a/lib/imsg.c b/lib/imsg.c index 6419f805ab..5424140720 100644 --- a/lib/imsg.c +++ b/lib/imsg.c @@ -77,7 +77,7 @@ ssize_t imsg_read(struct imsgbuf *ibuf) char buf[CMSG_SPACE(sizeof(int) * 1)]; } cmsgbuf; struct iovec iov; - ssize_t n = -1; + ssize_t n; int fd; struct imsg_fd *ifd; @@ -110,7 +110,8 @@ again: return (-1); } - if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { + n = recvmsg(ibuf->fd, &msg, 0); + if (n == -1) { if (errno == EINTR) goto again; goto fail; diff --git a/lib/libfrr.c b/lib/libfrr.c index 88203fbeb6..505bea9b18 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -78,6 +78,8 @@ static void opt_extend(const struct optspec *os) #define OPTION_VTYSOCK 1000 #define OPTION_MODULEDIR 1002 +#define OPTION_LOG 1003 +#define OPTION_LOGLEVEL 1004 static const struct option lo_always[] = { {"help", no_argument, NULL, 'h'}, @@ -86,6 +88,8 @@ static const struct option lo_always[] = { {"module", no_argument, NULL, 'M'}, {"vty_socket", required_argument, NULL, OPTION_VTYSOCK}, {"moduledir", required_argument, NULL, OPTION_MODULEDIR}, + {"log", required_argument, NULL, OPTION_LOG}, + {"log-level", required_argument, NULL, OPTION_LOGLEVEL}, {NULL}}; static const struct optspec os_always = { "hvdM:", @@ -94,7 +98,9 @@ static const struct optspec os_always = { " -d, --daemon Runs in daemon mode\n" " -M, --module Load specified module\n" " --vty_socket Override vty socket path\n" - " --moduledir Override modules directory\n", + " --moduledir Override modules directory\n" + " --log Set Logging to stdout, syslog, or file:<name>\n" + " --log-level Set Logging Level to use, debug, info, warn, etc\n", lo_always}; @@ -444,6 +450,12 @@ static int frr_opt(int opt) return 1; di->privs->group = optarg; break; + case OPTION_LOG: + di->early_logging = optarg; + break; + case OPTION_LOGLEVEL: + di->early_loglevel = optarg; + break; default: return 1; } @@ -543,9 +555,8 @@ struct thread_master *frr_init(void) openzlog(di->progname, di->logname, di->instance, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); -#if defined(HAVE_CUMULUS) - zlog_set_level(ZLOG_DEST_SYSLOG, zlog_default->default_lvl); -#endif + + command_setup_early_logging(di->early_logging, di->early_loglevel); if (!frr_zclient_addr(&zclient_addr, &zclient_addr_len, frr_zclientpath)) { @@ -721,15 +732,37 @@ static void frr_daemonize(void) frr_daemon_wait(fds[0]); } +/* + * Why is this a thread? + * + * The read in of config for integrated config happens *after* + * thread execution starts( because it is passed in via a vtysh -b -n ) + * While if you are not using integrated config we want the ability + * to read the config in after thread execution starts, so that + * we can match this behavior. + */ +static int frr_config_read_in(struct thread *t) +{ + if (!vty_read_config(di->config_file, config_default) && + di->backup_config_file) { + zlog_info("Attempting to read backup config file: %s specified", + di->backup_config_file); + vty_read_config(di->backup_config_file, config_default); + } + return 0; +} + void frr_config_fork(void) { hook_call(frr_late_init, master); - vty_read_config(di->config_file, config_default); - /* Don't start execution if we are in dry-run mode */ - if (di->dryrun) + if (di->dryrun) { + frr_config_read_in(NULL); exit(0); + } + + thread_add_event(master, frr_config_read_in, NULL, 0, &di->read_in); if (di->daemon_mode || di->terminal) frr_daemonize(); diff --git a/lib/libfrr.h b/lib/libfrr.h index 7ffa780bfb..d255279906 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -50,11 +50,16 @@ struct frr_daemon_info { bool dryrun; bool daemon_mode; bool terminal; + + struct thread *read_in; const char *config_file; + const char *backup_config_file; const char *pid_file; const char *vty_path; const char *module_path; const char *pathspace; + const char *early_logging; + const char *early_loglevel; const char *proghelp; void (*printhelp)(FILE *target); diff --git a/lib/plist.c b/lib/plist.c index 5ed1589f45..056b737f54 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -850,6 +850,11 @@ static int vty_prefix_list_install(struct vty *vty, afi_t afi, const char *name, int lenum = 0; int genum = 0; + if (name == NULL || prefix == NULL || typestr == NULL) { + vty_out(vty, "%% Missing prefix or type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + /* Sequential number. */ if (seq) seqnum = (int64_t)atol(seq); diff --git a/lib/sockopt.c b/lib/sockopt.c index 1d8d9990df..815be86c2e 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -457,8 +457,7 @@ int setsockopt_ifindex(int af, int sock, ifindex_t val) */ static ifindex_t getsockopt_ipv4_ifindex(struct msghdr *msgh) { - /* XXX: initialize to zero? (Always overwritten, so just cosmetic.) */ - ifindex_t ifindex = -1; + ifindex_t ifindex; #if defined(IP_PKTINFO) /* Linux pktinfo based ifindex retrieval */ @@ -466,7 +465,11 @@ static ifindex_t getsockopt_ipv4_ifindex(struct msghdr *msgh) pktinfo = (struct in_pktinfo *)getsockopt_cmsg_data(msgh, IPPROTO_IP, IP_PKTINFO); - /* XXX Can pktinfo be NULL? Clean up post 0.98. */ + + /* getsockopt_ifindex() will forward this, being 0 "not found" */ + if (pktinfo == NULL) + return 0; + ifindex = pktinfo->ipi_ifindex; #elif defined(IP_RECVIF) diff --git a/lib/sockunion.c b/lib/sockunion.c index 28a7f647cb..44378b5363 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -46,6 +46,9 @@ int str2sockunion(const char *str, union sockunion *su) { int ret; + if (str == NULL) + return -1; + memset(su, 0, sizeof(union sockunion)); ret = inet_pton(AF_INET, str, &su->sin.sin_addr); @@ -2462,12 +2462,13 @@ static FILE *vty_use_backup_config(const char *fullpath) } /* Read up configuration file from file_name. */ -void vty_read_config(const char *config_file, char *config_default_dir) +bool vty_read_config(const char *config_file, char *config_default_dir) { char cwd[MAXPATHLEN]; FILE *confp = NULL; const char *fullpath; char *tmp = NULL; + bool read_success = false; /* If -f flag specified. */ if (config_file != NULL) { @@ -2525,8 +2526,10 @@ void vty_read_config(const char *config_file, char *config_default_dir) if (strstr(config_default_dir, "vtysh") == NULL) { ret = stat(integrate_default, &conf_stat); - if (ret >= 0) + if (ret >= 0) { + read_success = true; goto tmp_free_and_out; + } } #endif /* VTYSH */ confp = fopen(config_default_dir, "r"); @@ -2550,6 +2553,7 @@ void vty_read_config(const char *config_file, char *config_default_dir) } vty_read_file(confp); + read_success = true; fclose(confp); @@ -2558,6 +2562,8 @@ void vty_read_config(const char *config_file, char *config_default_dir) tmp_free_and_out: if (tmp) XFREE(MTYPE_TMP, tmp); + + return read_success; } /* Small utility function which output log to the VTY. */ @@ -242,7 +242,7 @@ extern void vty_frame(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); extern void vty_endframe(struct vty *, const char *); bool vty_set_include(struct vty *vty, const char *regexp); -extern void vty_read_config(const char *, char *); +extern bool vty_read_config(const char *, char *); extern void vty_time_print(struct vty *, int); extern void vty_serv_sock(const char *, unsigned short, const char *); extern void vty_close(struct vty *); |
