summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-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/zapi_msg.c29
-rw-r--r--zebra/zebra_netns_id.c2
-rw-r--r--zebra/zebra_netns_notify.c12
-rw-r--r--zebra/zebra_pbr.c174
-rw-r--r--zebra/zebra_pbr.h15
-rw-r--r--zebra/zebra_rib.c12
-rw-r--r--zebra/zserv.c7
11 files changed, 381 insertions, 32 deletions
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/zapi_msg.c b/zebra/zapi_msg.c
index 853a83373d..6e0d86d668 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -521,6 +521,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
struct zapi_nexthop *api_nh;
struct nexthop *nexthop;
int count = 0;
+ afi_t afi;
memset(&api, 0, sizeof(api));
api.vrf_id = re->vrf_id;
@@ -528,6 +529,24 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
api.instance = re->instance;
api.flags = re->flags;
+ afi = family2afi(p->family);
+ switch (afi) {
+ case AFI_IP:
+ if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+ client->redist_v4_add_cnt++;
+ else
+ client->redist_v4_del_cnt++;
+ break;
+ case AFI_IP6:
+ if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
+ client->redist_v6_add_cnt++;
+ else
+ client->redist_v6_del_cnt++;
+ break;
+ default:
+ break;
+ }
+
/* Prefix. */
api.prefix = *p;
if (src_p) {
@@ -2896,9 +2915,9 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
if (!is_default_prefix(&zpi.dst))
zpi.filter_bm |= PBR_FILTER_DST_IP;
- if (zpi.dst_port_min != 0)
+ if (zpi.dst_port_min != 0 || zpi.proto == IPPROTO_ICMP)
zpi.filter_bm |= PBR_FILTER_DST_PORT;
- if (zpi.src_port_min != 0)
+ if (zpi.src_port_min != 0 || zpi.proto == IPPROTO_ICMP)
zpi.filter_bm |= PBR_FILTER_SRC_PORT;
if (zpi.dst_port_max != 0)
zpi.filter_bm |= PBR_FILTER_DST_PORT_RANGE;
@@ -2938,6 +2957,12 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS)
STREAM_GETL(s, zpi.action);
STREAM_GETL(s, zpi.fwmark);
STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
+ STREAM_GETW(s, zpi.pkt_len_min);
+ STREAM_GETW(s, zpi.pkt_len_max);
+ STREAM_GETW(s, zpi.tcp_flags);
+ STREAM_GETW(s, zpi.tcp_mask_flags);
+ STREAM_GETC(s, zpi.dscp_value);
+ STREAM_GETC(s, zpi.fragment);
STREAM_GETL(s, zpi.nb_interface);
zebra_pbr_iptable_update_interfacelist(s, &zpi);
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 317b02f601..96e6df34da 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -307,7 +307,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
nlh = (struct nlmsghdr *)((char *)nlh
+ NETLINK_ALIGN(
nlh->nlmsg_len));
- } while (len != 0 && return_nsid != NS_UNKNOWN && ret == 0);
+ } while (len != 0 && ret == 0);
}
close(fd);
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 30f850597c..d0ea661403 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -212,6 +212,18 @@ static int zebra_ns_notify_read(struct thread *t)
continue;
if (event->mask & IN_DELETE)
return zebra_ns_delete(event->name);
+
+ if (offsetof(struct inotify_event, name) + event->len
+ >= sizeof(buf)) {
+ zlog_err("NS notify read: buffer underflow");
+ break;
+ }
+
+ 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;
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index d511c8c6ec..74ef25b031 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -44,6 +44,63 @@ static const struct message ipset_type_msg[] = {
{0}
};
+const struct message icmp_typecode_str[] = {
+ { 0 << 8, "echo-reply"},
+ { 0 << 8, "pong"},
+ { 3 << 8, "network-unreachable"},
+ { (3 << 8) + 1, "host-unreachable"},
+ { (3 << 8) + 2, "protocol-unreachable"},
+ { (3 << 8) + 3, "port-unreachable"},
+ { (3 << 8) + 4, "fragmentation-needed"},
+ { (3 << 8) + 5, "source-route-failed"},
+ { (3 << 8) + 6, "network-unknown"},
+ { (3 << 8) + 7, "host-unknown"},
+ { (3 << 8) + 9, "network-prohibited"},
+ { (3 << 8) + 10, "host-prohibited"},
+ { (3 << 8) + 11, "TOS-network-unreachable"},
+ { (3 << 8) + 12, "TOS-host-unreachable"},
+ { (3 << 8) + 13, "communication-prohibited"},
+ { (3 << 8) + 14, "host-precedence-violation"},
+ { (3 << 8) + 15, "precedence-cutoff"},
+ { 4 << 8, "source-quench"},
+ { 5 << 8, "network-redirect"},
+ { (5 << 8) + 1, "host-redirect"},
+ { (5 << 8) + 2, "TOS-network-redirect"},
+ { (5 << 8) + 3, "TOS-host-redirect"},
+ { 8 << 8, "echo-request"},
+ { 8 << 8, "ping"},
+ { 9 << 8, "router-advertisement"},
+ { 10 << 8, "router-solicitation"},
+ { 11 << 8, "ttl-zero-during-transit"},
+ { (11 << 8) + 1, "ttl-zero-during-reassembly"},
+ { 12 << 8, "ip-header-bad"},
+ { (12 << 8) + 1, "required-option-missing"},
+ { 13 << 8, "timestamp-request"},
+ { 14 << 8, "timestamp-reply"},
+ { 17 << 8, "address-mask-request"},
+ { 18 << 8, "address-mask-reply"},
+ {0}
+};
+
+/* definitions */
+static const struct message tcp_value_str[] = {
+ {TCP_HEADER_FIN, "FIN"},
+ {TCP_HEADER_SYN, "SYN"},
+ {TCP_HEADER_RST, "RST"},
+ {TCP_HEADER_PSH, "PSH"},
+ {TCP_HEADER_ACK, "ACK"},
+ {TCP_HEADER_URG, "URG"},
+ {0}
+};
+
+static const struct message fragment_value_str[] = {
+ {1, "dont-fragment"},
+ {2, "is-fragment"},
+ {4, "first-fragment"},
+ {8, "last-fragment"},
+ {0}
+};
+
/* static function declarations */
DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns,
struct zebra_pbr_ipset_entry *ipset,
@@ -322,6 +379,12 @@ uint32_t zebra_pbr_iptable_hash_key(void *arg)
key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE,
0x63ab42de);
key = jhash_1word(iptable->fwmark, key);
+ key = jhash_1word(iptable->pkt_len_min, key);
+ key = jhash_1word(iptable->pkt_len_max, key);
+ key = jhash_1word(iptable->tcp_flags, key);
+ key = jhash_1word(iptable->tcp_mask_flags, key);
+ key = jhash_1word(iptable->dscp_value, key);
+ key = jhash_1word(iptable->fragment, key);
return jhash_3words(iptable->filter_bm, iptable->type,
iptable->unique, key);
}
@@ -346,6 +409,18 @@ int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
if (strncmp(r1->ipset_name, r2->ipset_name,
ZEBRA_IPSET_NAME_SIZE))
return 0;
+ if (r1->pkt_len_min != r2->pkt_len_min)
+ return 0;
+ if (r1->pkt_len_max != r2->pkt_len_max)
+ return 0;
+ if (r1->tcp_flags != r2->tcp_flags)
+ return 0;
+ if (r1->tcp_mask_flags != r2->tcp_mask_flags)
+ return 0;
+ if (r1->dscp_value != r2->dscp_value)
+ return 0;
+ if (r1->fragment != r2->fragment)
+ return 0;
return 1;
}
@@ -515,7 +590,7 @@ struct pbr_ipset_name_lookup {
char ipset_name[ZEBRA_IPSET_NAME_SIZE];
};
-static const char *zebra_pbr_ipset_type2str(uint32_t type)
+const char *zebra_pbr_ipset_type2str(uint32_t type)
{
return lookup_msg(ipset_type_msg, type,
"Unrecognized IPset Type");
@@ -773,6 +848,30 @@ static const char *zebra_pbr_prefix2str(union prefixconstptr pu,
return prefix2str(pu, str, size);
}
+static void zebra_pbr_display_icmp(struct vty *vty,
+ struct zebra_pbr_ipset_entry *zpie)
+{
+ char decoded_str[20];
+ uint16_t port;
+
+ /* range icmp type */
+ if (zpie->src_port_max || zpie->dst_port_max) {
+ vty_out(vty, ":icmp:[type <%d:%d>;code <%d:%d>",
+ zpie->src_port_min, zpie->src_port_max,
+ zpie->dst_port_min, zpie->dst_port_max);
+ } else {
+ port = ((zpie->src_port_min << 8) & 0xff00) +
+ (zpie->dst_port_min & 0xff);
+ memset(decoded_str, 0, sizeof(decoded_str));
+ sprintf(decoded_str, "%d/%d",
+ zpie->src_port_min,
+ zpie->dst_port_min);
+ vty_out(vty, ":icmp:%s",
+ lookup_msg(icmp_typecode_str,
+ port, decoded_str));
+ }
+}
+
static void zebra_pbr_display_port(struct vty *vty, uint32_t filter_bm,
uint16_t port_min, uint16_t port_max,
uint8_t proto)
@@ -816,7 +915,8 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
vty_out(vty, "\tfrom %s", buf);
- if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
+ if (zpie->filter_bm & PBR_FILTER_SRC_PORT &&
+ zpie->proto != IPPROTO_ICMP)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->src_port_min,
zpie->src_port_max,
@@ -824,11 +924,14 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
vty_out(vty, " to ");
zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
vty_out(vty, "%s", buf);
- if (zpie->filter_bm & PBR_FILTER_DST_PORT)
+ if (zpie->filter_bm & PBR_FILTER_DST_PORT &&
+ zpie->proto != IPPROTO_ICMP)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->dst_port_min,
zpie->dst_port_max,
zpie->proto);
+ if (zpie->proto == IPPROTO_ICMP)
+ zebra_pbr_display_icmp(vty, zpie);
} else if ((zpi->type == IPSET_NET) ||
(zpi->type == IPSET_NET_PORT)) {
char buf[PREFIX_STRLEN];
@@ -837,7 +940,8 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
vty_out(vty, "\tfrom %s", buf);
}
- if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
+ if (zpie->filter_bm & PBR_FILTER_SRC_PORT &&
+ zpie->proto != IPPROTO_ICMP)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->src_port_min,
zpie->src_port_max,
@@ -846,11 +950,14 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
vty_out(vty, "\tto %s", buf);
}
- if (zpie->filter_bm & PBR_FILTER_DST_PORT)
+ if (zpie->filter_bm & PBR_FILTER_DST_PORT &&
+ zpie->proto != IPPROTO_ICMP)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->dst_port_min,
zpie->dst_port_max,
zpie->proto);
+ if (zpie->proto == IPPROTO_ICMP)
+ zebra_pbr_display_icmp(vty, zpie);
}
vty_out(vty, " (%u)\n", zpie->unique);
@@ -882,6 +989,26 @@ static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg)
return HASHWALK_CONTINUE;
}
+size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len,
+ uint16_t tcp_val)
+{
+ size_t len_written = 0;
+ static struct message nt = {0};
+ const struct message *pnt;
+ int incr = 0;
+
+ for (pnt = tcp_value_str;
+ memcmp(pnt, &nt, sizeof(struct message)); pnt++)
+ if (pnt->key & tcp_val) {
+ len_written += snprintf(buffer + len_written,
+ len - len_written,
+ "%s%s", incr ?
+ ",":"", pnt->str);
+ incr++;
+ }
+ return len_written;
+}
+
/*
*/
void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname)
@@ -946,7 +1073,42 @@ static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg)
vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name,
iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect",
iptable->unique);
-
+ if (iptable->pkt_len_min || iptable->pkt_len_max) {
+ if (!iptable->pkt_len_max)
+ vty_out(vty, "\t pkt len %u\n",
+ iptable->pkt_len_min);
+ else
+ vty_out(vty, "\t pkt len [%u;%u]\n",
+ iptable->pkt_len_min,
+ iptable->pkt_len_max);
+ }
+ if (iptable->tcp_flags || iptable->tcp_mask_flags) {
+ char tcp_flag_str[64];
+ char tcp_flag_mask_str[64];
+
+ zebra_pbr_tcpflags_snprintf(tcp_flag_str,
+ sizeof(tcp_flag_str),
+ iptable->tcp_flags);
+ zebra_pbr_tcpflags_snprintf(tcp_flag_mask_str,
+ sizeof(tcp_flag_mask_str),
+ iptable->tcp_mask_flags);
+ vty_out(vty, "\t tcpflags [%s/%s]\n",
+ tcp_flag_str, tcp_flag_mask_str);
+ }
+ if (iptable->filter_bm & (MATCH_DSCP_SET | MATCH_DSCP_INVERSE_SET)) {
+ vty_out(vty, "\t dscp %s %d\n",
+ iptable->filter_bm & MATCH_DSCP_INVERSE_SET ?
+ "not" : "", iptable->dscp_value);
+ }
+ if (iptable->fragment) {
+ char val_str[10];
+
+ sprintf(val_str, "%d", iptable->fragment);
+ vty_out(vty, "\t fragment%s %s\n",
+ iptable->filter_bm & MATCH_FRAGMENT_INVERSE_SET ?
+ " not" : "", lookup_msg(fragment_value_str,
+ iptable->fragment, val_str));
+ }
ret = hook_call(zebra_pbr_iptable_wrap_script_get_stat,
zns, iptable, &pkts, &bytes);
if (ret && pkts > 0)
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index 6cbafd6daa..fd83502ae1 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -91,8 +91,10 @@ struct zebra_pbr_ipset_entry {
struct prefix src;
struct prefix dst;
+ /* udp/tcp src port or icmp type */
uint16_t src_port_min;
uint16_t src_port_max;
+ /* udp/tcp dst port or icmp code */
uint16_t dst_port_min;
uint16_t dst_port_max;
@@ -131,6 +133,13 @@ struct zebra_pbr_iptable {
uint32_t action;
+ uint16_t pkt_len_min;
+ uint16_t pkt_len_max;
+ uint16_t tcp_flags;
+ uint16_t tcp_mask_flags;
+ uint8_t dscp_value;
+ uint8_t fragment;
+
uint32_t nb_interface;
struct list *interface_name_list;
@@ -138,6 +147,10 @@ struct zebra_pbr_iptable {
char ipset_name[ZEBRA_IPSET_NAME_SIZE];
};
+extern const struct message icmp_typecode_str[];
+
+const char *zebra_pbr_ipset_type2str(uint32_t type);
+
void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule);
void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule);
void zebra_pbr_create_ipset(struct zebra_ns *zns,
@@ -225,6 +238,8 @@ extern void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname);
extern void zebra_pbr_show_iptable(struct vty *vty);
extern void zebra_pbr_iptable_update_interfacelist(struct stream *s,
struct zebra_pbr_iptable *zpi);
+size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len,
+ uint16_t tcp_val);
DECLARE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns,
struct zebra_pbr_ipset_entry *ipset,
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index bd00823ed8..8935956b25 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1428,18 +1428,14 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (new != old)
zlog_debug(
"%u:%s: Deleting route rn %p, re %p (type %d) "
- "old %p (type %d) - %s",
+ "old %p (type %d) - nexthop inactive",
zvrf_id(zvrf), buf, rn, new,
- new->type, old, old->type,
- nh_active ? "install failed"
- : "nexthop inactive");
+ new->type, old, old->type);
else
zlog_debug(
- "%u:%s: Deleting route rn %p, re %p (type %d) - %s",
+ "%u:%s: Deleting route rn %p, re %p (type %d) - nexthop inactive",
zvrf_id(zvrf), buf, rn, new,
- new->type,
- nh_active ? "install failed"
- : "nexthop inactive");
+ new->type);
}
/* If labeled-unicast route, uninstall transit LSP. */
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 14e0db40bf..b297f75ed9 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -198,7 +198,7 @@ static int zserv_write(struct thread *thread)
{
struct zserv *client = THREAD_ARG(thread);
struct stream *msg;
- uint32_t wcmd;
+ uint32_t wcmd = 0;
struct stream_fifo *cache;
/* If we have any data pending, try to flush it first */
@@ -939,6 +939,11 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt);
vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt);
+#if defined DEV_BUILD
+ vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
+ client->ibuf_fifo->count, client->ibuf_fifo->max_count,
+ client->obuf_fifo->count, client->obuf_fifo->max_count);
+#endif
vty_out(vty, "\n");
return;
}