summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/clippy.c6
-rw-r--r--lib/command.c82
-rw-r--r--lib/command.h4
-rw-r--r--lib/command_match.c5
-rw-r--r--lib/imsg.c5
-rw-r--r--lib/libfrr.c51
-rw-r--r--lib/libfrr.h5
-rw-r--r--lib/linklist.c22
-rw-r--r--lib/linklist.h2
-rw-r--r--lib/pbr.h35
-rw-r--r--lib/plist.c5
-rw-r--r--lib/privs.c13
-rw-r--r--lib/sbuf.c5
-rw-r--r--lib/sockopt.c9
-rw-r--r--lib/sockunion.c3
-rw-r--r--lib/stream.c13
-rw-r--r--lib/stream.h3
-rw-r--r--lib/vrf.c39
-rw-r--r--lib/vty.c10
-rw-r--r--lib/vty.h2
20 files changed, 230 insertions, 89 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.c b/lib/linklist.c
index 2cfa3e7482..86649dd495 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -186,26 +186,10 @@ void listnode_move_to_tail(struct list *l, struct listnode *n)
void listnode_delete(struct list *list, void *val)
{
- struct listnode *node;
+ struct listnode *node = listnode_lookup(list, val);
- assert(list);
- for (node = list->head; node; node = node->next) {
- if (node->data == val) {
- if (node->prev)
- node->prev->next = node->next;
- else
- list->head = node->next;
-
- if (node->next)
- node->next->prev = node->prev;
- else
- list->tail = node->prev;
-
- list->count--;
- listnode_free(node);
- return;
- }
- }
+ if (node)
+ list_delete_node(list, node);
}
void *listnode_head(struct list *list)
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/pbr.h b/lib/pbr.h
index 401cfb0813..90997348cf 100644
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -20,6 +20,12 @@
#ifndef _PBR_H
#define _PBR_H
+#include <zebra.h>
+#include "stream.h"
+#include "prefix.h"
+
+#define PBR_STR "Policy Based Routing\n"
+
/*
* A PBR filter
*
@@ -83,6 +89,35 @@ struct pbr_rule {
uint32_t ifindex;
};
+/* TCP flags value shared
+ * those are values of byte 13 of TCP header
+ * as mentioned in rfc793
+ */
+#define TCP_HEADER_FIN (0x01)
+#define TCP_HEADER_SYN (0x02)
+#define TCP_HEADER_RST (0x04)
+#define TCP_HEADER_PSH (0x08)
+#define TCP_HEADER_ACK (0x10)
+#define TCP_HEADER_URG (0x20)
+#define TCP_HEADER_ALL_FLAGS (TCP_HEADER_FIN | TCP_HEADER_SYN \
+ | TCP_HEADER_RST | TCP_HEADER_PSH \
+ | TCP_HEADER_ACK | TCP_HEADER_URG)
+
+/* Pbr IPTable defines
+ * those are common flags shared between BGP and Zebra
+ */
+#define MATCH_IP_SRC_SET (1 << 0)
+#define MATCH_IP_DST_SET (1 << 1)
+#define MATCH_PORT_SRC_SET (1 << 2)
+#define MATCH_PORT_DST_SET (1 << 3)
+#define MATCH_PORT_SRC_RANGE_SET (1 << 4)
+#define MATCH_PORT_DST_RANGE_SET (1 << 5)
+#define MATCH_DSCP_SET (1 << 6)
+#define MATCH_DSCP_INVERSE_SET (1 << 7)
+#define MATCH_PKT_LEN_INVERSE_SET (1 << 8)
+#define MATCH_FRAGMENT_INVERSE_SET (1 << 9)
+#define MATCH_ICMP_SET (1 << 10)
+
extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
struct pbr_rule *zrule);
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);
diff --git a/lib/stream.c b/lib/stream.c
index aba4c20166..a172eedc99 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -1109,6 +1109,10 @@ struct stream_fifo *stream_fifo_new(void)
/* Add new stream to fifo. */
void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
{
+#if defined DEV_BUILD
+ size_t max, curmax;
+#endif
+
if (fifo->tail)
fifo->tail->next = s;
else
@@ -1116,8 +1120,15 @@ void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
fifo->tail = s;
fifo->tail->next = NULL;
-
+#if !defined DEV_BUILD
atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
+#else
+ max = atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
+ curmax = atomic_load_explicit(&fifo->max_count, memory_order_relaxed);
+ if (max > curmax)
+ atomic_store_explicit(&fifo->max_count, max,
+ memory_order_relaxed);
+#endif
}
void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s)
diff --git a/lib/stream.h b/lib/stream.h
index e5d325e43e..11af85c663 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -115,6 +115,9 @@ struct stream_fifo {
/* number of streams in this fifo */
_Atomic size_t count;
+#if defined DEV_BUILD
+ _Atomic size_t max_count;
+#endif
struct stream *head;
struct stream *tail;
diff --git a/lib/vrf.c b/lib/vrf.c
index 797b25d01d..643ad29cf8 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -121,10 +121,10 @@ int vrf_switch_to_netns(vrf_id_t vrf_id)
/* VRF is default VRF. silently ignore */
if (!vrf || vrf->vrf_id == VRF_DEFAULT)
- return 0;
+ return 1; /* 1 = default */
/* VRF has no NETNS backend. silently ignore */
if (vrf->data.l.netns_name[0] == '\0')
- return 0;
+ return 2; /* 2 = no netns */
name = ns_netns_pathname(NULL, vrf->data.l.netns_name);
if (debug_vrf)
zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id);
@@ -505,6 +505,35 @@ void vrf_terminate(void)
}
}
+static int vrf_default_accepts_vrf(int type)
+{
+ const char *fname = NULL;
+ char buf[32] = {0x0};
+ int ret = 0;
+ FILE *fd = NULL;
+
+ /*
+ * TCP & UDP services running in the default VRF context (ie., not bound
+ * to any VRF device) can work across all VRF domains by enabling the
+ * tcp_l3mdev_accept and udp_l3mdev_accept sysctl options:
+ * sysctl -w net.ipv4.tcp_l3mdev_accept=1
+ * sysctl -w net.ipv4.udp_l3mdev_accept=1
+ */
+ if (type == SOCK_STREAM)
+ fname = "/proc/sys/net/ipv4/tcp_l3mdev_accept";
+ else if (type == SOCK_DGRAM)
+ fname = "/proc/sys/net/ipv4/udp_l3mdev_accept";
+ else
+ return ret;
+ fd = fopen(fname, "r");
+ if (fd == NULL)
+ return ret;
+ fgets(buf, 32, fd);
+ ret = atoi(buf);
+ fclose(fd);
+ return ret;
+}
+
/* Create a socket for the VRF. */
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
char *interfacename)
@@ -515,6 +544,12 @@ int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
if (ret < 0)
zlog_err("%s: Can't switch to VRF %u (%s)", __func__, vrf_id,
safe_strerror(errno));
+ if (ret > 0 && interfacename && vrf_default_accepts_vrf(type)) {
+ zlog_err("VRF socket not used since net.ipv4.%s_l3mdev_accept != 0",
+ (type == SOCK_STREAM ? "tcp" : "udp"));
+ errno = EEXIST; /* not sure if this is the best error... */
+ return -2;
+ }
ret = socket(domain, type, protocol);
save_errno = errno;
ret2 = vrf_switchback_to_initial();
diff --git a/lib/vty.c b/lib/vty.c
index 280b2ace51..e9d1f2e323 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -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. */
diff --git a/lib/vty.h b/lib/vty.h
index d14ddf5908..b55abf2204 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -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 *);