diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/if_netlink.c | 20 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 117 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 19 | ||||
| -rw-r--r-- | zebra/rule_netlink.c | 6 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 29 | ||||
| -rw-r--r-- | zebra/zebra_netns_id.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_netns_notify.c | 12 | ||||
| -rw-r--r-- | zebra/zebra_pbr.c | 174 | ||||
| -rw-r--r-- | zebra/zebra_pbr.h | 15 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 12 | ||||
| -rw-r--r-- | zebra/zserv.c | 7 |
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; } |
