]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/zclient.c
Merge remote-tracking branch 'upstream/master' into evpn-extended-mobility
[mirror_frr.git] / lib / zclient.c
index 48182d6b2c515652e8c176a30eb1f501a2058a96..b2bafcb7d8f831e2c5f8a69037b331cde2ae2a51 100644 (file)
@@ -38,6 +38,7 @@
 #include "sockopt.h"
 #include "pbr.h"
 #include "nexthop_group.h"
+#include "lib_errors.h"
 
 DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient")
 DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs")
@@ -212,9 +213,9 @@ int zclient_socket_connect(struct zclient *zclient)
 
        set_cloexec(sock);
 
-       zclient->privs->change(ZPRIVS_RAISE);
-       setsockopt_so_sendbuf(sock, 1048576);
-       zclient->privs->change(ZPRIVS_LOWER);
+       frr_elevate_privs(zclient->privs) {
+               setsockopt_so_sendbuf(sock, 1048576);
+       }
 
        /* Connect to zebra. */
        ret = connect(sock, (struct sockaddr *)&zclient_addr, zclient_addr_len);
@@ -312,9 +313,9 @@ int zclient_read_header(struct stream *s, int sock, uint16_t *size,
        STREAM_GETW(s, *cmd);
 
        if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) {
-               zlog_err(
-                       "%s: socket %d version mismatch, marker %d, version %d",
-                       __func__, sock, *marker, *version);
+               flog_err(LIB_ERR_ZAPI_MISSMATCH,
+                         "%s: socket %d version mismatch, marker %d, version %d",
+                         __func__, sock, *marker, *version);
                return -1;
        }
 
@@ -675,11 +676,11 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
  * "xdr_encode"-like interface that allows daemon (client) to send
  * a message to zebra server for a route that needs to be
  * added/deleted to the kernel. Info about the route is specified
- * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes
+ * by the caller in a struct zapi_route. zapi_route_encode() then writes
  * the info down the zclient socket using the stream_* functions.
  *
  * The corresponding read ("xdr_decode") function on the server
- * side is zread_ipv4_add()/zread_ipv4_delete().
+ * side is zapi_route_decode().
  *
  *  0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -706,21 +707,16 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
  * is set to 1 and a nexthop of type NEXTHOP_TYPE_BLACKHOLE is the sole
  * nexthop.
  *
- * The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*()
- * infrastructure was built around the traditional (32-bit "gate OR
- * ifindex") nexthop data unit. A special encoding can be used to feed
- * onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route()
- * using the same zapi_ipv4 structure. This is done by setting zapi_ipv4
- * fields as follows:
+ * The original struct zapi_route_*() infrastructure was built around
+ * the traditional (32-bit "gate OR ifindex") nexthop data unit.
+ * A special encoding can be used to feed onlink (64-bit "gate AND ifindex")
+ * nexthops into zapi_route_encode() using the same zapi_route structure.
+ * This is done by setting zapi_route fields as follows:
  *  - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK
  *  - .nexthop_num == .ifindex_num
  *  - .nexthop and .ifindex are filled with gate and ifindex parts of
  *    each compound nexthop, both in the same order
  *
- * zapi_ipv4_route() will produce two nexthop data units for each such
- * interleaved 64-bit nexthop. On the zserv side of the socket it will be
- * mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure.
- *
  * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
  * byte value.
  *
@@ -733,226 +729,6 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
  *
  * XXX: No attention paid to alignment.
  */
-int zapi_ipv4_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv4 *p,
-                   struct zapi_ipv4 *api)
-{
-       int i;
-       int psize;
-       struct stream *s;
-
-       /* Reset stream. */
-       s = zclient->obuf;
-       stream_reset(s);
-
-       /* Some checks for labeled-unicast. The current expectation is that each
-        * nexthop is accompanied by a label in the case of labeled-unicast.
-        */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
-           && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               /* We expect prefixes installed with labels and the number to
-                * match
-                * the number of nexthops.
-                */
-               assert(api->label_num == api->nexthop_num);
-       }
-
-       zclient_create_header(s, cmd, api->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, api->type);
-       stream_putw(s, api->instance);
-       stream_putl(s, api->flags);
-       stream_putc(s, api->message);
-       stream_putw(s, api->safi);
-
-       /* Put prefix information. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (uint8_t *)&p->prefix, psize);
-
-       /* Nexthop, ifindex, distance and metric information. */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               stream_putc(s, api->nexthop_num + api->ifindex_num);
-
-               for (i = 0; i < api->nexthop_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IPV4);
-                       stream_put_in_addr(s, api->nexthop[i]);
-                       /* For labeled-unicast, each nexthop is followed by
-                        * label. */
-                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
-                               stream_putl(s, api->label[i]);
-               }
-               for (i = 0; i < api->ifindex_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                       stream_putl(s, api->ifindex[i]);
-               }
-       }
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
-               stream_putc(s, api->distance);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
-               stream_putl(s, api->metric);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
-               stream_putl(s, api->tag);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
-               stream_putl(s, api->mtu);
-
-       /* Put length at the first point of the stream. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
-       return zclient_send_message(zclient);
-}
-
-int zapi_ipv4_route_ipv6_nexthop(uint8_t cmd, struct zclient *zclient,
-                                struct prefix_ipv4 *p, struct zapi_ipv6 *api)
-{
-       int i;
-       int psize;
-       struct stream *s;
-
-       /* Reset stream. */
-       s = zclient->obuf;
-       stream_reset(s);
-
-       /* Some checks for labeled-unicast. The current expectation is that each
-        * nexthop is accompanied by a label in the case of labeled-unicast.
-        */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
-           && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               /* We expect prefixes installed with labels and the number to
-                * match
-                * the number of nexthops.
-                */
-               assert(api->label_num == api->nexthop_num);
-       }
-
-       zclient_create_header(s, cmd, api->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, api->type);
-       stream_putw(s, api->instance);
-       stream_putl(s, api->flags);
-       stream_putc(s, api->message);
-       stream_putw(s, api->safi);
-
-       /* Put prefix information. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (uint8_t *)&p->prefix, psize);
-
-       /* Nexthop, ifindex, distance and metric information. */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               stream_putc(s, api->nexthop_num + api->ifindex_num);
-
-               for (i = 0; i < api->nexthop_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IPV6);
-                       stream_write(s, (uint8_t *)api->nexthop[i], 16);
-                       /* For labeled-unicast, each nexthop is followed by
-                        * label. */
-                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
-                               stream_putl(s, api->label[i]);
-               }
-               for (i = 0; i < api->ifindex_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                       stream_putl(s, api->ifindex[i]);
-               }
-       }
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
-               stream_putc(s, api->distance);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
-               stream_putl(s, api->metric);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
-               stream_putl(s, api->tag);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
-               stream_putl(s, api->mtu);
-
-       /* Put length at the first point of the stream. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
-       return zclient_send_message(zclient);
-}
-
-int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv6 *p,
-                   struct prefix_ipv6 *src_p, struct zapi_ipv6 *api)
-{
-       int i;
-       int psize;
-       struct stream *s;
-
-       /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL
-        */
-       assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p);
-
-       /* Reset stream. */
-       s = zclient->obuf;
-       stream_reset(s);
-
-       /* Some checks for labeled-unicast. The current expectation is that each
-        * nexthop is accompanied by a label in the case of labeled-unicast.
-        */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
-           && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               /* We expect prefixes installed with labels and the number to
-                * match
-                * the number of nexthops.
-                */
-               assert(api->label_num == api->nexthop_num);
-       }
-
-       zclient_create_header(s, cmd, api->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, api->type);
-       stream_putw(s, api->instance);
-       stream_putl(s, api->flags);
-       stream_putc(s, api->message);
-       stream_putw(s, api->safi);
-
-       /* Put prefix information. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (uint8_t *)&p->prefix, psize);
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
-               psize = PSIZE(src_p->prefixlen);
-               stream_putc(s, src_p->prefixlen);
-               stream_write(s, (uint8_t *)&src_p->prefix, psize);
-       }
-
-       /* Nexthop, ifindex, distance and metric information. */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               stream_putc(s, api->nexthop_num + api->ifindex_num);
-
-               for (i = 0; i < api->nexthop_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IPV6);
-                       stream_write(s, (uint8_t *)api->nexthop[i], 16);
-                       /* For labeled-unicast, each nexthop is followed by
-                        * label. */
-                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
-                               stream_putl(s, api->label[i]);
-               }
-               for (i = 0; i < api->ifindex_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                       stream_putl(s, api->ifindex[i]);
-               }
-       }
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
-               stream_putc(s, api->distance);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
-               stream_putl(s, api->metric);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
-               stream_putl(s, api->tag);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
-               stream_putl(s, api->mtu);
-
-       /* Put length at the first point of the stream. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
-       return zclient_send_message(zclient);
-}
-
 int zclient_route_send(uint8_t cmd, struct zclient *zclient,
                       struct zapi_route *api)
 {
@@ -975,8 +751,6 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
        stream_putl(s, api->flags);
        stream_putc(s, api->message);
        stream_putc(s, api->safi);
-       if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
-               stream_put(s, &(api->rmac), sizeof(struct ethaddr));
 
        /* Put prefix information. */
        stream_putc(s, api->prefix.family);
@@ -1047,12 +821,12 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
                                        char buf[PREFIX2STR_BUFFER];
                                        prefix2str(&api->prefix, buf,
                                                   sizeof(buf));
-                                       zlog_err(
-                                               "%s: prefix %s: can't encode "
-                                               "%u labels (maximum is %u)",
-                                               __func__, buf,
-                                               api_nh->label_num,
-                                               MPLS_MAX_LABELS);
+                                       flog_err(LIB_ERR_ZAPI_ENCODE,
+                                                 "%s: prefix %s: can't encode "
+                                                 "%u labels (maximum is %u)",
+                                                 __func__, buf,
+                                                 api_nh->label_num,
+                                                 MPLS_MAX_LABELS);
                                        return -1;
                                }
 
@@ -1061,6 +835,11 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
                                           api_nh->label_num
                                                   * sizeof(mpls_label_t));
                        }
+
+                       /* Router MAC for EVPN routes. */
+                       if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
+                               stream_put(s, &(api_nh->rmac),
+                                          sizeof(struct ethaddr));
                }
        }
 
@@ -1101,8 +880,6 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
        STREAM_GETL(s, api->flags);
        STREAM_GETC(s, api->message);
        STREAM_GETC(s, api->safi);
-       if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
-               STREAM_GET(&(api->rmac), s, sizeof(struct ethaddr));
 
        /* Prefix. */
        STREAM_GETC(s, api->prefix.family);
@@ -1212,6 +989,11 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
                                           api_nh->label_num
                                                   * sizeof(mpls_label_t));
                        }
+
+                       /* Router MAC for EVPN routes. */
+                       if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
+                               stream_get(&(api_nh->rmac), s,
+                                          sizeof(struct ethaddr));
                }
        }
 
@@ -1231,9 +1013,8 @@ stream_failure:
        return 0;
 }
 
-static void zapi_encode_prefix(struct stream *s,
-                             struct prefix *p,
-                             uint8_t family)
+static void zapi_encode_prefix(struct stream *s, struct prefix *p,
+                              uint8_t family)
 {
        struct prefix any;
 
@@ -1248,8 +1029,7 @@ static void zapi_encode_prefix(struct stream *s,
        stream_put(s, &p->u.prefix, prefix_blen(p));
 }
 
-int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
-                        struct pbr_rule *zrule)
+int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule)
 {
        stream_reset(s);
        zclient_create_header(s, cmd, zrule->vrf_id);
@@ -1265,11 +1045,11 @@ int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s,
 
        zapi_encode_prefix(s, &(zrule->filter.src_ip),
                           zrule->filter.src_ip.family);
-       stream_putw(s, zrule->filter.src_port);  /* src port */
+       stream_putw(s, zrule->filter.src_port); /* src port */
        zapi_encode_prefix(s, &(zrule->filter.dst_ip),
                           zrule->filter.src_ip.family);
-       stream_putw(s, zrule->filter.dst_port);  /* dst port */
-       stream_putw(s, zrule->filter.fwmark);    /* fwmark */
+       stream_putw(s, zrule->filter.dst_port); /* dst port */
+       stream_putw(s, zrule->filter.fwmark);   /* fwmark */
 
        stream_putl(s, zrule->action.table);
        stream_putl(s, zrule->ifindex);
@@ -1317,8 +1097,8 @@ bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
        STREAM_GETL(s, ifi);
 
        if (zclient_debug)
-               zlog_debug("%s: %u %u %u %u", __PRETTY_FUNCTION__,
-                          seq, prio, uni, ifi);
+               zlog_debug("%s: %u %u %u %u", __PRETTY_FUNCTION__, seq, prio,
+                          uni, ifi);
        *seqno = seq;
        *priority = prio;
        *unique = uni;
@@ -1330,9 +1110,8 @@ stream_failure:
        return false;
 }
 
-bool zapi_ipset_notify_decode(struct stream *s,
-                             uint32_t *unique,
-                            enum zapi_ipset_notify_owner *note)
+bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique,
+                             enum zapi_ipset_notify_owner *note)
 {
        uint32_t uni;
 
@@ -1350,10 +1129,9 @@ stream_failure:
        return false;
 }
 
-bool zapi_ipset_entry_notify_decode(struct stream *s,
-               uint32_t *unique,
-               char *ipset_name,
-               enum zapi_ipset_entry_notify_owner *note)
+bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
+                                   char *ipset_name,
+                                   enum zapi_ipset_entry_notify_owner *note)
 {
        uint32_t uni;
 
@@ -1361,8 +1139,27 @@ bool zapi_ipset_entry_notify_decode(struct stream *s,
 
        STREAM_GETL(s, uni);
 
-       STREAM_GET(ipset_name, s,
-                  ZEBRA_IPSET_NAME_SIZE);
+       STREAM_GET(ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
+
+       if (zclient_debug)
+               zlog_debug("%s: %u", __PRETTY_FUNCTION__, uni);
+       *unique = uni;
+
+       return true;
+
+stream_failure:
+       return false;
+}
+
+bool zapi_iptable_notify_decode(struct stream *s,
+               uint32_t *unique,
+               enum zapi_iptable_notify_owner *note)
+{
+       uint32_t uni;
+
+       STREAM_GET(note, s, sizeof(*note));
+
+       STREAM_GETL(s, uni);
 
        if (zclient_debug)
                zlog_debug("%s: %u", __PRETTY_FUNCTION__, uni);
@@ -1388,7 +1185,7 @@ struct nexthop *nexthop_from_zapi_nexthop(struct zapi_nexthop *znh)
         */
        if (znh->label_num) {
                nexthop_add_labels(n, ZEBRA_LSP_NONE, znh->label_num,
-                       znh->labels);
+                                  znh->labels);
        }
 
        return n;
@@ -1449,7 +1246,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
                if (nhr->nexthops[i].label_num)
                        STREAM_GET(&nhr->nexthops[i].labels[0], s,
                                   nhr->nexthops[i].label_num
-                                  * sizeof(mpls_label_t));
+                                          * sizeof(mpls_label_t));
        }
 
        return true;
@@ -1650,10 +1447,10 @@ static void link_params_set_value(struct stream *s, struct if_link_params *iflp)
                for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++)
                        iflp->unrsv_bw[i] = stream_getf(s);
                if (i < bwclassnum)
-                       zlog_err(
-                               "%s: received %d > %d (MAX_CLASS_TYPE) bw entries"
-                               " - outdated library?",
-                               __func__, bwclassnum, MAX_CLASS_TYPE);
+                       flog_err(LIB_ERR_ZAPI_MISSMATCH,
+                                 "%s: received %d > %d (MAX_CLASS_TYPE) bw entries"
+                                 " - outdated library?",
+                                 __func__, bwclassnum, MAX_CLASS_TYPE);
        }
        iflp->admin_grp = stream_getl(s);
        iflp->rmt_as = stream_getl(s);
@@ -1682,8 +1479,9 @@ struct interface *zebra_interface_link_params_read(struct stream *s)
        struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
 
        if (ifp == NULL) {
-               zlog_err("%s: unknown ifindex %u, shouldn't happen", __func__,
-                        ifindex);
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "%s: unknown ifindex %u, shouldn't happen", __func__,
+                         ifindex);
                return NULL;
        }
 
@@ -1872,8 +1670,9 @@ struct connected *zebra_interface_address_read(int type, struct stream *s,
                                zlog_warn(
                                        "warning: interface %s address %s "
                                        "with peer flag set, but no peer address!",
-                                       ifp->name, prefix2str(ifc->address, buf,
-                                                             sizeof buf));
+                                       ifp->name,
+                                       prefix2str(ifc->address, buf,
+                                                  sizeof buf));
                                UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
                        }
                }
@@ -2017,7 +1816,8 @@ static int zclient_read_sync_response(struct zclient *zclient,
                                   size);
        }
        if (ret != 0) {
-               zlog_err("%s: Invalid Sync Message Reply", __func__);
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                        "%s: Invalid Sync Message Reply", __func__);
                return -1;
        }
 
@@ -2039,7 +1839,7 @@ int lm_label_manager_connect(struct zclient *zclient)
        uint8_t result;
 
        if (zclient_debug)
-               zlog_debug("Connecting to Label Manager");
+               zlog_debug("Connecting to Label Manager (LM)");
 
        if (zclient->sock < 0)
                return -1;
@@ -2059,33 +1859,45 @@ int lm_label_manager_connect(struct zclient *zclient)
 
        ret = writen(zclient->sock, s->data, stream_get_endp(s));
        if (ret < 0) {
-               zlog_err("%s: can't write to zclient->sock", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET, "Can't write to zclient sock");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (ret == 0) {
-               zlog_err("%s: zclient->sock connection closed", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET, "Zclient sock closed");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (zclient_debug)
-               zlog_debug("%s: Label manager connect request (%d bytes) sent",
-                          __func__, ret);
+               zlog_debug("LM connect request sent (%d bytes)", ret);
 
        /* read response */
        if (zclient_read_sync_response(zclient, ZEBRA_LABEL_MANAGER_CONNECT)
            != 0)
                return -1;
 
-       /* result */
        s = zclient->ibuf;
+
+       /* read instance and proto */
+       uint8_t proto = stream_getc(s);
+       uint16_t instance = stream_getw(s);
+
+       /* sanity */
+       if (proto != zclient->redist_default)
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "Wrong proto (%u) in LM connect response. Should be %u",
+                         proto, zclient->redist_default);
+       if (instance != zclient->instance)
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "Wrong instId (%u) in LM connect response. Should be %u",
+                         instance, zclient->instance);
+
+       /* result code */
        result = stream_getc(s);
        if (zclient_debug)
-               zlog_debug(
-                       "%s: Label Manager connect response received, result %u",
-                       __func__, result);
+               zlog_debug("LM connect-response received, result %u", result);
 
        return (int)result;
 }
@@ -2098,10 +1910,8 @@ int lm_label_manager_connect(struct zclient *zclient)
  * @param chunk_size Amount of labels requested
  * @result 0 on success, -1 otherwise
  */
-int zclient_send_get_label_chunk(
-       struct zclient  *zclient,
-       uint8_t         keep,
-       uint32_t        chunk_size)
+int zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep,
+                                uint32_t chunk_size)
 {
        struct stream *s;
 
@@ -2115,6 +1925,10 @@ int zclient_send_get_label_chunk(
        stream_reset(s);
 
        zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
+       /* proto */
+       stream_putc(s, zclient->redist_default);
+       /* instance */
+       stream_putw(s, zclient->instance);
        stream_putc(s, keep);
        stream_putl(s, chunk_size);
 
@@ -2154,6 +1968,10 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
        s = zclient->obuf;
        stream_reset(s);
        zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
+       /* proto */
+       stream_putc(s, zclient->redist_default);
+       /* instance */
+       stream_putw(s, zclient->instance);
        /* keep */
        stream_putc(s, keep);
        /* chunk size */
@@ -2163,26 +1981,43 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
 
        ret = writen(zclient->sock, s->data, stream_get_endp(s));
        if (ret < 0) {
-               zlog_err("%s: can't write to zclient->sock", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET,
+                         "Can't write to zclient sock");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (ret == 0) {
-               zlog_err("%s: zclient->sock connection closed", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET,
+                         "Zclient sock closed");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (zclient_debug)
-               zlog_debug("%s: Label chunk request (%d bytes) sent", __func__,
-                          ret);
+               zlog_debug("Label chunk request (%d bytes) sent", ret);
 
        /* read response */
        if (zclient_read_sync_response(zclient, ZEBRA_GET_LABEL_CHUNK) != 0)
                return -1;
 
+       /* parse response */
        s = zclient->ibuf;
+
+       /* read proto and instance */
+       uint8_t proto = stream_getc(s);
+       uint16_t instance = stream_getw(s);
+
+       /* sanities */
+       if (proto != zclient->redist_default)
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "Wrong proto (%u) in get chunk response. Should be %u",
+                         proto, zclient->redist_default);
+       if (instance != zclient->instance)
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "Wrong instId (%u) in get chunk response Should be %u",
+                         instance, zclient->instance);
+
        /* keep */
        response_keep = stream_getc(s);
        /* start and end labels */
@@ -2191,20 +2026,20 @@ int lm_get_label_chunk(struct zclient *zclient, uint8_t keep,
 
        /* not owning this response */
        if (keep != response_keep) {
-               zlog_err(
-                       "%s: Invalid Label chunk: %u - %u, keeps mismatch %u != %u",
-                       __func__, *start, *end, keep, response_keep);
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "Invalid Label chunk: %u - %u, keeps mismatch %u != %u",
+                         *start, *end, keep, response_keep);
        }
        /* sanity */
        if (*start > *end || *start < MPLS_LABEL_UNRESERVED_MIN
            || *end > MPLS_LABEL_UNRESERVED_MAX) {
-               zlog_err("%s: Invalid Label chunk: %u - %u", __func__, *start,
-                        *end);
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "Invalid Label chunk: %u - %u", *start, *end);
                return -1;
        }
 
        if (zclient_debug)
-               zlog_debug("Label Chunk assign: %u - %u (%u) ", *start, *end,
+               zlog_debug("Label Chunk assign: %u - %u (%u)", *start, *end,
                           response_keep);
 
        return 0;
@@ -2225,7 +2060,7 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
        struct stream *s;
 
        if (zclient_debug)
-               zlog_debug("Releasing Label Chunk");
+               zlog_debug("Releasing Label Chunk %u - %u", start, end);
 
        if (zclient->sock < 0)
                return -1;
@@ -2235,6 +2070,10 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
        stream_reset(s);
        zclient_create_header(s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT);
 
+       /* proto */
+       stream_putc(s, zclient->redist_default);
+       /* instance */
+       stream_putw(s, zclient->instance);
        /* start */
        stream_putl(s, start);
        /* end */
@@ -2245,13 +2084,14 @@ int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
 
        ret = writen(zclient->sock, s->data, stream_get_endp(s));
        if (ret < 0) {
-               zlog_err("%s: can't write to zclient->sock", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET, "Can't write to zclient sock");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (ret == 0) {
-               zlog_err("%s: zclient->sock connection closed", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET,
+                         "Zclient sock connection closed");
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
@@ -2299,8 +2139,7 @@ int tm_table_manager_connect(struct zclient *zclient)
                return -1;
 
        if (zclient_debug)
-               zlog_debug("%s: Table manager connect request sent",
-                          __func__);
+               zlog_debug("%s: Table manager connect request sent", __func__);
 
        /* read response */
        if (zclient_read_sync_response(zclient, ZEBRA_TABLE_MANAGER_CONNECT)
@@ -2355,13 +2194,15 @@ int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
 
        ret = writen(zclient->sock, s->data, stream_get_endp(s));
        if (ret < 0) {
-               zlog_err("%s: can't write to zclient->sock", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET,
+                         "%s: can't write to zclient->sock", __func__);
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
        }
        if (ret == 0) {
-               zlog_err("%s: zclient->sock connection closed", __func__);
+               flog_err(LIB_ERR_ZAPI_SOCKET,
+                         "%s: zclient->sock connection closed", __func__);
                close(zclient->sock);
                zclient->sock = -1;
                return -1;
@@ -2447,7 +2288,8 @@ int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw)
                stream_write(s, (uint8_t *)&pw->nexthop.ipv6, 16);
                break;
        default:
-               zlog_err("%s: unknown af", __func__);
+               flog_err(LIB_ERR_ZAPI_ENCODE,
+                         "%s: unknown af", __func__);
                return -1;
        }
 
@@ -2485,6 +2327,25 @@ void zebra_read_pw_status_update(int command, struct zclient *zclient,
        pw->status = stream_getl(s);
 }
 
+static void zclient_capability_decode(int command, struct zclient *zclient,
+                                     zebra_size_t length, vrf_id_t vrf_id)
+{
+       struct zclient_capabilities cap;
+       struct stream *s = zclient->ibuf;
+       uint8_t mpls_enabled;
+
+       memset(&cap, 0, sizeof(cap));
+       STREAM_GETC(s, mpls_enabled);
+       cap.mpls_enabled = !!mpls_enabled;
+       STREAM_GETL(s, cap.ecmp);
+
+       if (zclient->zebra_capabilities)
+               (*zclient->zebra_capabilities)(&cap);
+
+stream_failure:
+       return;
+}
+
 /* Zebra client message read function. */
 static int zclient_read(struct thread *thread)
 {
@@ -2530,15 +2391,16 @@ static int zclient_read(struct thread *thread)
        command = stream_getw(zclient->ibuf);
 
        if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
-               zlog_err(
-                       "%s: socket %d version mismatch, marker %d, version %d",
-                       __func__, zclient->sock, marker, version);
+               flog_err(LIB_ERR_ZAPI_MISSMATCH,
+                         "%s: socket %d version mismatch, marker %d, version %d",
+                         __func__, zclient->sock, marker, version);
                return zclient_failed(zclient);
        }
 
        if (length < ZEBRA_HEADER_SIZE) {
-               zlog_err("%s: socket %d message length %u is less than %d ",
-                        __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
+               flog_err(LIB_ERR_ZAPI_MISSMATCH,
+                         "%s: socket %d message length %u is less than %d ",
+                         __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
                return zclient_failed(zclient);
        }
 
@@ -2582,6 +2444,9 @@ static int zclient_read(struct thread *thread)
                           (void *)zclient, command, vrf_id);
 
        switch (command) {
+       case ZEBRA_CAPABILITIES:
+               zclient_capability_decode(command, zclient, length, vrf_id);
+               break;
        case ZEBRA_ROUTER_ID_UPDATE:
                if (zclient->router_id_update)
                        (*zclient->router_id_update)(command, zclient, length,
@@ -2683,6 +2548,16 @@ static int zclient_read(struct thread *thread)
                if (zclient->fec_update)
                        (*zclient->fec_update)(command, zclient, length);
                break;
+       case ZEBRA_LOCAL_ES_ADD:
+               if (zclient->local_es_add)
+                       (*zclient->local_es_add)(command, zclient, length,
+                                                vrf_id);
+               break;
+       case ZEBRA_LOCAL_ES_DEL:
+               if (zclient->local_es_del)
+                       (*zclient->local_es_del)(command, zclient, length,
+                                                vrf_id);
+               break;
        case ZEBRA_VNI_ADD:
                if (zclient->local_vni_add)
                        (*zclient->local_vni_add)(command, zclient, length,
@@ -2741,8 +2616,24 @@ static int zclient_read(struct thread *thread)
        case ZEBRA_GET_LABEL_CHUNK:
                if (zclient->label_chunk)
                        (*zclient->label_chunk)(command, zclient, length,
+                                               vrf_id);
+               break;
+       case ZEBRA_IPSET_NOTIFY_OWNER:
+               if (zclient->ipset_notify_owner)
+                       (*zclient->ipset_notify_owner)(command, zclient, length,
                                                      vrf_id);
                break;
+       case ZEBRA_IPSET_ENTRY_NOTIFY_OWNER:
+               if (zclient->ipset_entry_notify_owner)
+                       (*zclient->ipset_entry_notify_owner)(command,
+                                                    zclient, length,
+                                                    vrf_id);
+               break;
+       case ZEBRA_IPTABLE_NOTIFY_OWNER:
+               if (zclient->iptable_notify_owner)
+                       (*zclient->iptable_notify_owner)(command,
+                                                zclient, length,
+                                                vrf_id);
        default:
                break;
        }