SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
api.mtu = re->mtu;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
/* Encode route and send. */
- if (zapi_route_encode(cmd, client->obuf, &api) < 0)
+ if (zapi_route_encode(cmd, s, &api) < 0)
return -1;
- return zebra_server_send_message(client, s);
+
+ if (IS_ZEBRA_DEBUG_SEND) {
+ char buf_prefix[PREFIX_STRLEN];
+ prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix));
+
+ zlog_debug("%s: %s to client %s: type %s, vrf_id %d, p %s",
+ __func__, zserv_command_string(cmd),
+ zebra_route_string(client->proto),
+ zebra_route_string(api.type), api.vrf_id,
+ buf_prefix);
+ }
+ return zebra_server_send_message(client);
+}
+
+static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop)
+{
+ stream_putc(s, nexthop->type);
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ stream_put_in_addr(s, &nexthop->gate.ipv4);
+ stream_putl(s, nexthop->ifindex);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ stream_put(s, &nexthop->gate.ipv6, 16);
+ break;
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ stream_put(s, &nexthop->gate.ipv6, 16);
+ stream_putl(s, nexthop->ifindex);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ stream_putl(s, nexthop->ifindex);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ return 1;
}
- /* Nexthop register */
- static int zserv_rnh_register(struct zserv *client, u_short length,
- rnh_type_t type, struct zebra_vrf *zvrf)
+ /*
+ * Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if
+ * nexthop is not found on mrib. Returns both route metric and protocol
+ * distance.
+ */
+ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
+ struct in_addr addr,
+ struct route_entry *re,
+ struct zebra_vrf *zvrf)
{
- struct rnh *rnh;
struct stream *s;
- struct prefix p;
- u_short l = 0;
- u_char flags = 0;
-
- if (IS_ZEBRA_DEBUG_NHT)
- zlog_debug(
- "rnh_register msg from client %s: length=%d, type=%s\n",
- zebra_route_string(client->proto), length,
- (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route");
+ unsigned long nump;
+ u_char num;
+ struct nexthop *nexthop;
- s = client->ibuf;
+ /* Get output stream. */
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ stream_reset(s);
- client->nh_reg_time = monotime(NULL);
+ /* Fill in result. */
+ zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
+ stream_put_in_addr(s, &addr);
- while (l < length) {
- STREAM_GETC(s, flags);
- STREAM_GETW(s, p.family);
- STREAM_GETC(s, p.prefixlen);
- l += 4;
- if (p.family == AF_INET) {
- if (p.prefixlen > IPV4_MAX_BITLEN) {
- zlog_warn(
- "%s: Specified prefix length %d is too large for a v4 address",
- __PRETTY_FUNCTION__, p.prefixlen);
- return -1;
- }
- STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
- l += IPV4_MAX_BYTELEN;
- } else if (p.family == AF_INET6) {
- if (p.prefixlen > IPV6_MAX_BITLEN) {
- zlog_warn(
- "%s: Specified prefix length %d is to large for a v6 address",
- __PRETTY_FUNCTION__, p.prefixlen);
- return -1;
- }
- STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
- l += IPV6_MAX_BYTELEN;
- } else {
- zlog_err(
- "rnh_register: Received unknown family type %d\n",
- p.family);
- return -1;
- }
- rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type);
- if (type == RNH_NEXTHOP_TYPE) {
- if (flags
- && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
- SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
- else if (!flags
- && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
- UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
- } else if (type == RNH_IMPORT_CHECK_TYPE) {
- if (flags
- && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
- SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
- else if (!flags && CHECK_FLAG(rnh->flags,
- ZEBRA_NHT_EXACT_MATCH))
- UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
- }
+ if (re) {
+ stream_putc(s, re->distance);
+ stream_putl(s, re->metric);
+ num = 0;
+ nump = stream_get_endp(
+ s); /* remember position for nexthop_num */
+ stream_putc(s, 0); /* reserve room for nexthop_num */
+ /* Only non-recursive routes are elegible to resolve the nexthop
+ * we
+ * are looking up. Therefore, we will just iterate over the top
+ * chain of nexthops. */
+ for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ num += zserv_encode_nexthop(s, nexthop);
- zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
- /* Anything not AF_INET/INET6 has been filtered out above */
- zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p);
+ stream_putc_at(s, nump, num); /* store nexthop_num */
+ } else {
+ stream_putc(s, 0); /* distance */
+ stream_putl(s, 0); /* metric */
+ stream_putc(s, 0); /* nexthop_num */
}
- stream_failure:
- return 0;
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client, s);
}
- /* Nexthop register */
- static int zserv_rnh_unregister(struct zserv *client, u_short length,
- rnh_type_t type, struct zebra_vrf *zvrf)
+ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
+ enum zapi_route_notify_owner note)
{
- struct rnh *rnh;
+ struct zserv *client;
struct stream *s;
- struct prefix p;
- u_short l = 0;
+ uint8_t blen;
- if (IS_ZEBRA_DEBUG_NHT)
- zlog_debug("rnh_unregister msg from client %s: length=%d\n",
- zebra_route_string(client->proto), length);
+ client = zebra_find_client(re->type, re->instance);
+ if (!client || !client->notify_owner) {
+ if (IS_ZEBRA_DEBUG_PACKET) {
+ char buff[PREFIX_STRLEN];
- s = client->ibuf;
+ zlog_debug(
+ "Not Notifying Owner: %u about prefix %s(%u) %d",
+ re->type, prefix2str(p, buff, sizeof(buff)),
+ re->table, note);
+ }
+ return 0;
+ }
- while (l < length) {
- uint8_t flags;
+ if (IS_ZEBRA_DEBUG_PACKET) {
+ char buff[PREFIX_STRLEN];
- STREAM_GETC(s, flags);
- if (flags != 0)
- goto stream_failure;
+ zlog_debug("Notifying Owner: %u about prefix %s(%u) %d",
+ re->type, prefix2str(p, buff, sizeof(buff)),
+ re->table, note);
+ }
- STREAM_GETW(s, p.family);
- STREAM_GETC(s, p.prefixlen);
- l += 4;
- if (p.family == AF_INET) {
- if (p.prefixlen > IPV4_MAX_BITLEN) {
- zlog_warn(
- "%s: Specified prefix length %d is to large for a v4 address",
- __PRETTY_FUNCTION__, p.prefixlen);
- return -1;
- }
- STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
- l += IPV4_MAX_BYTELEN;
- } else if (p.family == AF_INET6) {
- if (p.prefixlen > IPV6_MAX_BITLEN) {
- zlog_warn(
- "%s: Specified prefix length %d is to large for a v6 address",
- __PRETTY_FUNCTION__, p.prefixlen);
- return -1;
- }
- STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
- l += IPV6_MAX_BYTELEN;
- } else {
- zlog_err(
- "rnh_register: Received unknown family type %d\n",
- p.family);
- return -1;
- }
- rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type);
- if (rnh) {
- client->nh_dereg_time = monotime(NULL);
- zebra_remove_rnh_client(rnh, client, type);
- }
- }
- stream_failure:
- return 0;
- }
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ stream_reset(s);
- #define ZEBRA_MIN_FEC_LENGTH 5
+ zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id);
- /* FEC register */
- static int zserv_fec_register(struct zserv *client, u_short length)
- {
- struct stream *s;
- struct zebra_vrf *zvrf;
- u_short l = 0;
- struct prefix p;
- u_int16_t flags;
- u_int32_t label_index = MPLS_INVALID_LABEL_INDEX;
+ stream_put(s, ¬e, sizeof(note));
- s = client->ibuf;
- zvrf = vrf_info_lookup(VRF_DEFAULT);
- if (!zvrf)
- return 0; // unexpected
+ stream_putc(s, p->family);
- /*
- * The minimum amount of data that can be sent for one fec
- * registration
- */
- if (length < ZEBRA_MIN_FEC_LENGTH) {
- zlog_err(
- "fec_register: Received a fec register of length %d, it is of insufficient size to properly decode",
- length);
- return -1;
- }
+ blen = prefix_blen(p);
+ stream_putc(s, p->prefixlen);
+ stream_put(s, &p->u.prefix, blen);
- while (l < length) {
- STREAM_GETW(s, flags);
- memset(&p, 0, sizeof(p));
- STREAM_GETW(s, p.family);
- if (p.family != AF_INET && p.family != AF_INET6) {
- zlog_err(
- "fec_register: Received unknown family type %d\n",
- p.family);
- return -1;
- }
- STREAM_GETC(s, p.prefixlen);
- if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
- || (p.family == AF_INET6
- && p.prefixlen > IPV6_MAX_BITLEN)) {
- zlog_warn(
- "%s: Specified prefix length: %d is to long for %d",
- __PRETTY_FUNCTION__, p.prefixlen, p.family);
- return -1;
- }
- l += 5;
- STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
- l += PSIZE(p.prefixlen);
- if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) {
- STREAM_GETL(s, label_index);
- l += 4;
- } else
- label_index = MPLS_INVALID_LABEL_INDEX;
- zebra_mpls_fec_register(zvrf, &p, label_index, client);
- }
+ stream_putl(s, re->table);
- stream_failure:
- return 0;
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client, s);
}
- /* FEC unregister */
- static int zserv_fec_unregister(struct zserv *client, u_short length)
+ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
+ enum zapi_rule_notify_owner note)
{
+ struct listnode *node;
+ struct zserv *client;
struct stream *s;
- struct zebra_vrf *zvrf;
- u_short l = 0;
- struct prefix p;
- uint16_t flags;
- s = client->ibuf;
- zvrf = vrf_info_lookup(VRF_DEFAULT);
- if (!zvrf)
- return 0; // unexpected
+ if (IS_ZEBRA_DEBUG_PACKET) {
+ zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
+ rule->unique);
+ }
- /*
- * The minimum amount of data that can be sent for one
- * fec unregistration
- */
- if (length < ZEBRA_MIN_FEC_LENGTH) {
- zlog_err(
- "fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode",
- length);
- return -1;
+ for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+ if (rule->sock == client->sock)
+ break;
}
- while (l < length) {
- STREAM_GETW(s, flags);
- if (flags != 0)
- goto stream_failure;
+ if (!client)
+ return;
- memset(&p, 0, sizeof(p));
- STREAM_GETW(s, p.family);
- if (p.family != AF_INET && p.family != AF_INET6) {
- zlog_err(
- "fec_unregister: Received unknown family type %d\n",
- p.family);
- return -1;
- }
- STREAM_GETC(s, p.prefixlen);
- if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
- || (p.family == AF_INET6
- && p.prefixlen > IPV6_MAX_BITLEN)) {
- zlog_warn(
- "%s: Received prefix length %d which is greater than %d can support",
- __PRETTY_FUNCTION__, p.prefixlen, p.family);
- return -1;
- }
- l += 5;
- STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
- l += PSIZE(p.prefixlen);
- zebra_mpls_fec_unregister(zvrf, &p, client);
- }
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ stream_reset(s);
- stream_failure:
- return 0;
+ zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
+ stream_put(s, ¬e, sizeof(note));
+ stream_putl(s, rule->seq);
+ stream_putl(s, rule->priority);
+ stream_putl(s, rule->unique);
+ if (rule->ifp)
+ stream_putl(s, rule->ifp->ifindex);
+ else
+ stream_putl(s, 0);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ zebra_server_send_message(client, s);
}
- /*
- Modified version of zsend_ipv4_nexthop_lookup():
- Query unicast rib if nexthop is not found on mrib.
- Returns both route metric and protocol distance.
- */
- static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
- struct in_addr addr,
- struct route_entry *re,
- struct zebra_vrf *zvrf)
+ /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
+ int zsend_router_id_update(struct zserv *client, struct prefix *p,
+ vrf_id_t vrf_id)
{
- struct stream *s;
- unsigned long nump;
- u_char num;
- struct nexthop *nexthop;
+ int blen;
- /* Get output stream. */
- s = client->obuf;
- stream_reset(s);
+ /* Check this client need interface information. */
+ if (!vrf_bitmap_check(client->ridinfo, vrf_id))
+ return 0;
- /* Fill in result. */
- zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
- stream_put_in_addr(s, &addr);
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- if (re) {
- stream_putc(s, re->distance);
- stream_putl(s, re->metric);
- num = 0;
- nump = stream_get_endp(
- s); /* remember position for nexthop_num */
- stream_putc(s, 0); /* reserve room for nexthop_num */
- /* Only non-recursive routes are elegible to resolve the nexthop
- * we
- * are looking up. Therefore, we will just iterate over the top
- * chain of nexthops. */
- for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- num += zsend_write_nexthop(s, nexthop);
+ /* Message type. */
+ zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
- stream_putc_at(s, nump, num); /* store nexthop_num */
- } else {
- stream_putc(s, 0); /* distance */
- stream_putl(s, 0); /* metric */
- stream_putc(s, 0); /* nexthop_num */
- }
+ /* Prefix information. */
+ stream_putc(s, p->family);
+ blen = prefix_blen(p);
+ stream_put(s, &p->u.prefix, blen);
+ stream_putc(s, p->prefixlen);
+ /* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
- return zebra_server_send_message(client);
+ return zebra_server_send_message(client, s);
}
- int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
- enum zapi_route_notify_owner note)
+ /*
+ * Function used by Zebra to send a PW status update to LDP daemon
+ */
+ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
{
- struct zserv *client;
- struct stream *s;
- uint8_t blen;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- client = zebra_find_client(re->type, re->instance);
- if (!client || !client->notify_owner) {
- if (IS_ZEBRA_DEBUG_PACKET) {
- char buff[PREFIX_STRLEN];
+ zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
+ stream_write(s, pw->ifname, IF_NAMESIZE);
+ stream_putl(s, pw->ifindex);
+ stream_putl(s, pw->status);
- zlog_debug(
- "Not Notifying Owner: %u about prefix %s(%u) %d",
- re->type, prefix2str(p, buff, sizeof(buff)),
- re->table, note);
- }
- return 0;
- }
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
- if (IS_ZEBRA_DEBUG_PACKET) {
- char buff[PREFIX_STRLEN];
+ return zebra_server_send_message(client, s);
+ }
- zlog_debug("Notifying Owner: %u about prefix %s(%u) %d",
- re->type, prefix2str(p, buff, sizeof(buff)),
- re->table, note);
- }
+ /* Send response to a get label chunk request to client */
+ static int zsend_assign_label_chunk_response(struct zserv *client,
+ vrf_id_t vrf_id,
+ struct label_manager_chunk *lmc)
+ {
+ int ret;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- s = client->obuf;
- stream_reset(s);
+ zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
- zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id);
+ if (lmc) {
+ /* keep */
+ stream_putc(s, lmc->keep);
+ /* start and end labels */
+ stream_putl(s, lmc->start);
+ stream_putl(s, lmc->end);
+ }
- stream_put(s, ¬e, sizeof(note));
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
- stream_putc(s, p->family);
+ ret = writen(client->sock, s->data, stream_get_endp(s));
+ stream_free(s);
+ return ret;
+ }
- blen = prefix_blen(p);
- stream_putc(s, p->prefixlen);
- stream_put(s, &p->u.prefix, blen);
+ /* Send response to a label manager connect request to client */
+ static int zsend_label_manager_connect_response(struct zserv *client,
+ vrf_id_t vrf_id, u_short result)
+ {
+ int ret;
+ struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- stream_putl(s, re->table);
+ zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
+ /* result */
+ stream_putc(s, result);
+
+ /* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
- return zebra_server_send_message(client);
+ ret = writen(client->sock, s->data, stream_get_endp(s));
+ stream_free(s);
+
+ return ret;
}
- void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
- enum zapi_rule_notify_owner note)
+ /* Inbound message handling ------------------------------------------------ */
+
+ int cmd2type[] = {
+ [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE,
+ [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE,
+ [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE,
+ [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE,
+ };
+
+ /* Nexthop register */
+ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
{
- struct listnode *node;
- struct zserv *client;
+ struct rnh *rnh;
struct stream *s;
+ struct prefix p;
+ u_short l = 0;
+ u_char flags = 0;
+ uint16_t type = cmd2type[hdr->command];
- if (IS_ZEBRA_DEBUG_PACKET) {
- zlog_debug("%s: Notifying %u",
- __PRETTY_FUNCTION__, rule->unique);
- }
+ if (IS_ZEBRA_DEBUG_NHT)
+ zlog_debug(
+ "rnh_register msg from client %s: hdr->length=%d, type=%s\n",
+ zebra_route_string(client->proto), hdr->length,
+ (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route");
- for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
- if (rule->sock == client->sock)
- break;
+ s = msg;
+
+ client->nh_reg_time = monotime(NULL);
+
+ while (l < hdr->length) {
+ STREAM_GETC(s, flags);
+ STREAM_GETW(s, p.family);
+ STREAM_GETC(s, p.prefixlen);
+ l += 4;
+ if (p.family == AF_INET) {
+ if (p.prefixlen > IPV4_MAX_BITLEN) {
+ zlog_warn(
+ "%s: Specified prefix hdr->length %d is too large for a v4 address",
+ __PRETTY_FUNCTION__, p.prefixlen);
+ return;
+ }
+ STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
+ l += IPV4_MAX_BYTELEN;
+ } else if (p.family == AF_INET6) {
+ if (p.prefixlen > IPV6_MAX_BITLEN) {
+ zlog_warn(
+ "%s: Specified prefix hdr->length %d is to large for a v6 address",
+ __PRETTY_FUNCTION__, p.prefixlen);
+ return;
+ }
+ STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
+ l += IPV6_MAX_BYTELEN;
+ } else {
+ zlog_err(
+ "rnh_register: Received unknown family type %d\n",
+ p.family);
+ return;
+ }
+ rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type);
+ if (type == RNH_NEXTHOP_TYPE) {
+ if (flags
+ && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
+ SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
+ else if (!flags
+ && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
+ UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
+ } else if (type == RNH_IMPORT_CHECK_TYPE) {
+ if (flags
+ && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
+ SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
+ else if (!flags
+ && CHECK_FLAG(rnh->flags,
+ ZEBRA_NHT_EXACT_MATCH))
+ UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
+ }
+
+ zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
+ /* Anything not AF_INET/INET6 has been filtered out above */
+ zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p);
}
- if (!client)
- return;
+ stream_failure:
+ return;
+ }
- s = client->obuf;
- stream_reset(s);
+ /* Nexthop register */
+ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
+ {
+ struct rnh *rnh;
+ struct stream *s;
+ struct prefix p;
+ u_short l = 0;
+ uint16_t type = cmd2type[hdr->command];
- zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
- stream_put(s, ¬e, sizeof(note));
- stream_putl(s, rule->seq);
- stream_putl(s, rule->priority);
- stream_putl(s, rule->unique);
- if (rule->ifp)
- stream_putl(s, rule->ifp->ifindex);
- else
- stream_putl(s, 0);
+ if (IS_ZEBRA_DEBUG_NHT)
+ zlog_debug(
+ "rnh_unregister msg from client %s: hdr->length=%d\n",
+ zebra_route_string(client->proto), hdr->length);
- stream_putw_at(s, 0, stream_get_endp(s));
+ s = msg;
+
+ while (l < hdr->length) {
+ uint8_t flags;
+
+ STREAM_GETC(s, flags);
+ if (flags != 0)
+ goto stream_failure;
- zebra_server_send_message(client);
+ STREAM_GETW(s, p.family);
+ STREAM_GETC(s, p.prefixlen);
+ l += 4;
+ if (p.family == AF_INET) {
+ if (p.prefixlen > IPV4_MAX_BITLEN) {
+ zlog_warn(
+ "%s: Specified prefix hdr->length %d is to large for a v4 address",
+ __PRETTY_FUNCTION__, p.prefixlen);
+ return;
+ }
+ STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
+ l += IPV4_MAX_BYTELEN;
+ } else if (p.family == AF_INET6) {
+ if (p.prefixlen > IPV6_MAX_BITLEN) {
+ zlog_warn(
+ "%s: Specified prefix hdr->length %d is to large for a v6 address",
+ __PRETTY_FUNCTION__, p.prefixlen);
+ return;
+ }
+ STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
+ l += IPV6_MAX_BYTELEN;
+ } else {
+ zlog_err(
+ "rnh_register: Received unknown family type %d\n",
+ p.family);
+ return;
+ }
+ rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type);
+ if (rnh) {
+ client->nh_dereg_time = monotime(NULL);
+ zebra_remove_rnh_client(rnh, client, type);
+ }
+ }
+ stream_failure:
+ return;
}
- /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
- int zsend_router_id_update(struct zserv *client, struct prefix *p,
- vrf_id_t vrf_id)
+ #define ZEBRA_MIN_FEC_LENGTH 5
+
+ /* FEC register */
+ static void zread_fec_register(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- int blen;
-
- /* Check this client need interface information. */
- if (!vrf_bitmap_check(client->ridinfo, vrf_id))
- return 0;
-
- s = client->obuf;
- stream_reset(s);
+ u_short l = 0;
+ struct prefix p;
+ uint16_t flags;
+ uint32_t label_index = MPLS_INVALID_LABEL_INDEX;
- /* Message type. */
- zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
+ s = msg;
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return; // unexpected
- /* Prefix information. */
- stream_putc(s, p->family);
- blen = prefix_blen(p);
- stream_put(s, &p->u.prefix, blen);
- stream_putc(s, p->prefixlen);
+ /*
+ * The minimum amount of data that can be sent for one fec
+ * registration
+ */
+ if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
+ zlog_err(
+ "fec_register: Received a fec register of hdr->length %d, it is of insufficient size to properly decode",
+ hdr->length);
+ return;
+ }
- /* Write packet size. */
- stream_putw_at(s, 0, stream_get_endp(s));
+ while (l < hdr->length) {
+ STREAM_GETW(s, flags);
+ memset(&p, 0, sizeof(p));
+ STREAM_GETW(s, p.family);
+ if (p.family != AF_INET && p.family != AF_INET6) {
+ zlog_err(
+ "fec_register: Received unknown family type %d\n",
+ p.family);
+ return;
+ }
+ STREAM_GETC(s, p.prefixlen);
+ if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
+ || (p.family == AF_INET6
+ && p.prefixlen > IPV6_MAX_BITLEN)) {
+ zlog_warn(
+ "%s: Specified prefix hdr->length: %d is to long for %d",
+ __PRETTY_FUNCTION__, p.prefixlen, p.family);
+ return;
+ }
+ l += 5;
+ STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
+ l += PSIZE(p.prefixlen);
+ if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) {
+ STREAM_GETL(s, label_index);
+ l += 4;
+ } else
+ label_index = MPLS_INVALID_LABEL_INDEX;
+ zebra_mpls_fec_register(zvrf, &p, label_index, client);
+ }
- return zebra_server_send_message(client);
+ stream_failure:
+ return;
}
- /*
- * Function used by Zebra to send a PW status update to LDP daemon
- */
- int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
+ /* FEC unregister */
+ static void zread_fec_unregister(ZAPI_HANDLER_ARGS)
{
struct stream *s;
+ u_short l = 0;
+ struct prefix p;
+ uint16_t flags;
- s = client->obuf;
- stream_reset(s);
+ s = msg;
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return; // unexpected
- zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
- stream_write(s, pw->ifname, IF_NAMESIZE);
- stream_putl(s, pw->ifindex);
- stream_putl(s, pw->status);
+ /*
+ * The minimum amount of data that can be sent for one
+ * fec unregistration
+ */
+ if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
+ zlog_err(
+ "fec_unregister: Received a fec unregister of hdr->length %d, it is of insufficient size to properly decode",
+ hdr->length);
+ return;
+ }
- /* Put length at the first point of the stream. */
- stream_putw_at(s, 0, stream_get_endp(s));
+ while (l < hdr->length) {
+ STREAM_GETW(s, flags);
+ if (flags != 0)
+ goto stream_failure;
- return zebra_server_send_message(client);
+ memset(&p, 0, sizeof(p));
+ STREAM_GETW(s, p.family);
+ if (p.family != AF_INET && p.family != AF_INET6) {
+ zlog_err(
+ "fec_unregister: Received unknown family type %d\n",
+ p.family);
+ return;
+ }
+ STREAM_GETC(s, p.prefixlen);
+ if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
+ || (p.family == AF_INET6
+ && p.prefixlen > IPV6_MAX_BITLEN)) {
+ zlog_warn(
+ "%s: Received prefix hdr->length %d which is greater than %d can support",
+ __PRETTY_FUNCTION__, p.prefixlen, p.family);
+ return;
+ }
+ l += 5;
+ STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
+ l += PSIZE(p.prefixlen);
+ zebra_mpls_fec_unregister(zvrf, &p, client);
+ }
+
+ stream_failure:
+ return;
}
- /* Register zebra server interface information. Send current all
- interface and address information. */
- static int zread_interface_add(struct zserv *client, u_short length,
- struct zebra_vrf *zvrf)
+
+ /*
+ * Register zebra server interface information.
+ * Send current all interface and address information.
+ */
+ static void zread_interface_add(ZAPI_HANDLER_ARGS)
{
struct vrf *vrf;
struct interface *ifp;
struct nexthop *nexthop = NULL;
int i, ret;
vrf_id_t vrf_id = 0;
+ struct ipaddr vtep_ip;
- s = client->ibuf;
- if (zapi_route_decode(s, &api) < 0)
- return -1;
+ s = msg;
+ zapi_route_decode(s, &api);
+ if (IS_ZEBRA_DEBUG_RECV) {
+ char buf_prefix[PREFIX_STRLEN];
+ prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix));
+ zlog_debug("%s: p=%s, ZAPI_MESSAGE_LABEL: %sset, flags=0x%x",
+ __func__, buf_prefix,
+ (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) ? ""
+ : "un"),
+ api.flags);
+ }
+
/* Allocate new route. */
vrf_id = zvrf_id(zvrf);
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));