#include "lib/vrf.h"
#include "lib/libfrr.h"
#include "lib/sockopt.h"
+#include "lib/lib_errors.h"
#include "zebra/zebra_router.h"
#include "zebra/rib.h"
#include "zebra/zapi_msg.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_mlag.h"
+#include "zebra/connected.h"
/* Encoding helpers -------------------------------------------------------- */
return 1;
}
+/*
+ * Zebra error addition adds error type.
+ *
+ *
+ * 0 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | enum zebra_error_types |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+static void zserv_encode_error(struct stream *s, enum zebra_error_types error)
+{
+ stream_put(s, &error, sizeof(error));
+
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+}
+
/* Send handlers ----------------------------------------------------------- */
/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
struct nexthop *nexthop = NULL;
struct nexthop_group *ng = NULL;
int i, ret;
- vrf_id_t vrf_id = 0;
+ vrf_id_t vrf_id;
struct ipaddr vtep_ip;
+ struct interface *ifp;
s = msg;
if (zapi_route_decode(s, &api) < 0) {
api_nh = &api.nexthops[i];
ifindex_t ifindex = 0;
+ nexthop = NULL;
+
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("nh type %d", api_nh->type);
&api_nh->gate.ipv4, NULL, ifindex,
api_nh->vrf_id);
+ ifp = if_lookup_by_index(ifindex, api_nh->vrf_id);
+ if (ifp && connected_is_unnumbered(ifp))
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
/* Special handling for IPv4 routes sourced from EVPN:
* the nexthop and associated MAC need to be installed.
*/
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
src_p = &api.src_prefix;
+ if (api.safi != SAFI_UNICAST && api.safi != SAFI_MULTICAST) {
+ flog_warn(EC_LIB_ZAPI_MISSMATCH,
+ "%s: Received safi: %d but we can only accept UNICAST or MULTICAST",
+ __func__, api.safi);
+ nexthop_group_delete(&ng);
+ XFREE(MTYPE_RE, re);
+ return;
+ }
ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re, ng);
/* Stats */
client->instance = instance;
}
+ /* Graceful restart processing for client connect */
+ zebra_gr_client_reconnect(client);
zsend_capabilities(client, zvrf);
zebra_vrf_update_all(client);
stream_failure:
s = msg;
STREAM_GETL(s, nlabel);
STREAM_GETC(s, afi);
+
+ if (!(IS_VALID_AFI(afi))) {
+ zlog_warn("Invalid AFI for VRF label: %u", afi);
+ return;
+ }
+
if (nlabel == zvrf->label[afi]) {
/*
* Nothing to do here move along
if (!(zpr.rule.filter.src_ip.family == AF_INET
|| zpr.rule.filter.src_ip.family == AF_INET6)) {
- zlog_warn("Unsupported PBR source IP family: %s\n",
- family2str(zpr.rule.filter.src_ip.family));
+ zlog_warn(
+ "Unsupported PBR source IP family: %s (%" PRIu8
+ ")\n",
+ family2str(zpr.rule.filter.src_ip.family),
+ zpr.rule.filter.src_ip.family);
return;
}
if (!(zpr.rule.filter.dst_ip.family == AF_INET
|| zpr.rule.filter.dst_ip.family == AF_INET6)) {
- zlog_warn("Unsupported PBR dest IP family: %s\n",
- family2str(zpr.rule.filter.dst_ip.family));
+ zlog_warn("Unsupported PBR IP family: %s (%" PRIu8
+ ")\n",
+ family2str(zpr.rule.filter.dst_ip.family),
+ zpr.rule.filter.dst_ip.family);
return;
}
return;
}
+static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
+ struct zmsghdr *bad_hdr)
+{
+
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ zclient_create_header(s, ZEBRA_ERROR, bad_hdr->vrf_id);
+
+ zserv_encode_error(s, error);
+
+ client->error_cnt++;
+ zserv_send_message(client, s);
+}
+
+static void zserv_error_no_vrf(ZAPI_HANDLER_ARGS)
+{
+ if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("ZAPI message specifies unknown VRF: %d",
+ hdr->vrf_id);
+
+ zsend_error_msg(client, ZEBRA_NO_VRF, hdr);
+}
+
+static void zserv_error_invalid_msg_type(ZAPI_HANDLER_ARGS)
+{
+ zlog_info("Zebra received unknown command %d", hdr->command);
+
+ zsend_error_msg(client, ZEBRA_INVALID_MSG_TYPE, hdr);
+}
+
void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_ROUTER_ID_ADD] = zread_router_id_add,
[ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete,
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
+ [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities
};
#if defined(HANDLE_ZAPI_FUZZING)
/* lookup vrf */
zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id);
- if (!zvrf) {
- if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
- zlog_debug("ZAPI message specifies unknown VRF: %d",
- hdr.vrf_id);
- return;
- }
+ if (!zvrf)
+ return zserv_error_no_vrf(client, &hdr, msg, zvrf);
if (hdr.command >= array_size(zserv_handlers)
|| zserv_handlers[hdr.command] == NULL)
- zlog_info("Zebra received unknown command %d", hdr.command);
- else
- zserv_handlers[hdr.command](client, &hdr, msg, zvrf);
+ return zserv_error_invalid_msg_type(client, &hdr, msg, zvrf);
+
+ zserv_handlers[hdr.command](client, &hdr, msg, zvrf);
}