diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/clippy.c | 6 | ||||
| -rw-r--r-- | lib/command.c | 82 | ||||
| -rw-r--r-- | lib/command.h | 4 | ||||
| -rw-r--r-- | lib/command_match.c | 5 | ||||
| -rw-r--r-- | lib/imsg.c | 5 | ||||
| -rw-r--r-- | lib/libfrr.c | 51 | ||||
| -rw-r--r-- | lib/libfrr.h | 5 | ||||
| -rw-r--r-- | lib/linklist.h | 2 | ||||
| -rw-r--r-- | lib/plist.c | 5 | ||||
| -rw-r--r-- | lib/privs.c | 13 | ||||
| -rw-r--r-- | lib/sbuf.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 |
15 files changed, 140 insertions, 67 deletions
diff --git a/lib/clippy.c b/lib/clippy.c index bcec6c2cca..44dcc02eb8 100644 --- a/lib/clippy.c +++ b/lib/clippy.c @@ -31,9 +31,11 @@ #define pychar wchar_t static wchar_t *wconv(const char *s) { - size_t outlen = mbstowcs(NULL, s, 0); + size_t outlen = s ? mbstowcs(NULL, s, 0) : 0; wchar_t *out = malloc((outlen + 1) * sizeof(wchar_t)); - mbstowcs(out, s, outlen + 1); + + if (outlen > 0) + mbstowcs(out, s, outlen); out[outlen] = 0; return out; } diff --git a/lib/command.c b/lib/command.c index a8e61c6bb4..0bf856f248 100644 --- a/lib/command.c +++ b/lib/command.c @@ -261,8 +261,11 @@ void print_version(const char *progname) char *argv_concat(struct cmd_token **argv, int argc, int shift) { - int cnt = argc - shift; - const char *argstr[cnt]; + int cnt = MAX(argc - shift, 0); + const char *argstr[cnt + 1]; + + if (!cnt) + return NULL; for (int i = 0; i < cnt; i++) argstr[i] = argv[i + shift]->arg; @@ -515,13 +518,6 @@ static int config_write_host(struct vty *vty) host.enable); } - if (zlog_default->default_lvl != LOG_DEBUG) { - vty_out(vty, - "! N.B. The 'log trap' command is deprecated.\n"); - vty_out(vty, "log trap %s\n", - zlog_priority[zlog_default->default_lvl]); - } - if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) { @@ -2429,7 +2425,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 +2442,39 @@ 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, ":"); + if (token == NULL) + return; + + 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>]", @@ -2552,36 +2582,6 @@ DEFUN (no_config_log_facility, return CMD_SUCCESS; } -DEFUN_DEPRECATED( - config_log_trap, config_log_trap_cmd, - "log trap <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>", - "Logging control\n" - "(Deprecated) Set logging level and default for all destinations\n" LOG_LEVEL_DESC) -{ - int new_level; - int i; - - if ((new_level = level_match(argv[2]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - - zlog_default->default_lvl = new_level; - for (i = 0; i < ZLOG_NUM_DESTS; i++) - if (zlog_default->maxlvl[i] != ZLOG_DISABLED) - zlog_default->maxlvl[i] = new_level; - return CMD_SUCCESS; -} - -DEFUN_DEPRECATED( - no_config_log_trap, no_config_log_trap_cmd, - "no log trap [emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]", - NO_STR - "Logging control\n" - "Permit all logging information\n" LOG_LEVEL_DESC) -{ - zlog_default->default_lvl = LOG_DEBUG; - return CMD_SUCCESS; -} - DEFUN (config_log_record_priority, config_log_record_priority_cmd, "log record-priority", @@ -2871,8 +2871,6 @@ void cmd_init(int terminal) install_element(CONFIG_NODE, &no_config_log_syslog_cmd); install_element(CONFIG_NODE, &config_log_facility_cmd); install_element(CONFIG_NODE, &no_config_log_facility_cmd); - install_element(CONFIG_NODE, &config_log_trap_cmd); - install_element(CONFIG_NODE, &no_config_log_trap_cmd); install_element(CONFIG_NODE, &config_log_record_priority_cmd); install_element(CONFIG_NODE, &no_config_log_record_priority_cmd); diff --git a/lib/command.h b/lib/command.h index 9bf482f41b..2d333b098a 100644 --- a/lib/command.h +++ b/lib/command.h @@ -240,9 +240,6 @@ struct cmd_node { #define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN) -#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) - /* DEFUN_NOSH for commands that vtysh should ignore */ #define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \ DEFUN(funcname, cmdname, cmdstr, helpstr) @@ -479,4 +476,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..c165305d78 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -608,11 +608,14 @@ static struct cmd_token *disambiguate_tokens(struct cmd_token *first, static struct list *disambiguate(struct list *first, struct list *second, vector vline, unsigned int n) { + assert(first != NULL); + assert(second != NULL); // doesn't make sense for these to be inequal length assert(first->count == second->count); assert(first->count == vector_active(vline) - n + 1); - struct listnode *fnode = listhead(first), *snode = listhead(second); + struct listnode *fnode = listhead_unchecked(first), + *snode = listhead_unchecked(second); struct cmd_token *ftok = listgetdata(fnode), *stok = listgetdata(snode), *best = NULL; 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..9ea5e985cd 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(); @@ -813,7 +846,9 @@ static int frr_daemon_ctl(struct thread *t) switch (buf[0]) { case 'S': /* SIGTSTP */ vty_stdio_suspend(); - send(daemon_ctl_sock, "s", 1, 0); + if (send(daemon_ctl_sock, "s", 1, 0) < 0) + zlog_err("%s send(\"s\") error (SIGTSTP propagation)", + (di && di->name ? di->name : "")); break; case 'R': /* SIGTCNT [implicit] */ vty_stdio_resume(); 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/linklist.h b/lib/linklist.h index 39e70293d2..1e2631ea46 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -52,7 +52,9 @@ struct list { }; #define listnextnode(X) ((X) ? ((X)->next) : NULL) +#define listnextnode_unchecked(X) ((X)->next) #define listhead(X) ((X) ? ((X)->head) : NULL) +#define listhead_unchecked(X) ((X)->head) #define listtail(X) ((X) ? ((X)->tail) : NULL) #define listcount(X) ((X)->count) #define list_isempty(X) ((X)->head == NULL && (X)->tail == NULL) 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/privs.c b/lib/privs.c index cfe7d6d6f8..7c99742d34 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -824,6 +824,19 @@ void zprivs_init(struct zebra_privs_t *zprivs) #ifdef HAVE_CAPABILITIES zprivs_caps_init(zprivs); + + /* + * If we have initialized the system with no requested + * capabilities, change will not have been set + * to anything by zprivs_caps_init, As such + * we should make sure that when we attempt + * to raize privileges that we actually have + * a do nothing function to call instead of a + * crash :). + */ + if (!zprivs->change) + zprivs->change = zprivs_change_null; + #else /* !HAVE_CAPABILITIES */ /* we dont have caps. we'll need to maintain rid and saved uid * and change euid back to saved uid (who we presume has all neccessary diff --git a/lib/sbuf.c b/lib/sbuf.c index 37c1e5283d..03a2be3e09 100644 --- a/lib/sbuf.c +++ b/lib/sbuf.c @@ -63,13 +63,12 @@ void sbuf_push(struct sbuf *buf, int indent, const char *format, ...) int written; if (!buf->fixed) { - char dummy; int written1, written2; size_t new_size; - written1 = snprintf(&dummy, 0, "%*s", indent, ""); + written1 = indent; va_start(args, format); - written2 = vsnprintf(&dummy, 0, format, args); + written2 = vsnprintf(NULL, 0, format, args); va_end(args); new_size = buf->size; 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 *); |
