summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c2
-rw-r--r--bgpd/bgp_attr.c3
-rw-r--r--bgpd/bgp_clist.c5
-rw-r--r--bgpd/bgp_io.c7
-rw-r--r--bgpd/bgp_mplsvpn.c25
-rw-r--r--bgpd/bgp_nexthop.c4
-rw-r--r--bgpd/bgp_open.c5
-rw-r--r--bgpd/bgp_route.c12
-rw-r--r--bgpd/bgp_updgrp_packet.c2
-rw-r--r--bgpd/bgp_vpn.c2
-rw-r--r--bgpd/bgp_vty.c35
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.c5
-rw-r--r--bgpd/rfapi/rfapi_vty.c14
-rw-r--r--doc/user/basic.rst12
-rw-r--r--eigrpd/eigrp_fsm.c8
-rw-r--r--eigrpd/eigrp_interface.c3
-rw-r--r--eigrpd/eigrp_topology.c16
-rw-r--r--include/linux/netlink.h247
-rw-r--r--include/subdir.am1
-rw-r--r--isisd/isis_lsp.c3
-rw-r--r--isisd/isis_pfpacket.c6
-rw-r--r--isisd/isis_spf.c38
-rw-r--r--isisd/isis_te.c2
-rw-r--r--isisd/isisd.c2
-rw-r--r--ldpd/ldp_debug.c3
-rw-r--r--ldpd/ldp_vty_conf.c54
-rw-r--r--ldpd/ldpd.c19
-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.h2
-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/vty.c10
-rw-r--r--lib/vty.h2
-rw-r--r--nhrpd/vici.c1
-rw-r--r--ospf6d/ospf6_abr.c28
-rw-r--r--ospf6d/ospf6_asbr.c10
-rw-r--r--ospf6d/ospf6_flood.c1
-rw-r--r--ospf6d/ospf6_intra.c7
-rw-r--r--ospf6d/ospf6_proto.c10
-rw-r--r--ospf6d/ospf6_proto.h9
-rw-r--r--ospf6d/ospf6_spf.c8
-rw-r--r--ospfd/ospf_api.c21
-rw-r--r--ospfd/ospf_apiserver.c3
-rw-r--r--ospfd/ospf_ase.c2
-rw-r--r--ospfd/ospf_route.c4
-rw-r--r--ospfd/ospf_te.c5
-rw-r--r--ospfd/ospf_vty.c13
-rw-r--r--ospfd/ospf_zebra.c10
-rw-r--r--ospfd/ospfd.c7
-rw-r--r--pimd/mtracebis.c21
-rw-r--r--pimd/pim_cmd.c4
-rw-r--r--pimd/pim_igmp_mtrace.c2
-rw-r--r--pimd/pim_pim.c2
-rw-r--r--ripd/ripd.c4
-rw-r--r--sharpd/sharp_main.c1
-rw-r--r--tests/Makefile.am5
-rw-r--r--tools/start-stop-daemon.c6
-rw-r--r--vtysh/vtysh.c34
-rw-r--r--zebra/if_netlink.c20
-rw-r--r--zebra/kernel_netlink.c117
-rw-r--r--zebra/rt_netlink.c19
-rw-r--r--zebra/rule_netlink.c6
-rw-r--r--zebra/zebra_netns_notify.c11
72 files changed, 869 insertions, 264 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index e02617691f..05e67baa8a 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1632,7 +1632,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
struct aspath *newpath = NULL, *mergedpath;
int hops, cpasns = 0;
- if (!aspath)
+ if (!aspath || !as4path)
return NULL;
seg = aspath->segments;
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 2c52b57b36..6596e7cfa2 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1513,6 +1513,9 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
if (!ignore_as4_path
&& (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
newpath = aspath_reconcile_as4(attr->aspath, as4_path);
+ if (!newpath)
+ return BGP_ATTR_PARSE_ERROR;
+
aspath_unintern(&attr->aspath);
attr->aspath = aspath_intern(newpath);
}
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 7cf1477549..0ffbe174ed 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -1054,6 +1054,9 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name,
struct ecommunity *ecom = NULL;
regex_t *regex = NULL;
+ if (str == NULL)
+ return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+
entry = NULL;
/* Get community list. */
@@ -1089,7 +1092,7 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name,
entry = community_entry_new();
entry->direct = direct;
entry->style = style;
- entry->any = (str ? 0 : 1);
+ entry->any = 0;
if (ecom)
entry->config = ecommunity_ecom2str(
ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0);
diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index 69c92e829c..c8d5b1daa1 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -174,7 +174,6 @@ static int bgp_process_reads(struct thread *thread)
bool more = true; // whether we got more data
bool fatal = false; // whether fatal error occurred
bool added_pkt = false; // whether we pushed onto ->ibuf
- bool header_valid = true; // whether header is valid
/* clang-format on */
peer = THREAD_ARG(thread);
@@ -214,10 +213,8 @@ static int bgp_process_reads(struct thread *thread)
if (ringbuf_remain(ibw) < BGP_HEADER_SIZE)
break;
- /* validate header */
- header_valid = validate_header(peer);
-
- if (!header_valid) {
+ /* check that header is valid */
+ if (!validate_header(peer)) {
fatal = true;
break;
}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 28e8ceb15d..3a854be534 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -466,6 +466,7 @@ leak_update(
{
struct prefix *p = &bn->p;
struct bgp_info *bi;
+ struct bgp_info *bi_ultimate;
struct bgp_info *new;
char buf_prefix[PREFIX_STRLEN];
@@ -477,6 +478,26 @@ leak_update(
}
/*
+ * Routes that are redistributed into BGP from zebra do not get
+ * nexthop tracking. However, if those routes are subsequently
+ * imported to other RIBs within BGP, the leaked routes do not
+ * carry the original BGP_ROUTE_REDISTRIBUTE sub_type. Therefore,
+ * in order to determine if the route we are currently leaking
+ * should have nexthop tracking, we must find the ultimate
+ * parent so we can check its sub_type.
+ *
+ * As of now, source_bi may at most be a second-generation route
+ * (only one hop back to ultimate parent for vrf-vpn-vrf scheme).
+ * Using a loop here supports more complex intra-bgp import-export
+ * schemes that could be implemented in the future.
+ *
+ */
+ for (bi_ultimate = source_bi;
+ bi_ultimate->extra && bi_ultimate->extra->parent;
+ bi_ultimate = bi_ultimate->extra->parent)
+ ;
+
+ /*
* match parent
*/
for (bi = bn->info; bi; bi = bi->next) {
@@ -528,7 +549,7 @@ leak_update(
bgp_nexthop = bi->extra->bgp_orig;
/* No nexthop tracking for redistributed routes */
- if (source_bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
+ if (bi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
nh_valid = 1;
else
/*
@@ -591,7 +612,7 @@ leak_update(
* their originating protocols will do the tracking and
* withdraw those routes if the nexthops become unreachable
*/
- if (source_bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
+ if (bi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
nh_valid = 1;
else
/*
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index fd8d894878..32011d210b 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -438,7 +438,7 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
struct bgp_node *rn1, *rn2;
struct peer_af *paf;
struct prefix p, np;
- struct bgp *bgp = NULL;
+ struct bgp *bgp;
np.family = AF_INET;
np.prefixlen = IPV4_MAX_BITLEN;
@@ -447,7 +447,7 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
- rn1 = rn2 = NULL;
+ rn2 = NULL;
bgp = SUBGRP_INST(subgrp);
rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index aa98f8a557..da90bbd67d 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -80,8 +80,9 @@ void bgp_capability_vty_out(struct vty *vty, struct peer *peer,
afi_t afi;
safi_t safi;
- bgp_map_afi_safi_iana2int(ntohs(mpc.afi), mpc.safi,
- &afi, &safi);
+ (void)bgp_map_afi_safi_iana2int(ntohs(mpc.afi),
+ mpc.safi, &afi, &safi);
+
if (use_json) {
switch (afi) {
case AFI_IP:
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 95e7def8fb..0b1deba517 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1318,6 +1318,8 @@ void bgp_attr_add_gshut_community(struct attr *attr)
old = attr->community;
gshut = community_str2com("graceful-shutdown");
+ assert(gshut);
+
if (old) {
merge = community_merge(community_dup(old), gshut);
@@ -6564,14 +6566,8 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
} else {
char buf[BUFSIZ];
- if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
- snprintf(buf, sizeof(buf), "%s%s",
- inet_ntoa(attr->mp_nexthop_global_in),
- vrf_id_str);
- else
- snprintf(buf, sizeof(buf), "%s%s",
- inet_ntoa(attr->nexthop),
- vrf_id_str);
+ snprintf(buf, sizeof(buf), "%s%s",
+ inet_ntoa(attr->nexthop), vrf_id_str);
vty_out(vty, "%-16s", buf);
}
}
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index cabd5b5cbd..34ddbfcd14 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -397,7 +397,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
vec = &pkt->arr.entries[BGP_ATTR_VEC_NH];
if (CHECK_FLAG(vec->flags, BPKT_ATTRVEC_FLAGS_UPDATED)) {
uint8_t nhlen;
- afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */
+ afi_t nhafi;
int route_map_sets_nh;
nhlen = stream_getc_from(s, vec->offset);
if (peer_cap_enhe(peer, paf->afi, paf->safi))
diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c
index cc05194703..a771eedf0f 100644
--- a/bgpd/bgp_vpn.c
+++ b/bgpd/bgp_vpn.c
@@ -125,7 +125,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
if (rd_header) {
uint16_t type;
- struct rd_as rd_as;
+ struct rd_as rd_as = {0};
struct rd_ip rd_ip = {0};
#if ENABLE_BGP_VNC
struct rd_vnc_eth rd_vnc_eth = {
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 4e0f7155ba..3d1fdfd38d 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -2009,27 +2009,19 @@ DEFUN (no_bgp_fast_external_failover,
CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
#endif
-DEFUN_DEPRECATED (bgp_enforce_first_as,
- bgp_enforce_first_as_cmd,
- "bgp enforce-first-as",
- BGP_STR
- "Enforce the first AS for EBGP routes\n")
+DEFUN_HIDDEN (bgp_enforce_first_as,
+ bgp_enforce_first_as_cmd,
+ "[no] bgp enforce-first-as",
+ NO_STR
+ BGP_STR
+ "Enforce the first AS for EBGP routes\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- bgp_flag_set(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
- return CMD_SUCCESS;
-}
-
-DEFUN_DEPRECATED (no_bgp_enforce_first_as,
- no_bgp_enforce_first_as_cmd,
- "no bgp enforce-first-as",
- NO_STR
- BGP_STR
- "Enforce the first AS for EBGP routes\n")
-{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
+ if (strmatch(argv[0]->text, "no"))
+ bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
+ else
+ bgp_flag_set(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
return CMD_SUCCESS;
}
@@ -6745,6 +6737,11 @@ DEFPY (bgp_imexport_vrf,
safi_t safi;
afi_t afi;
+ if (import_name == NULL) {
+ vty_out(vty, "%% Missing import name\n");
+ return CMD_WARNING;
+ }
+
if (argv_find(argv, argc, "no", &idx))
remove = true;
@@ -11409,7 +11406,6 @@ DEFUN (show_ip_bgp_peer_groups,
"Peer group name\n")
{
char *vrf, *pg;
- vrf = pg = NULL;
int idx = 0;
vrf = argv_find(argv, argc, "VIEWVRFNAME", &idx) ? argv[idx]->arg
@@ -12440,7 +12436,6 @@ void bgp_vty_init(void)
/* "bgp enforce-first-as" commands */
install_element(BGP_NODE, &bgp_enforce_first_as_cmd);
- install_element(BGP_NODE, &no_bgp_enforce_first_as_cmd);
/* "bgp bestpath compare-routerid" commands */
install_element(BGP_NODE, &bgp_bestpath_compare_router_id_cmd);
diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c
index 72255e54fb..8553846c90 100644
--- a/bgpd/rfapi/bgp_rfapi_cfg.c
+++ b/bgpd/rfapi/bgp_rfapi_cfg.c
@@ -1426,7 +1426,8 @@ DEFUN (vnc_export_nvegroup,
if (rfg_new == NULL) {
rfg_new = bgp_rfapi_cfg_match_byname(bgp, argv[5]->arg,
RFAPI_GROUP_CFG_VRF);
- vnc_add_vrf_opener(bgp, rfg_new);
+ if (rfg_new)
+ vnc_add_vrf_opener(bgp, rfg_new);
}
if (rfg_new == NULL) {
@@ -4518,7 +4519,7 @@ void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty)
if (VNC_EXPORT_ZEBRA_GRP_ENABLED(hc)) {
redist++;
vty_out(vty, "%sToZebra Groups={", (redist == 1 ? "" : " "));
- if (hc->rfg_export_direct_bgp_l) {
+ if (hc->rfg_export_zebra_l) {
int cnt = 0;
struct listnode *node, *nnode;
struct rfapi_rfg_name *rfgn;
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 18a979e531..2f8f132fcd 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -388,15 +388,11 @@ int rfapiStream2Vty(void *stream, /* input */
return 1;
}
- if (stream) {
- *vty = stream; /* VTYNL requires vty to be legit */
- *fp = (int (*)(void *, const char *, ...))vty_out;
- *outstream = stream;
- *vty_newline = str_vty_newline(*vty);
- return 1;
- }
-
- return 0;
+ *vty = stream; /* VTYNL requires vty to be legit */
+ *fp = (int (*)(void *, const char *, ...))vty_out;
+ *outstream = stream;
+ *vty_newline = str_vty_newline(*vty);
+ return 1;
}
/* called from bgpd/bgp_vty.c'route_vty_out() */
diff --git a/doc/user/basic.rst b/doc/user/basic.rst
index a75017c442..cb46080055 100644
--- a/doc/user/basic.rst
+++ b/doc/user/basic.rst
@@ -405,6 +405,18 @@ These options apply to all |PACKAGE_NAME| daemons.
Print program version.
+.. option:: --log <stdout|syslog|file:/path/to/log/file>
+
+ When initializing the daemon, setup the log to go to either stdout,
+ syslog or to a file. These values will be displayed as part of
+ a show run. Additionally they can be overridden at runtime if
+ desired via the normal log commands.
+
+.. option:: --log-level <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>
+
+ When initializing the daemon, allow the specification of a default
+ log level at startup from one of the specified levels.
+
.. _loadable-module-support:
Loadable Module Support
diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c
index 4107d44090..eeefc51968 100644
--- a/eigrpd/eigrp_fsm.c
+++ b/eigrpd/eigrp_fsm.c
@@ -486,6 +486,7 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg)
int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg)
{
+ struct eigrp *eigrp;
struct eigrp_prefix_entry *prefix = msg->prefix;
struct eigrp_nexthop_entry *ne = listnode_head(prefix->entries);
@@ -498,9 +499,10 @@ int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg)
if (msg->packet_type == EIGRP_OPC_QUERY)
eigrp_send_reply(msg->adv_router, prefix);
prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
- listnode_add(
- (eigrp_lookup())->topology_changes_internalIPV4,
- prefix);
+ eigrp = eigrp_lookup();
+ assert(eigrp);
+ listnode_add(eigrp->topology_changes_internalIPV4,
+ prefix);
}
eigrp_topology_update_node_flags(prefix);
eigrp_update_routing_table(prefix);
diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c
index cd459fdc42..cd62811fdf 100644
--- a/eigrpd/eigrp_interface.c
+++ b/eigrpd/eigrp_interface.c
@@ -336,6 +336,9 @@ void eigrp_if_free(struct eigrp_interface *ei, int source)
struct eigrp_prefix_entry *pe;
struct eigrp *eigrp = eigrp_lookup();
+ if (!eigrp)
+ return;
+
if (source == INTERFACE_DOWN_BY_VTY) {
THREAD_OFF(ei->t_hello);
eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c
index becb29a95f..8ca0e282a8 100644
--- a/eigrpd/eigrp_topology.c
+++ b/eigrpd/eigrp_topology.c
@@ -182,6 +182,9 @@ void eigrp_prefix_entry_delete(struct route_table *table,
struct eigrp *eigrp = eigrp_lookup();
struct route_node *rn;
+ if (!eigrp)
+ return;
+
rn = route_node_lookup(table, pe->destination);
if (!rn)
return;
@@ -426,6 +429,9 @@ void eigrp_topology_update_all_node_flags(struct eigrp *eigrp)
struct eigrp_prefix_entry *pe;
struct route_node *rn;
+ if (!eigrp)
+ return;
+
for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
pe = rn->info;
@@ -442,6 +448,8 @@ void eigrp_topology_update_node_flags(struct eigrp_prefix_entry *dest)
struct eigrp_nexthop_entry *entry;
struct eigrp *eigrp = eigrp_lookup();
+ assert(eigrp);
+
for (ALL_LIST_ELEMENTS_RO(dest->entries, node, entry)) {
if (entry->reported_distance < dest->fdistance) {
// is feasible successor, can be successor
@@ -471,11 +479,15 @@ void eigrp_topology_update_node_flags(struct eigrp_prefix_entry *dest)
void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix)
{
struct eigrp *eigrp = eigrp_lookup();
- struct list *successors =
- eigrp_topology_get_successor_max(prefix, eigrp->max_paths);
+ struct list *successors;
struct listnode *node;
struct eigrp_nexthop_entry *entry;
+ if (!eigrp)
+ return;
+
+ successors = eigrp_topology_get_successor_max(prefix, eigrp->max_paths);
+
if (successors) {
eigrp_zebra_route_add(prefix->destination, successors);
for (ALL_LIST_ELEMENTS_RO(successors, node, entry))
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
new file mode 100644
index 0000000000..0b2c29bd08
--- /dev/null
+++ b/include/linux/netlink.h
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_NETLINK_H
+#define __LINUX_NETLINK_H
+
+#include <linux/kernel.h>
+#include <linux/socket.h> /* for __kernel_sa_family_t */
+#include <linux/types.h>
+
+#define NETLINK_ROUTE 0 /* Routing/device hook */
+#define NETLINK_UNUSED 1 /* Unused number */
+#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
+#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
+#define NETLINK_SOCK_DIAG 4 /* socket monitoring */
+#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
+#define NETLINK_XFRM 6 /* ipsec */
+#define NETLINK_SELINUX 7 /* SELinux event notifications */
+#define NETLINK_ISCSI 8 /* Open-iSCSI */
+#define NETLINK_AUDIT 9 /* auditing */
+#define NETLINK_FIB_LOOKUP 10
+#define NETLINK_CONNECTOR 11
+#define NETLINK_NETFILTER 12 /* netfilter subsystem */
+#define NETLINK_IP6_FW 13
+#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
+#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
+#define NETLINK_GENERIC 16
+/* leave room for NETLINK_DM (DM Events) */
+#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
+#define NETLINK_ECRYPTFS 19
+#define NETLINK_RDMA 20
+#define NETLINK_CRYPTO 21 /* Crypto layer */
+#define NETLINK_SMC 22 /* SMC monitoring */
+
+#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
+
+#define MAX_LINKS 32
+
+struct sockaddr_nl {
+ __kernel_sa_family_t nl_family; /* AF_NETLINK */
+ unsigned short nl_pad; /* zero */
+ __u32 nl_pid; /* port ID */
+ __u32 nl_groups; /* multicast groups mask */
+};
+
+struct nlmsghdr {
+ __u32 nlmsg_len; /* Length of message including header */
+ __u16 nlmsg_type; /* Message content */
+ __u16 nlmsg_flags; /* Additional flags */
+ __u32 nlmsg_seq; /* Sequence number */
+ __u32 nlmsg_pid; /* Sending process port ID */
+};
+
+/* Flags values */
+
+#define NLM_F_REQUEST 0x01 /* It is request message. */
+#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */
+#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */
+#define NLM_F_ECHO 0x08 /* Echo this request */
+#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */
+#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */
+
+/* Modifiers to GET request */
+#define NLM_F_ROOT 0x100 /* specify tree root */
+#define NLM_F_MATCH 0x200 /* return all matching */
+#define NLM_F_ATOMIC 0x400 /* atomic GET */
+#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
+
+/* Modifiers to NEW request */
+#define NLM_F_REPLACE 0x100 /* Override existing */
+#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
+#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
+#define NLM_F_APPEND 0x800 /* Add to end of list */
+
+/* Modifiers to DELETE request */
+#define NLM_F_NONREC 0x100 /* Do not delete recursively */
+
+/* Flags for ACK message */
+#define NLM_F_CAPPED 0x100 /* request was capped */
+#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
+
+/*
+ 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
+ 4.4BSD CHANGE NLM_F_REPLACE
+
+ True CHANGE NLM_F_CREATE|NLM_F_REPLACE
+ Append NLM_F_CREATE
+ Check NLM_F_EXCL
+ */
+
+#define NLMSG_ALIGNTO 4U
+#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
+#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
+#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
+#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
+#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
+ (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
+#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
+ (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
+ (nlh)->nlmsg_len <= (len))
+#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
+
+#define NLMSG_NOOP 0x1 /* Nothing. */
+#define NLMSG_ERROR 0x2 /* Error */
+#define NLMSG_DONE 0x3 /* End of a dump */
+#define NLMSG_OVERRUN 0x4 /* Data lost */
+
+#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
+
+struct nlmsgerr {
+ int error;
+ struct nlmsghdr msg;
+ /*
+ * followed by the message contents unless NETLINK_CAP_ACK was set
+ * or the ACK indicates success (error == 0)
+ * message length is aligned with NLMSG_ALIGN()
+ */
+ /*
+ * followed by TLVs defined in enum nlmsgerr_attrs
+ * if NETLINK_EXT_ACK was set
+ */
+};
+
+/**
+ * enum nlmsgerr_attrs - nlmsgerr attributes
+ * @NLMSGERR_ATTR_UNUSED: unused
+ * @NLMSGERR_ATTR_MSG: error message string (string)
+ * @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original
+ * message, counting from the beginning of the header (u32)
+ * @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
+ * be used - in the success case - to identify a created
+ * object or operation or similar (binary)
+ * @__NLMSGERR_ATTR_MAX: number of attributes
+ * @NLMSGERR_ATTR_MAX: highest attribute number
+ */
+enum nlmsgerr_attrs {
+ NLMSGERR_ATTR_UNUSED,
+ NLMSGERR_ATTR_MSG,
+ NLMSGERR_ATTR_OFFS,
+ NLMSGERR_ATTR_COOKIE,
+
+ __NLMSGERR_ATTR_MAX,
+ NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
+};
+
+#define NETLINK_ADD_MEMBERSHIP 1
+#define NETLINK_DROP_MEMBERSHIP 2
+#define NETLINK_PKTINFO 3
+#define NETLINK_BROADCAST_ERROR 4
+#define NETLINK_NO_ENOBUFS 5
+#define NETLINK_RX_RING 6
+#define NETLINK_TX_RING 7
+#define NETLINK_LISTEN_ALL_NSID 8
+#define NETLINK_LIST_MEMBERSHIPS 9
+#define NETLINK_CAP_ACK 10
+#define NETLINK_EXT_ACK 11
+
+struct nl_pktinfo {
+ __u32 group;
+};
+
+struct nl_mmap_req {
+ unsigned int nm_block_size;
+ unsigned int nm_block_nr;
+ unsigned int nm_frame_size;
+ unsigned int nm_frame_nr;
+};
+
+struct nl_mmap_hdr {
+ unsigned int nm_status;
+ unsigned int nm_len;
+ __u32 nm_group;
+ /* credentials */
+ __u32 nm_pid;
+ __u32 nm_uid;
+ __u32 nm_gid;
+};
+
+enum nl_mmap_status {
+ NL_MMAP_STATUS_UNUSED,
+ NL_MMAP_STATUS_RESERVED,
+ NL_MMAP_STATUS_VALID,
+ NL_MMAP_STATUS_COPY,
+ NL_MMAP_STATUS_SKIP,
+};
+
+#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
+#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
+#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
+
+#define NET_MAJOR 36 /* Major 36 is reserved for networking */
+
+enum {
+ NETLINK_UNCONNECTED = 0,
+ NETLINK_CONNECTED,
+};
+
+/*
+ * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
+ * +---------------------+- - -+- - - - - - - - - -+- - -+
+ * | Header | Pad | Payload | Pad |
+ * | (struct nlattr) | ing | | ing |
+ * +---------------------+- - -+- - - - - - - - - -+- - -+
+ * <-------------- nlattr->nla_len -------------->
+ */
+
+struct nlattr {
+ __u16 nla_len;
+ __u16 nla_type;
+};
+
+/*
+ * nla_type (16 bits)
+ * +---+---+-------------------------------+
+ * | N | O | Attribute Type |
+ * +---+---+-------------------------------+
+ * N := Carries nested attributes
+ * O := Payload stored in network byte order
+ *
+ * Note: The N and O flag are mutually exclusive.
+ */
+#define NLA_F_NESTED (1 << 15)
+#define NLA_F_NET_BYTEORDER (1 << 14)
+#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
+
+#define NLA_ALIGNTO 4
+#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
+#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
+
+/* Generic 32 bitflags attribute content sent to the kernel.
+ *
+ * The value is a bitmap that defines the values being set
+ * The selector is a bitmask that defines which value is legit
+ *
+ * Examples:
+ * value = 0x0, and selector = 0x1
+ * implies we are selecting bit 1 and we want to set its value to 0.
+ *
+ * value = 0x2, and selector = 0x2
+ * implies we are selecting bit 2 and we want to set its value to 1.
+ *
+ */
+struct nla_bitfield32 {
+ __u32 value;
+ __u32 selector;
+};
+
+#endif /* __LINUX_NETLINK_H */
diff --git a/include/subdir.am b/include/subdir.am
index db5ed06c61..731785d4b4 100644
--- a/include/subdir.am
+++ b/include/subdir.am
@@ -4,6 +4,7 @@ noinst_HEADERS += \
include/linux/lwtunnel.h \
include/linux/mpls_iptunnel.h \
include/linux/neighbour.h \
+ include/linux/netlink.h \
include/linux/rtnetlink.h \
include/linux/socket.h \
include/linux/net_namespace.h \
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index bba86d4c1f..c8ef829064 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -622,7 +622,7 @@ static const char *lsp_bits2string(uint8_t lsp_bits, char *buf, size_t buf_size)
pos += sprintf(pos, "%d/",
ISIS_MASK_LSP_PARTITION_BIT(lsp_bits) ? 1 : 0);
- pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(lsp_bits) ? 1 : 0);
+ sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(lsp_bits) ? 1 : 0);
return buf;
}
@@ -1052,6 +1052,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
uint8_t subtlv_len;
if (IS_MPLS_TE(isisMplsTE)
+ && circuit->interface != NULL
&& HAS_LINK_PARAMS(
circuit->interface))
/* Update Local and Remote IP
diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c
index 6e56870ebd..fd82b85f51 100644
--- a/isisd/isis_pfpacket.c
+++ b/isisd/isis_pfpacket.c
@@ -309,9 +309,9 @@ int isis_recv_pdu_p2p(struct isis_circuit *circuit, uint8_t *ssnpa)
addr_len = sizeof(s_addr);
/* we can read directly to the stream */
- stream_recvfrom(circuit->rcv_stream, circuit->fd,
- circuit->interface->mtu, 0, (struct sockaddr *)&s_addr,
- (socklen_t *)&addr_len);
+ (void)stream_recvfrom(
+ circuit->rcv_stream, circuit->fd, circuit->interface->mtu, 0,
+ (struct sockaddr *)&s_addr, (socklen_t *)&addr_len);
if (s_addr.sll_pkttype == PACKET_OUTGOING) {
/* Read the packet into discard buff */
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index a55a0e1902..2e2933db33 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -77,14 +77,13 @@ enum vertextype {
/*
* Triple <N, d(N), {Adj(N)}>
*/
+union isis_N {
+ uint8_t id[ISIS_SYS_ID_LEN + 1];
+ struct prefix prefix;
+};
struct isis_vertex {
enum vertextype type;
-
- union {
- uint8_t id[ISIS_SYS_ID_LEN + 1];
- struct prefix prefix;
- } N;
-
+ union isis_N N;
uint32_t d_N; /* d(N) Distance from this IS */
uint16_t depth; /* The depth in the imaginary tree */
struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */
@@ -407,28 +406,28 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
return "UNKNOWN";
}
-static void isis_vertex_id_init(struct isis_vertex *vertex, void *id,
+static void isis_vertex_id_init(struct isis_vertex *vertex, union isis_N *n,
enum vertextype vtype)
{
vertex->type = vtype;
if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) {
- memcpy(vertex->N.id, (uint8_t *)id, ISIS_SYS_ID_LEN + 1);
+ memcpy(vertex->N.id, n->id, ISIS_SYS_ID_LEN + 1);
} else if (VTYPE_IP(vtype)) {
- memcpy(&vertex->N.prefix, (struct prefix *)id,
- sizeof(struct prefix));
+ memcpy(&vertex->N.prefix, &n->prefix, sizeof(struct prefix));
} else {
zlog_err("WTF!");
}
}
-static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype)
+static struct isis_vertex *isis_vertex_new(union isis_N *n,
+ enum vertextype vtype)
{
struct isis_vertex *vertex;
vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex));
- isis_vertex_id_init(vertex, id, vtype);
+ isis_vertex_id_init(vertex, n, vtype);
vertex->Adj_N = list_new();
vertex->parents = list_new();
@@ -598,17 +597,17 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
#ifdef EXTREME_DEBUG
char buff[PREFIX2STR_BUFFER];
#endif /* EXTREME_DEBUG */
- uint8_t id[ISIS_SYS_ID_LEN + 1];
+ union isis_N n;
- memcpy(id, sysid, ISIS_SYS_ID_LEN);
- LSP_PSEUDO_ID(id) = 0;
+ memcpy(n.id, sysid, ISIS_SYS_ID_LEN);
+ LSP_PSEUDO_ID(n.id) = 0;
lsp = isis_root_system_lsp(spftree->area, spftree->level, sysid);
if (lsp == NULL)
zlog_warn("ISIS-Spf: could not find own l%d LSP!",
spftree->level);
- vertex = isis_vertex_new(id,
+ vertex = isis_vertex_new(&n,
spftree->area->oldmetric
? VTYPE_NONPSEUDO_IS
: VTYPE_NONPSEUDO_TE_IS);
@@ -625,11 +624,12 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree,
}
static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue,
- void *id, enum vertextype vtype)
+ union isis_N *n,
+ enum vertextype vtype)
{
struct isis_vertex querier;
- isis_vertex_id_init(&querier, id, vtype);
+ isis_vertex_id_init(&querier, n, vtype);
return hash_lookup(queue->hash, &querier);
}
@@ -1212,7 +1212,7 @@ static void add_to_paths(struct isis_spftree *spftree,
{
char buff[PREFIX2STR_BUFFER];
- if (isis_find_vertex(&spftree->paths, vertex->N.id, vertex->type))
+ if (isis_find_vertex(&spftree->paths, &vertex->N, vertex->type))
return;
isis_vertex_queue_append(&spftree->paths, vertex);
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 6834f52a82..8e53df3b61 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -884,7 +884,7 @@ static uint8_t print_subtlv_use_bw(struct sbuf *buf, int indent,
static uint8_t print_unknown_tlv(struct sbuf *buf, int indent,
struct subtlv_header *tlvh)
{
- int i, rtn = 1;
+ int i, rtn;
uint8_t *v = (uint8_t *)tlvh;
if (tlvh->length != 0) {
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 6f04d72082..cecaa0693d 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -1373,7 +1373,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level)
struct isis_area *area;
struct isis_lsp *lsp;
struct isis_dynhn *dynhn;
- const char *pos = argv;
+ const char *pos;
uint8_t lspid[ISIS_SYS_ID_LEN + 2];
char sysid[255];
uint8_t number[3];
diff --git a/ldpd/ldp_debug.c b/ldpd/ldp_debug.c
index 39e20ef7c8..ec70ef510a 100644
--- a/ldpd/ldp_debug.c
+++ b/ldpd/ldp_debug.c
@@ -41,6 +41,9 @@ int
ldp_vty_debug(struct vty *vty, const char *negate, const char *type_str,
const char *dir_str, const char *all)
{
+ if (type_str == NULL)
+ return (CMD_WARNING_CONFIG_FAILED);
+
if (strcmp(type_str, "discovery") == 0) {
if (dir_str == NULL)
return (CMD_WARNING_CONFIG_FAILED);
diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c
index 382b006884..4ef57f574a 100644
--- a/ldpd/ldp_vty_conf.c
+++ b/ldpd/ldp_vty_conf.c
@@ -89,6 +89,9 @@ struct cmd_node ldp_pseudowire_node =
int
ldp_get_address(const char *str, int *af, union ldpd_addr *addr)
{
+ if (!str || !af || !addr)
+ return (-1);
+
memset(addr, 0, sizeof(*addr));
if (inet_pton(AF_INET, str, &addr->v4) == 1) {
@@ -428,6 +431,9 @@ ldp_vty_address_family(struct vty *vty, const char *negate, const char *af_str)
struct ldpd_af_conf *af_conf;
int af;
+ if (af_str == NULL)
+ return (CMD_WARNING_CONFIG_FAILED);
+
if (strcmp(af_str, "ipv4") == 0) {
af = AF_INET;
af_conf = &vty_conf->ipv4;
@@ -709,6 +715,11 @@ ldp_vty_interface(struct vty *vty, const char *negate, const char *ifname)
struct iface *iface;
struct iface_af *ia;
+ if (ifname == NULL) {
+ vty_out (vty, "%% Missing IF name\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
+
af = ldp_vty_get_af(vty);
iface = if_lookup_name(vty_conf, ifname);
@@ -776,8 +787,9 @@ ldp_vty_trans_addr(struct vty *vty, const char *negate, const char *addr_str)
if (negate)
memset(&af_conf->trans_addr, 0, sizeof(af_conf->trans_addr));
else {
- if (inet_pton(af, addr_str, &af_conf->trans_addr) != 1 ||
- bad_addr(af, &af_conf->trans_addr)) {
+ if (addr_str == NULL
+ || inet_pton(af, addr_str, &af_conf->trans_addr) != 1
+ || bad_addr(af, &af_conf->trans_addr)) {
vty_out (vty, "%% Malformed address\n");
return (CMD_SUCCESS);
}
@@ -797,7 +809,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, const char *negate, const char *addr_
af = ldp_vty_get_af(vty);
- if (inet_pton(af, addr_str, &addr) != 1 ||
+ if (addr_str == NULL || inet_pton(af, addr_str, &addr) != 1 ||
bad_addr(af, &addr)) {
vty_out (vty, "%% Malformed address\n");
return (CMD_WARNING_CONFIG_FAILED);
@@ -1018,6 +1030,11 @@ ldp_vty_neighbor_password(struct vty *vty, const char *negate, struct in_addr ls
size_t password_len;
struct nbr_params *nbrp;
+ if (password_str == NULL) {
+ vty_out (vty, "%% Missing password\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
+
if (bad_addr_v4(lsr_id)) {
vty_out (vty, "%% Malformed address\n");
return (CMD_WARNING_CONFIG_FAILED);
@@ -1113,6 +1130,11 @@ ldp_vty_l2vpn(struct vty *vty, const char *negate, const char *name_str)
struct l2vpn_if *lif;
struct l2vpn_pw *pw;
+ if (name_str == NULL) {
+ vty_out (vty, "%% Missing name\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
+
l2vpn = l2vpn_find(vty_conf, name_str);
if (negate) {
@@ -1158,8 +1180,13 @@ ldp_vty_l2vpn_bridge(struct vty *vty, const char *negate, const char *ifname)
if (negate)
memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname));
- else
+ else {
+ if (ifname == NULL) {
+ vty_out (vty, "%% Missing IF name\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
strlcpy(l2vpn->br_ifname, ifname, sizeof(l2vpn->br_ifname));
+ }
ldp_config_apply(vty, vty_conf);
@@ -1187,6 +1214,11 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, const char *negate, const char *type_str)
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
int pw_type;
+ if (type_str == NULL) {
+ vty_out (vty, "%% Missing type\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
+
if (strcmp(type_str, "ethernet") == 0)
pw_type = PW_TYPE_ETHERNET;
else
@@ -1208,6 +1240,11 @@ ldp_vty_l2vpn_interface(struct vty *vty, const char *negate, const char *ifname)
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
struct l2vpn_if *lif;
+ if (ifname == NULL) {
+ vty_out (vty, "%% Missing IF name\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
+
lif = l2vpn_if_find(l2vpn, ifname);
if (negate) {
@@ -1246,6 +1283,11 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, const char *negate, const char *ifname
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
struct l2vpn_pw *pw;
+ if (ifname == NULL) {
+ vty_out (vty, "%% Missing IF name\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
+
pw = l2vpn_pw_find(l2vpn, ifname);
if (negate) {
@@ -1294,6 +1336,10 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, const char *negate, const char *preferen
if (negate)
pw->flags |= F_PW_CWORD_CONF;
else {
+ if (!preference_str) {
+ vty_out (vty, "%% Missing preference\n");
+ return (CMD_WARNING_CONFIG_FAILED);
+ }
if (preference_str[0] == 'e')
pw->flags &= ~F_PW_CWORD_CONF;
else
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index b265c98dae..b51ff82cea 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -187,6 +187,22 @@ FRR_DAEMON_INFO(ldpd, LDP,
.privs = &ldpd_privs,
)
+static int ldp_config_fork_apply(struct thread *t)
+{
+ /*
+ * So the frr_config_fork() function schedules
+ * the read of the vty config( if there is a
+ * non-integrated config ) to be after the
+ * end of startup and we are starting the
+ * main process loop. We need to schedule
+ * the application of this if necessary
+ * after the read in of the config.
+ */
+ ldp_config_apply(NULL, vty_conf);
+
+ return 0;
+}
+
int
main(int argc, char *argv[])
{
@@ -195,6 +211,7 @@ main(int argc, char *argv[])
int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2];
int pipe_parent2lde[2], pipe_parent2lde_sync[2];
char *ctl_sock_name;
+ struct thread *thread = NULL;
ldpd_process = PROC_MAIN;
log_procname = log_procnames[ldpd_process];
@@ -331,7 +348,7 @@ main(int argc, char *argv[])
frr_config_fork();
/* apply configuration */
- ldp_config_apply(NULL, vty_conf);
+ thread_add_event(master, ldp_config_fork_apply, NULL, 0, &thread);
/* setup pipes to children */
if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL ||
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);
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 *);
diff --git a/nhrpd/vici.c b/nhrpd/vici.c
index e6111f9d71..3bb0d8308e 100644
--- a/nhrpd/vici.c
+++ b/nhrpd/vici.c
@@ -287,6 +287,7 @@ static void vici_recv_sa(struct vici_conn *vici, struct zbuf *msg, int event)
char buf[32];
struct handle_sa_ctx ctx = {
.event = event,
+ .msgctx.nsections = 0
};
vici_parse_message(vici, msg, parse_sa_message, &ctx.msgctx);
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index b3aa3b21d2..7bccc78e00 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -161,9 +161,10 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
&& route->type != OSPF6_DEST_TYPE_RANGE
&& ((route->type != OSPF6_DEST_TYPE_ROUTER)
|| !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) {
- if (is_debug)
- zlog_debug(
- "Route type is none of network, range nor ASBR, ignore");
+#if 0
+ zlog_debug(
+ "Route type is none of network, range nor ASBR, ignore");
+#endif
return 0;
}
@@ -177,16 +178,17 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
/* do not generate if the path's area is the same as target area */
if (route->path.area_id == area->area_id) {
- if (is_debug)
- zlog_debug("The route is in the area itself, ignore");
+#if 0
+ zlog_debug("The route is in the area itself, ignore");
+#endif
return 0;
}
/* do not generate if the nexthops belongs to the target area */
if (ospf6_abr_nexthops_belong_to_area(route, area)) {
- if (is_debug)
- zlog_debug(
- "The route's nexthop is in the same area, ignore");
+#if 0
+ zlog_debug("The route's nexthop is in the same area, ignore");
+#endif
return 0;
}
@@ -641,6 +643,11 @@ void ospf6_abr_originate_summary(struct ospf6_route *route)
if (route->type == OSPF6_DEST_TYPE_NETWORK) {
oa = ospf6_area_lookup(route->path.area_id, ospf6);
+ if (!oa) {
+ zlog_err("OSPFv6 area lookup failed");
+ return;
+ }
+
range = ospf6_route_lookup_bestmatch(&route->prefix,
oa->range_table);
if (range) {
@@ -864,7 +871,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
lsa->header);
prefix.family = AF_INET6;
prefix.prefixlen = prefix_lsa->prefix.prefix_length;
- ospf6_prefix_in6_addr(&prefix.u.prefix6, &prefix_lsa->prefix);
+ ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
+ &prefix_lsa->prefix);
if (is_debug)
prefix2str(&prefix, buf, sizeof(buf));
table = oa->ospf6->route_table;
@@ -1284,7 +1292,7 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
(struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
lsa->header);
- ospf6_prefix_in6_addr(&in6, &prefix_lsa->prefix);
+ ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
if (buf) {
inet_ntop(AF_INET6, &in6, buf, buflen);
sprintf(&buf[strlen(buf)], "/%d",
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 7f575ee506..a723396507 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -497,7 +497,8 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
route->type = OSPF6_DEST_TYPE_NETWORK;
route->prefix.family = AF_INET6;
route->prefix.prefixlen = external->prefix.prefix_length;
- ospf6_prefix_in6_addr(&route->prefix.u.prefix6, &external->prefix);
+ ospf6_prefix_in6_addr(&route->prefix.u.prefix6, external,
+ &external->prefix);
route->path.area_id = asbr_entry->path.area_id;
route->path.origin.type = lsa->header->type;
@@ -576,7 +577,7 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
route_to_del->type = OSPF6_DEST_TYPE_NETWORK;
route_to_del->prefix.family = AF_INET6;
route_to_del->prefix.prefixlen = external->prefix.prefix_length;
- ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6,
+ ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6, external,
&external->prefix);
route_to_del->path.origin.type = lsa->header->type;
@@ -603,7 +604,7 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
memset(&prefix, 0, sizeof(struct prefix));
prefix.family = AF_INET6;
prefix.prefixlen = external->prefix.prefix_length;
- ospf6_prefix_in6_addr(&prefix.u.prefix6, &external->prefix);
+ ospf6_prefix_in6_addr(&prefix.u.prefix6, external, &external->prefix);
route = ospf6_route_lookup(&prefix, ospf6->route_table);
if (route == NULL) {
@@ -1705,7 +1706,8 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
lsa->header);
if (pos == 0) {
- ospf6_prefix_in6_addr(&in6, &external->prefix);
+ ospf6_prefix_in6_addr(&in6, external,
+ &external->prefix);
prefix_length = external->prefix.prefix_length;
} else {
in6 = *((struct in6_addr
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 2059d84868..ae26668c8a 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -347,6 +347,7 @@ void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
"Received is newer, remove requesting");
if (req == on->last_ls_req) {
ospf6_lsa_unlock(req);
+ req = NULL;
on->last_ls_req = NULL;
}
if (req)
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index d99541ebad..0ce08a61e2 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -1323,6 +1323,8 @@ static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route)
g_route = ospf6_route_lookup(&oa_route->prefix,
ospf6->route_table);
+ assert(g_route);
+
for (ospf6_route_lock(g_route); g_route &&
ospf6_route_is_prefix(&oa_route->prefix, g_route);
g_route = nroute) {
@@ -1698,7 +1700,8 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
memset(&route->prefix, 0, sizeof(struct prefix));
route->prefix.family = AF_INET6;
route->prefix.prefixlen = op->prefix_length;
- ospf6_prefix_in6_addr(&route->prefix.u.prefix6, op);
+ ospf6_prefix_in6_addr(&route->prefix.u.prefix6,
+ intra_prefix_lsa, op);
route->type = OSPF6_DEST_TYPE_NETWORK;
route->path.origin.type = lsa->header->type;
@@ -1880,7 +1883,7 @@ void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
memset(&prefix, 0, sizeof(struct prefix));
prefix.family = AF_INET6;
prefix.prefixlen = op->prefix_length;
- ospf6_prefix_in6_addr(&prefix.u.prefix6, op);
+ ospf6_prefix_in6_addr(&prefix.u.prefix6, intra_prefix_lsa, op);
route = ospf6_route_lookup(&prefix, oa->route_table);
if (route == NULL)
diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c
index 4b56a64b7f..864974c9a4 100644
--- a/ospf6d/ospf6_proto.c
+++ b/ospf6d/ospf6_proto.c
@@ -24,6 +24,16 @@
#include "ospf6_proto.h"
+void ospf6_prefix_in6_addr(struct in6_addr *in6, const void *prefix_buf,
+ const struct ospf6_prefix *p)
+{
+ ptrdiff_t in6_off = (caddr_t)p->addr - (caddr_t)prefix_buf;
+
+ memset(in6, 0, sizeof(struct in6_addr));
+ memcpy(in6, (uint8_t *)prefix_buf + in6_off,
+ OSPF6_PREFIX_SPACE(p->prefix_length));
+}
+
void ospf6_prefix_apply_mask(struct ospf6_prefix *op)
{
uint8_t *pnt, mask;
diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h
index ca2804c476..c9e7b549db 100644
--- a/ospf6d/ospf6_proto.h
+++ b/ospf6d/ospf6_proto.h
@@ -84,13 +84,8 @@ struct ospf6_prefix {
#define OSPF6_PREFIX_NEXT(x) \
((struct ospf6_prefix *)((caddr_t)(x) + OSPF6_PREFIX_SIZE(x)))
-#define ospf6_prefix_in6_addr(in6, op) \
- do { \
- memset(in6, 0, sizeof(struct in6_addr)); \
- memcpy(in6, (caddr_t)(op) + sizeof(struct ospf6_prefix), \
- OSPF6_PREFIX_SPACE((op)->prefix_length)); \
- } while (0)
-
+extern void ospf6_prefix_in6_addr(struct in6_addr *in6, const void *prefix_buf,
+ const struct ospf6_prefix *p);
extern void ospf6_prefix_apply_mask(struct ospf6_prefix *op);
extern void ospf6_prefix_options_printbuf(uint8_t prefix_options, char *buf,
int size);
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 28c3459825..5b6691e6bf 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -677,6 +677,10 @@ void ospf6_spf_schedule(struct ospf6 *ospf6, unsigned int reason)
{
unsigned long delay, elapsed, ht;
+ /* OSPF instance does not exist. */
+ if (ospf6 == NULL)
+ return;
+
ospf6_set_spf_reason(ospf6, reason);
if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME)) {
@@ -686,10 +690,6 @@ void ospf6_spf_schedule(struct ospf6 *ospf6, unsigned int reason)
rbuf);
}
- /* OSPF instance does not exist. */
- if (ospf6 == NULL)
- return;
-
/* SPF calculation timer is already scheduled. */
if (ospf6->t_spf_calc) {
if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME))
diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c
index 8369dde822..b1175a2f68 100644
--- a/ospfd/ospf_api.c
+++ b/ospfd/ospf_api.c
@@ -510,17 +510,18 @@ struct msg *new_msg_originate_request(uint32_t seqnum, struct in_addr ifaddr,
struct msg_originate_request *omsg;
unsigned int omsglen;
char buf[OSPF_API_MAX_MSG_SIZE];
+ size_t off_data = offsetof(struct msg_originate_request, data);
+ size_t data_maxs = sizeof(buf) - off_data;
+ struct lsa_header *omsg_data = (struct lsa_header *)&buf[off_data];
omsg = (struct msg_originate_request *)buf;
omsg->ifaddr = ifaddr;
omsg->area_id = area_id;
omsglen = ntohs(data->length);
- if (omsglen
- > sizeof(buf) - offsetof(struct msg_originate_request, data))
- omsglen = sizeof(buf)
- - offsetof(struct msg_originate_request, data);
- memcpy(&omsg->data, data, omsglen);
+ if (omsglen > data_maxs)
+ omsglen = data_maxs;
+ memcpy(omsg_data, data, omsglen);
omsglen += sizeof(struct msg_originate_request)
- sizeof(struct lsa_header);
@@ -630,6 +631,9 @@ struct msg *new_msg_lsa_change_notify(uint8_t msgtype, uint32_t seqnum,
uint8_t buf[OSPF_API_MAX_MSG_SIZE];
struct msg_lsa_change_notify *nmsg;
unsigned int len;
+ size_t off_data = offsetof(struct msg_lsa_change_notify, data);
+ size_t data_maxs = sizeof(buf) - off_data;
+ struct lsa_header *nmsg_data = (struct lsa_header *)&buf[off_data];
assert(data);
@@ -640,10 +644,9 @@ struct msg *new_msg_lsa_change_notify(uint8_t msgtype, uint32_t seqnum,
memset(&nmsg->pad, 0, sizeof(nmsg->pad));
len = ntohs(data->length);
- if (len > sizeof(buf) - offsetof(struct msg_lsa_change_notify, data))
- len = sizeof(buf)
- - offsetof(struct msg_lsa_change_notify, data);
- memcpy(&nmsg->data, data, len);
+ if (len > data_maxs)
+ len = data_maxs;
+ memcpy(nmsg_data, data, len);
len += sizeof(struct msg_lsa_change_notify) - sizeof(struct lsa_header);
return msg_new(msgtype, nmsg, seqnum, len);
diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c
index 37735e3611..8f8900e147 100644
--- a/ospfd/ospf_apiserver.c
+++ b/ospfd/ospf_apiserver.c
@@ -1741,6 +1741,8 @@ struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
struct ospf_lsa *new = NULL;
struct ospf *ospf;
+ assert(lsa);
+
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
assert(ospf);
@@ -1751,6 +1753,7 @@ struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
dump_lsa_key(lsa));
lsa->data->ls_age =
htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
+ goto out;
}
if (IS_LSA_MAXAGE(lsa)) {
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index d425624862..c799a4b30f 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -582,7 +582,7 @@ static int ospf_ase_route_match_same(struct route_table *rt,
/* Check each path. */
for (n1 = listhead(or->paths), n2 = listhead(newor->paths); n1 && n2;
- n1 = listnextnode(n1), n2 = listnextnode(n2)) {
+ n1 = listnextnode_unchecked(n1), n2 = listnextnode_unchecked(n2)) {
op = listgetdata(n1);
newop = listgetdata(n2);
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index b964bbab74..b36f2f4652 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -170,8 +170,8 @@ int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix,
/* Check each path. */
for (n1 = listhead(or->paths),
n2 = listhead(newor->paths);
- n1 && n2;
- n1 = listnextnode(n1), n2 = listnextnode(n2)) {
+ n1 && n2; n1 = listnextnode_unchecked(n1),
+ n2 = listnextnode_unchecked(n2)) {
op = listgetdata(n1);
newop = listgetdata(n2);
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index 2b1b328617..86125d0c76 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -2051,12 +2051,11 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
struct tlv_header *tlvh0,
uint16_t subtotal, uint16_t total)
{
- struct tlv_header *tlvh, *next;
+ struct tlv_header *tlvh;
uint16_t sum = subtotal;
for (tlvh = tlvh0; sum < total;
- tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
- next = NULL;
+ tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case TE_LINK_SUBTLV_LINK_TYPE:
sum += show_vty_link_subtlv_link_type(vty, tlvh);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 31cffea7f2..ddf9133ed9 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2412,8 +2412,8 @@ DEFUN (ospf_neighbor_poll_interval,
int idx_poll = 3;
int idx_pri = 5;
struct in_addr nbr_addr;
- unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
- unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT;
+ unsigned int priority;
+ unsigned int interval;
if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
@@ -2422,8 +2422,8 @@ DEFUN (ospf_neighbor_poll_interval,
interval = strtoul(argv[idx_poll]->arg, NULL, 10);
- if (argc > 4)
- priority = strtoul(argv[idx_pri]->arg, NULL, 10);
+ priority = argc > 4 ? strtoul(argv[idx_pri]->arg, NULL, 10)
+ : OSPF_NEIGHBOR_PRIORITY_DEFAULT;
ospf_nbr_nbma_set(ospf, nbr_addr);
ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval);
@@ -8166,6 +8166,11 @@ DEFUN (ospf_redistribute_instance_source,
source = proto_redistnum(AFI_IP, argv[idx_ospf_table]->text);
+ if (source < 0) {
+ vty_out(vty, "Unknown instance redistribution\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
instance = strtoul(argv[idx_number]->arg, NULL, 10);
if ((source == ZEBRA_ROUTE_OSPF) && !ospf->instance) {
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 141ece9c7a..0a7776cced 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -670,6 +670,16 @@ int ospf_redistribute_set(struct ospf *ospf, int type, unsigned short instance,
struct ospf_redist *red;
red = ospf_redist_lookup(ospf, type, instance);
+
+ if (red == NULL) {
+ zlog_err(
+ "Redistribute[%s][%d]: Lookup failed Type[%d] , Metric[%d]",
+ ospf_redist_string(type), instance,
+ metric_type(ospf, type, instance),
+ metric_value(ospf, type, instance));
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
if (ospf_is_type_redistributed(ospf, type, instance)) {
if (mtype != red->dmetric.type) {
red->dmetric.type = mtype;
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 4cf38439c6..f315421843 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -243,13 +243,14 @@ static struct ospf *ospf_new(unsigned short instance, const char *name)
zlog_debug(
"%s: Create new ospf instance with vrf_name %s vrf_id %u",
__PRETTY_FUNCTION__, name, new->vrf_id);
- if (vrf)
- ospf_vrf_link(new, vrf);
} else {
new->vrf_id = VRF_DEFAULT;
vrf = vrf_lookup_by_id(VRF_DEFAULT);
- ospf_vrf_link(new, vrf);
}
+
+ if (vrf)
+ ospf_vrf_link(new, vrf);
+
ospf_zebra_vrf_register(new);
new->abr_type = OSPF_ABR_DEFAULT;
diff --git a/pimd/mtracebis.c b/pimd/mtracebis.c
index 731fdb1beb..c0d95aeed9 100644
--- a/pimd/mtracebis.c
+++ b/pimd/mtracebis.c
@@ -266,6 +266,8 @@ static int recv_response(int fd, int *hops, struct igmp_mtrace *mtracer)
int mtrace_len;
int responses;
unsigned short sum;
+ size_t mtrace_off;
+ size_t ip_len;
recvd = recvfrom(fd, mtrace_buf, IP_AND_MTRACE_BUF_LEN, 0, NULL, 0);
@@ -292,17 +294,20 @@ static int recv_response(int fd, int *hops, struct igmp_mtrace *mtracer)
if (sum != in_cksum(ip, ip->ip_hl * 4))
return -1;
- mtrace = (struct igmp_mtrace *)(mtrace_buf + (4 * ip->ip_hl));
-
- mtrace_len = ntohs(ip->ip_len) - ip->ip_hl * 4;
-
- if ((char *)mtrace + mtrace_len
- > (char *)mtrace_buf + IP_AND_MTRACE_BUF_LEN)
+ /* Header overflow check */
+ mtrace_off = 4 * ip->ip_hl;
+ if (mtrace_off > MTRACE_BUF_LEN)
return -1;
- if (mtrace_len < (int)MTRACE_HDR_SIZE)
+ /* Underflow/overflow check */
+ ip_len = ntohs(ip->ip_len);
+ if (ip_len < mtrace_off || ip_len < MTRACE_HDR_SIZE
+ || ip_len > MTRACE_BUF_LEN)
return -1;
+ mtrace_len = ip_len - mtrace_off;
+ mtrace = (struct igmp_mtrace *)(mtrace_buf + mtrace_off);
+
sum = mtrace->checksum;
mtrace->checksum = 0;
if (sum != in_cksum(mtrace, mtrace_len)) {
@@ -336,7 +341,7 @@ static int wait_for_response(int fd, int *hops, struct igmp_mtrace *mtrace,
{
fd_set readfds;
struct timeval timeout;
- int ret = -1;
+ int ret;
long msec, rmsec, tmsec;
FD_ZERO(&readfds);
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 55222ecddb..123c47568c 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -4504,8 +4504,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
json_object *json_source = NULL;
json_object *json_oil = NULL;
json_object *json_ifp_out = NULL;
- int found_oif = 0;
- int first = 1;
+ int found_oif;
+ int first;
char grp_str[INET_ADDRSTRLEN];
char src_str[INET_ADDRSTRLEN];
char in_ifname[INTERFACE_NAMSIZ + 1];
diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c
index 673e2ca5b8..95d0278a34 100644
--- a/pimd/pim_igmp_mtrace.c
+++ b/pimd/pim_igmp_mtrace.c
@@ -817,7 +817,7 @@ int igmp_mtrace_recv_qry_req(struct igmp_sock *igmp, struct ip *ip_hdr,
* Previous-hop router not known,
* packet is sent to an appropriate multicast address
*/
- inet_aton(MCAST_ALL_ROUTERS, &nh_addr);
+ (void)inet_aton(MCAST_ALL_ROUTERS, &nh_addr);
}
/* 6.2.2 8. If this router is the Rendez-vous Point */
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index de09b070f4..f506875282 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -521,7 +521,7 @@ int pim_msg_send(int fd, struct in_addr src, struct in_addr dst,
socklen_t tolen;
unsigned char buffer[10000];
unsigned char *msg_start;
- uint8_t ttl = MAXTTL;
+ uint8_t ttl;
struct pim_msg_header *header;
struct ip *ip;
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 92c27106d5..90dc7808eb 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -799,11 +799,11 @@ static int rip_auth_simple_password(struct rte *rte, struct sockaddr_in *from,
struct interface *ifp)
{
struct rip_interface *ri;
- char *auth_str = (char *)&rte->prefix;
+ char *auth_str = (char *)rte + offsetof(struct rte, prefix);
int i;
/* reject passwords with zeros in the middle of the string */
- for (i = strlen(auth_str); i < 16; i++) {
+ for (i = strnlen(auth_str, 16); i < 16; i++) {
if (auth_str[i] != '\0')
return 0;
}
diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c
index a478b416bf..22a19da0b3 100644
--- a/sharpd/sharp_main.c
+++ b/sharpd/sharp_main.c
@@ -51,7 +51,6 @@ uint32_t installed_routes = 0;
uint32_t removed_routes = 0;
zebra_capabilities_t _caps_p[] = {
- ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN,
};
struct zebra_privs_t sharp_privs = {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9b60312cef..32d2db768a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -102,8 +102,6 @@ lib/cli/test_commands_defun.c: ../vtysh/vtysh_cmd.c
isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@"
-isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT): \
- isisd/test_fuzz_isis_tlv_tests.h
noinst_HEADERS = \
./helpers/c/prng.h \
@@ -146,6 +144,9 @@ bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c
bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c
+nodist_isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv_tests.h
+BUILT_SOURCES=isisd/test_fuzz_isis_tlv_tests.h
+CLEANFILES=isisd/test_fuzz_isis_tlv_tests.h
isisd_test_fuzz_isis_tlv_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/tests/isisd
isisd_test_isis_vertex_queue_SOURCES = isisd/test_isis_vertex_queue.c
diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c
index 8c3fe0c3c5..de58e0a20e 100644
--- a/tools/start-stop-daemon.c
+++ b/tools/start-stop-daemon.c
@@ -1024,8 +1024,10 @@ int main(int argc, char **argv)
close(i);
/* change tty */
fd = open("/dev/tty", O_RDWR);
- ioctl(fd, TIOCNOTTY, 0);
- close(fd);
+ if (fd >= 0) {
+ ioctl(fd, TIOCNOTTY, 0);
+ close(fd);
+ }
chdir("/");
umask(022); /* set a default for dumb programs */
setpgid(0, 0); /* set the process group */
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 309493b13e..0697cd8b75 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2415,10 +2415,11 @@ DEFUNSH(VTYSH_ALL, vtysh_log_syslog, vtysh_log_syslog_cmd,
}
DEFUNSH(VTYSH_ALL, no_vtysh_log_syslog, no_vtysh_log_syslog_cmd,
- "no log syslog [LEVEL]", NO_STR
+ "no log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
+ NO_STR
"Logging control\n"
"Cancel logging to syslog\n"
- "Logging level\n")
+ LOG_LEVEL_DESC)
{
return CMD_SUCCESS;
}
@@ -2440,24 +2441,6 @@ DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd,
return CMD_SUCCESS;
}
-DEFUNSH_DEPRECATED(
- VTYSH_ALL, vtysh_log_trap, vtysh_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)
-{
- return CMD_SUCCESS;
-}
-
-DEFUNSH_DEPRECATED(VTYSH_ALL, no_vtysh_log_trap, no_vtysh_log_trap_cmd,
- "no log trap [LEVEL]", NO_STR
- "Logging control\n"
- "Permit all logging information\n"
- "Logging level\n")
-{
- return CMD_SUCCESS;
-}
-
DEFUNSH(VTYSH_ALL, vtysh_log_record_priority, vtysh_log_record_priority_cmd,
"log record-priority",
"Logging control\n"
@@ -2634,8 +2617,13 @@ static void backup_config_file(const char *fbackup)
strcat(integrate_sav, CONF_BACKUP_EXT);
/* Move current configuration file to backup config file. */
- unlink(integrate_sav);
- rename(fbackup, integrate_sav);
+ if (unlink(integrate_sav) != 0) {
+ vty_out(vty, "Warning: %s unlink failed\n", integrate_sav);
+ }
+ if (rename(fbackup, integrate_sav) != 0) {
+ vty_out(vty, "Error renaming %s to %s\n", fbackup,
+ integrate_sav);
+ }
free(integrate_sav);
}
@@ -3760,8 +3748,6 @@ void vtysh_init_vty(void)
install_element(CONFIG_NODE, &no_vtysh_log_monitor_cmd);
install_element(CONFIG_NODE, &vtysh_log_syslog_cmd);
install_element(CONFIG_NODE, &no_vtysh_log_syslog_cmd);
- install_element(CONFIG_NODE, &vtysh_log_trap_cmd);
- install_element(CONFIG_NODE, &no_vtysh_log_trap_cmd);
install_element(CONFIG_NODE, &vtysh_log_facility_cmd);
install_element(CONFIG_NODE, &no_vtysh_log_facility_cmd);
install_element(CONFIG_NODE, &vtysh_log_record_priority_cmd);
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index e6d324ab6a..5c84219418 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -586,8 +586,13 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return 0;
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
- if (len < 0)
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
+ __PRETTY_FUNCTION__,
+ h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg)));
return -1;
+ }
/* We are interested in some AF_BRIDGE notifications. */
if (ifi->ifi_family == AF_BRIDGE)
@@ -893,8 +898,13 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return 0;
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- if (len < 0)
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
+ __PRETTY_FUNCTION__,
+ h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct ifaddrmsg)));
return -1;
+ }
memset(tb, 0, sizeof tb);
netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
@@ -1105,8 +1115,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
}
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
- if (len < 0)
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size %d %zu",
+ __PRETTY_FUNCTION__, h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg)));
return -1;
+ }
/* We are interested in some AF_BRIDGE notifications. */
if (ifi->ifi_family == AF_BRIDGE)
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 0e79b82533..d9c6631845 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -498,6 +498,75 @@ const char *nl_rttype_to_str(uint8_t rttype)
return lookup_msg(rttype_str, rttype, "");
}
+#define NL_OK(nla, len) \
+ ((len) >= (int)sizeof(struct nlattr) \
+ && (nla)->nla_len >= sizeof(struct nlattr) \
+ && (nla)->nla_len <= (len))
+#define NL_NEXT(nla, attrlen) \
+ ((attrlen) -= RTA_ALIGN((nla)->nla_len), \
+ (struct nlattr *)(((char *)(nla)) + RTA_ALIGN((nla)->nla_len)))
+#define NL_RTA(r) \
+ ((struct nlattr *)(((char *)(r)) \
+ + NLMSG_ALIGN(sizeof(struct nlmsgerr))))
+
+static void netlink_parse_nlattr(struct nlattr **tb, int max,
+ struct nlattr *nla, int len)
+{
+ while (NL_OK(nla, len)) {
+ if (nla->nla_type <= max)
+ tb[nla->nla_type] = nla;
+ nla = NL_NEXT(nla, len);
+ }
+}
+
+static void netlink_parse_extended_ack(struct nlmsghdr *h)
+{
+ struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
+ const struct nlmsgerr *err =
+ (const struct nlmsgerr *)((uint8_t *)h
+ + NLMSG_ALIGN(
+ sizeof(struct nlmsghdr)));
+ const struct nlmsghdr *err_nlh = NULL;
+ uint32_t hlen = sizeof(*err);
+ const char *msg = NULL;
+ uint32_t off = 0;
+
+ if (!(h->nlmsg_flags & NLM_F_CAPPED))
+ hlen += h->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
+
+ memset(tb, 0, sizeof(tb));
+ netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, NL_RTA(h), hlen);
+
+ if (tb[NLMSGERR_ATTR_MSG])
+ msg = (const char *)RTA_DATA(tb[NLMSGERR_ATTR_MSG]);
+
+ if (tb[NLMSGERR_ATTR_OFFS]) {
+ off = *(uint32_t *)RTA_DATA(tb[NLMSGERR_ATTR_OFFS]);
+
+ if (off > h->nlmsg_len) {
+ zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS\n");
+ } else if (!(h->nlmsg_flags & NLM_F_CAPPED)) {
+ /*
+ * Header of failed message
+ * we are not doing anything currently with it
+ * but noticing it for later.
+ */
+ err_nlh = &err->msg;
+ zlog_warn("%s: Received %d extended Ack",
+ __PRETTY_FUNCTION__, err_nlh->nlmsg_type);
+ }
+ }
+
+ if (msg && *msg != '\0') {
+ bool is_err = !!err->error;
+
+ if (is_err)
+ zlog_err("Extended Error: %s", msg);
+ else
+ zlog_warn("Extended Warning: %s", msg);
+ }
+}
+
/*
* netlink_parse_info
*
@@ -582,6 +651,23 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
int errnum = err->error;
int msg_type = err->msg.nlmsg_type;
+ if (h->nlmsg_len
+ < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
+ zlog_err("%s error: message truncated",
+ nl->name);
+ return -1;
+ }
+
+ /*
+ * Parse the extended information before
+ * we actually handle it.
+ * At this point in time we do not
+ * do anything other than report the
+ * issue.
+ */
+ if (h->nlmsg_flags & NLM_F_ACK_TLVS)
+ netlink_parse_extended_ack(h);
+
/* If the error field is zero, then this is an
* ACK */
if (err->error == 0) {
@@ -603,13 +689,6 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
continue;
}
- if (h->nlmsg_len
- < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
- zlog_err("%s error: message truncated",
- nl->name);
- return -1;
- }
-
/* Deal with errors that occur because of races
* in link handling */
if (nl == &zns->netlink_cmd
@@ -692,6 +771,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
error = (*filter)(h, zns->ns_id, startup);
if (error < 0) {
zlog_err("%s filter function error", nl->name);
+ zlog_backtrace(LOG_ERR);
ret = error;
}
}
@@ -836,6 +916,9 @@ int netlink_request(struct nlsock *nl, struct nlmsghdr *n)
void kernel_init(struct zebra_ns *zns)
{
unsigned long groups;
+#if defined SOL_NETLINK
+ int one, ret;
+#endif
/*
* Initialize netlink sockets
@@ -866,6 +949,25 @@ void kernel_init(struct zebra_ns *zns)
zns->netlink_cmd.sock = -1;
netlink_socket(&zns->netlink_cmd, 0, zns->ns_id);
+ /*
+ * SOL_NETLINK is not available on all platforms yet
+ * apparently. It's in bits/socket.h which I am not
+ * sure that we want to pull into our build system.
+ */
+#if defined SOL_NETLINK
+ /*
+ * Let's tell the kernel that we want to receive extended
+ * ACKS over our command socket
+ */
+ one = 1;
+ ret = setsockopt(zns->netlink_cmd.sock, SOL_NETLINK, NETLINK_EXT_ACK,
+ &one, sizeof(one));
+
+ if (ret < 0)
+ zlog_notice("Registration for extended ACK failed : %d %s",
+ errno, safe_strerror(errno));
+#endif
+
/* Register kernel socket. */
if (zns->netlink.sock > 0) {
/* Only want non-blocking on the netlink event socket */
@@ -880,6 +982,7 @@ void kernel_init(struct zebra_ns *zns)
netlink_install_filter(zns->netlink.sock,
zns->netlink_cmd.snl.nl_pid);
zns->t_netlink = NULL;
+
thread_add_read(zebrad.master, kernel_read, zns,
zns->netlink.sock, &zns->t_netlink);
}
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index a5f288f541..9033491549 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -295,8 +295,12 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
}
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
- if (len < 0)
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size %d %zu",
+ __PRETTY_FUNCTION__, h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
return -1;
+ }
memset(tb, 0, sizeof tb);
netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
@@ -747,8 +751,13 @@ int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return 0;
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
- if (len < 0)
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
+ __PRETTY_FUNCTION__,
+ h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
return -1;
+ }
if (rtm->rtm_type == RTN_MULTICAST)
netlink_route_change_read_multicast(h, ns_id, startup);
@@ -2356,8 +2365,12 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
/* Length validity. */
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
- if (len < 0)
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size %d %zu",
+ __PRETTY_FUNCTION__, h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct ndmsg)));
return -1;
+ }
/* Is this a notification for the MAC FDB or IP neighbor table? */
ndm = NLMSG_DATA(h);
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index bcffdf4722..c7a8517e17 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -196,8 +196,12 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
return 0;
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct fib_rule_hdr));
- if (len < 0)
+ if (len < 0) {
+ zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
+ __PRETTY_FUNCTION__, h->nlmsg_len,
+ (size_t)NLMSG_LENGTH(sizeof(struct fib_rule_hdr)));
return -1;
+ }
frh = NLMSG_DATA(h);
if (frh->family != AF_INET && frh->family != AF_INET6)
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index bb6a565211..d0ea661403 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -212,11 +212,18 @@ static int zebra_ns_notify_read(struct thread *t)
continue;
if (event->mask & IN_DELETE)
return zebra_ns_delete(event->name);
- if (&event->name[event->len] >= &buf[sizeof(buf)]) {
+
+ if (offsetof(struct inotify_event, name) + event->len
+ >= sizeof(buf)) {
zlog_err("NS notify read: buffer underflow");
break;
}
- event->name[event->len] = 0;
+
+ if (strnlen(event->name, event->len) == event->len) {
+ zlog_err("NS notify error: bad event name");
+ break;
+ }
+
netnspath = ns_netns_pathname(NULL, event->name);
if (!netnspath)
continue;