]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zapi_msg.c
staticd: kill static_memory.h, use MTYPE_STATIC
[mirror_frr.git] / zebra / zapi_msg.c
CommitLineData
bf094f69 1/*
d8647095 2 * Zebra API message creation & consumption.
bf094f69
QY
3 * Portions:
4 * Copyright (C) 1997-1999 Kunihiro Ishiguro
5 * Copyright (C) 2015-2018 Cumulus Networks, Inc.
6 * et al.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <zebra.h>
24#include <libgen.h>
25
26#include "lib/prefix.h"
bf094f69
QY
27#include "lib/stream.h"
28#include "lib/memory.h"
29#include "lib/table.h"
30#include "lib/network.h"
bf094f69
QY
31#include "lib/log.h"
32#include "lib/zclient.h"
33#include "lib/privs.h"
bf094f69
QY
34#include "lib/nexthop.h"
35#include "lib/vrf.h"
36#include "lib/libfrr.h"
5e7939a5 37#include "lib/lib_errors.h"
bf094f69 38
161e9ab7 39#include "zebra/zebra_router.h"
bf094f69
QY
40#include "zebra/rib.h"
41#include "zebra/zebra_memory.h"
42#include "zebra/zebra_ns.h"
43#include "zebra/zebra_vrf.h"
44#include "zebra/router-id.h"
45#include "zebra/redistribute.h"
46#include "zebra/debug.h"
47#include "zebra/zebra_rnh.h"
bf094f69
QY
48#include "zebra/interface.h"
49#include "zebra/zebra_ptm.h"
50#include "zebra/rtadv.h"
51#include "zebra/zebra_mpls.h"
52#include "zebra/zebra_mroute.h"
bf094f69 53#include "zebra/zebra_vxlan.h"
ce5160c0 54#include "zebra/zebra_evpn_mh.h"
bf094f69
QY
55#include "zebra/rt.h"
56#include "zebra/zebra_pbr.h"
57#include "zebra/table_manager.h"
58#include "zebra/zapi_msg.h"
364fed6b 59#include "zebra/zebra_errors.h"
02c0866d 60#include "zebra/zebra_mlag.h"
54bea4e5 61#include "zebra/connected.h"
79b3664a 62#include "zebra/zebra_opaque.h"
31f937fb 63#include "zebra/zebra_srte.h"
bf094f69 64
5898ce6f
MS
65static int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg);
66
bf094f69
QY
67/* Encoding helpers -------------------------------------------------------- */
68
69static void zserv_encode_interface(struct stream *s, struct interface *ifp)
70{
71 /* Interface information. */
53e60e5c 72 struct zebra_if *zif = ifp->info;
19c38250 73
bf094f69
QY
74 stream_put(s, ifp->name, INTERFACE_NAMSIZ);
75 stream_putl(s, ifp->ifindex);
76 stream_putc(s, ifp->status);
77 stream_putq(s, ifp->flags);
78 stream_putc(s, ifp->ptm_enable);
79 stream_putc(s, ifp->ptm_status);
80 stream_putl(s, ifp->metric);
81 stream_putl(s, ifp->speed);
82 stream_putl(s, ifp->mtu);
83 stream_putl(s, ifp->mtu6);
84 stream_putl(s, ifp->bandwidth);
53e60e5c 85 stream_putl(s, zif->link_ifindex);
bf094f69
QY
86 stream_putl(s, ifp->ll_type);
87 stream_putl(s, ifp->hw_addr_len);
88 if (ifp->hw_addr_len)
89 stream_put(s, ifp->hw_addr, ifp->hw_addr_len);
90
91 /* Then, Traffic Engineering parameters if any */
92 if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) {
93 stream_putc(s, 1);
94 zebra_interface_link_params_write(s, ifp);
95 } else
96 stream_putc(s, 0);
97
98 /* Write packet size. */
99 stream_putw_at(s, 0, stream_get_endp(s));
100}
101
102static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf)
103{
104 struct vrf_data data;
105 const char *netns_name = zvrf_ns_name(zvrf);
106
a013777a 107 memset(&data, 0, sizeof(data));
bf094f69
QY
108 data.l.table_id = zvrf->table_id;
109
110 if (netns_name)
111 strlcpy(data.l.netns_name, basename((char *)netns_name),
112 NS_NAMSIZ);
113 else
114 memset(data.l.netns_name, 0, NS_NAMSIZ);
115 /* Pass the tableid and the netns NAME */
116 stream_put(s, &data, sizeof(struct vrf_data));
117 /* Interface information. */
118 stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ);
119 /* Write packet size. */
120 stream_putw_at(s, 0, stream_get_endp(s));
121}
122
123static int zserv_encode_nexthop(struct stream *s, struct nexthop *nexthop)
124{
a756969d 125 stream_putl(s, nexthop->vrf_id);
bf094f69
QY
126 stream_putc(s, nexthop->type);
127 switch (nexthop->type) {
128 case NEXTHOP_TYPE_IPV4:
129 case NEXTHOP_TYPE_IPV4_IFINDEX:
130 stream_put_in_addr(s, &nexthop->gate.ipv4);
131 stream_putl(s, nexthop->ifindex);
132 break;
133 case NEXTHOP_TYPE_IPV6:
134 stream_put(s, &nexthop->gate.ipv6, 16);
135 break;
136 case NEXTHOP_TYPE_IPV6_IFINDEX:
137 stream_put(s, &nexthop->gate.ipv6, 16);
138 stream_putl(s, nexthop->ifindex);
139 break;
140 case NEXTHOP_TYPE_IFINDEX:
141 stream_putl(s, nexthop->ifindex);
142 break;
143 default:
144 /* do nothing */
145 break;
146 }
147 return 1;
148}
149
9ab0b2a3
SW
150/*
151 * Zebra error addition adds error type.
152 *
153 *
154 * 0 1
155 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
156 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 * | enum zebra_error_types |
158 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 *
160 */
161static void zserv_encode_error(struct stream *s, enum zebra_error_types error)
162{
163 stream_put(s, &error, sizeof(error));
164
165 /* Write packet size. */
166 stream_putw_at(s, 0, stream_get_endp(s));
167}
168
bf094f69
QY
169/* Send handlers ----------------------------------------------------------- */
170
171/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
172/*
173 * This function is called in the following situations:
174 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
175 * from the client.
176 * - at startup, when zebra figures out the available interfaces
177 * - when an interface is added (where support for
178 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
179 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
180 * received)
181 */
182int zsend_interface_add(struct zserv *client, struct interface *ifp)
183{
184 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
185
a36898e7 186 zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id);
bf094f69
QY
187 zserv_encode_interface(s, ifp);
188
189 client->ifadd_cnt++;
21ccc0cf 190 return zserv_send_message(client, s);
bf094f69
QY
191}
192
193/* Interface deletion from zebra daemon. */
194int zsend_interface_delete(struct zserv *client, struct interface *ifp)
195{
196 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
197
a36898e7 198 zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id);
bf094f69
QY
199 zserv_encode_interface(s, ifp);
200
201 client->ifdel_cnt++;
21ccc0cf 202 return zserv_send_message(client, s);
bf094f69
QY
203}
204
205int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf)
206{
207 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
208
209 zclient_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf));
210 zserv_encode_vrf(s, zvrf);
211
212 client->vrfadd_cnt++;
21ccc0cf 213 return zserv_send_message(client, s);
bf094f69
QY
214}
215
216/* VRF deletion from zebra daemon. */
217int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf)
218
219{
220 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
221
222 zclient_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf));
223 zserv_encode_vrf(s, zvrf);
224
225 client->vrfdel_cnt++;
21ccc0cf 226 return zserv_send_message(client, s);
bf094f69
QY
227}
228
229int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
230{
231 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
232
bf094f69
QY
233 if (!ifp->link_params) {
234 stream_free(s);
235 return 0;
236 }
237
a36898e7 238 zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id);
bf094f69
QY
239
240 /* Add Interface Index */
241 stream_putl(s, ifp->ifindex);
242
243 /* Then TE Link Parameters */
244 if (zebra_interface_link_params_write(s, ifp) == 0) {
245 stream_free(s);
246 return 0;
247 }
248
249 /* Write packet size. */
250 stream_putw_at(s, 0, stream_get_endp(s));
251
21ccc0cf 252 return zserv_send_message(client, s);
bf094f69
QY
253}
254
255/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
256 * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
257 *
258 * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
259 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
260 * from the client, after the ZEBRA_INTERFACE_ADD has been
261 * sent from zebra to the client
262 * - redistribute new address info to all clients in the following situations
263 * - at startup, when zebra figures out the available interfaces
264 * - when an interface is added (where support for
265 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
266 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
267 * received)
b1bd1015 268 * - for the vty commands "ip address A.B.C.D/M [<label LINE>]"
bf094f69
QY
269 * and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
270 * - when an RTM_NEWADDR message is received from the kernel,
271 *
272 * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:
273 *
274 * zsend_interface_address(DELETE)
275 * ^
276 * |
277 * zebra_interface_address_delete_update
278 * ^ ^ ^
279 * | | if_delete_update
280 * | |
281 * ip_address_uninstall connected_delete_ipv4
282 * [ipv6_addresss_uninstall] [connected_delete_ipv6]
283 * ^ ^
284 * | |
285 * | RTM_NEWADDR on routing/netlink socket
286 * |
287 * vty commands:
288 * "no ip address A.B.C.D/M [label LINE]"
b1bd1015 289 * "no ip address A.B.C.D/M"
bf094f69
QY
290 * ["no ipv6 address X:X::X:X/M"]
291 *
292 */
293int zsend_interface_address(int cmd, struct zserv *client,
294 struct interface *ifp, struct connected *ifc)
295{
296 int blen;
297 struct prefix *p;
298 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
299
a36898e7 300 zclient_create_header(s, cmd, ifp->vrf_id);
bf094f69
QY
301 stream_putl(s, ifp->ifindex);
302
303 /* Interface address flag. */
304 stream_putc(s, ifc->flags);
305
306 /* Prefix information. */
307 p = ifc->address;
308 stream_putc(s, p->family);
309 blen = prefix_blen(p);
310 stream_put(s, &p->u.prefix, blen);
311
312 /*
313 * XXX gnu version does not send prefixlen for
314 * ZEBRA_INTERFACE_ADDRESS_DELETE
315 * but zebra_interface_address_delete_read() in the gnu version
316 * expects to find it
317 */
318 stream_putc(s, p->prefixlen);
319
320 /* Destination. */
321 p = ifc->destination;
322 if (p)
323 stream_put(s, &p->u.prefix, blen);
324 else
325 stream_put(s, NULL, blen);
326
327 /* Write packet size. */
328 stream_putw_at(s, 0, stream_get_endp(s));
329
330 client->connected_rt_add_cnt++;
21ccc0cf 331 return zserv_send_message(client, s);
bf094f69
QY
332}
333
334static int zsend_interface_nbr_address(int cmd, struct zserv *client,
335 struct interface *ifp,
336 struct nbr_connected *ifc)
337{
338 int blen;
339 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
340 struct prefix *p;
341
a36898e7 342 zclient_create_header(s, cmd, ifp->vrf_id);
bf094f69
QY
343 stream_putl(s, ifp->ifindex);
344
345 /* Prefix information. */
346 p = ifc->address;
347 stream_putc(s, p->family);
348 blen = prefix_blen(p);
349 stream_put(s, &p->u.prefix, blen);
350
351 /*
352 * XXX gnu version does not send prefixlen for
353 * ZEBRA_INTERFACE_ADDRESS_DELETE
354 * but zebra_interface_address_delete_read() in the gnu version
355 * expects to find it
356 */
357 stream_putc(s, p->prefixlen);
358
359 /* Write packet size. */
360 stream_putw_at(s, 0, stream_get_endp(s));
361
21ccc0cf 362 return zserv_send_message(client, s);
bf094f69
QY
363}
364
365/* Interface address addition. */
366static void zebra_interface_nbr_address_add_update(struct interface *ifp,
367 struct nbr_connected *ifc)
368{
369 struct listnode *node, *nnode;
370 struct zserv *client;
371 struct prefix *p;
372
373 if (IS_ZEBRA_DEBUG_EVENT) {
374 char buf[INET6_ADDRSTRLEN];
375
376 p = ifc->address;
377 zlog_debug(
378 "MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s",
379 inet_ntop(p->family, &p->u.prefix, buf,
380 INET6_ADDRSTRLEN),
381 p->prefixlen, ifc->ifp->name);
382 }
383
17da84a4
KS
384 for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
385 /* Do not send unsolicited messages to synchronous clients. */
386 if (client->synchronous)
387 continue;
388
bf094f69
QY
389 zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
390 client, ifp, ifc);
17da84a4 391 }
bf094f69
QY
392}
393
394/* Interface address deletion. */
395static void zebra_interface_nbr_address_delete_update(struct interface *ifp,
396 struct nbr_connected *ifc)
397{
398 struct listnode *node, *nnode;
399 struct zserv *client;
400 struct prefix *p;
401
402 if (IS_ZEBRA_DEBUG_EVENT) {
403 char buf[INET6_ADDRSTRLEN];
404
405 p = ifc->address;
406 zlog_debug(
407 "MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s",
408 inet_ntop(p->family, &p->u.prefix, buf,
409 INET6_ADDRSTRLEN),
410 p->prefixlen, ifc->ifp->name);
411 }
412
17da84a4
KS
413 for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
414 /* Do not send unsolicited messages to synchronous clients. */
415 if (client->synchronous)
416 continue;
417
bf094f69
QY
418 zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
419 client, ifp, ifc);
17da84a4 420 }
bf094f69
QY
421}
422
423/* Send addresses on interface to client */
424int zsend_interface_addresses(struct zserv *client, struct interface *ifp)
425{
426 struct listnode *cnode, *cnnode;
427 struct connected *c;
428 struct nbr_connected *nc;
429
430 /* Send interface addresses. */
431 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
432 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
433 continue;
434
435 if (zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, client,
436 ifp, c)
437 < 0)
438 return -1;
439 }
440
441 /* Send interface neighbors. */
442 for (ALL_LIST_ELEMENTS(ifp->nbr_connected, cnode, cnnode, nc)) {
443 if (zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
444 client, ifp, nc)
445 < 0)
446 return -1;
447 }
448
449 return 0;
450}
451
452/* Notify client about interface moving from one VRF to another.
453 * Whether client is interested in old and new VRF is checked by caller.
454 */
455int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
456 vrf_id_t vrf_id)
457{
458 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
459
a36898e7 460 zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
bf094f69 461
91d227b7
RW
462 /* Fill in the name of the interface and its new VRF (id) */
463 stream_put(s, ifp->name, INTERFACE_NAMSIZ);
bf094f69
QY
464 stream_putl(s, vrf_id);
465
466 /* Write packet size. */
467 stream_putw_at(s, 0, stream_get_endp(s));
468
469 client->if_vrfchg_cnt++;
21ccc0cf 470 return zserv_send_message(client, s);
bf094f69
QY
471}
472
473/* Add new nbr connected IPv6 address */
474void nbr_connected_add_ipv6(struct interface *ifp, struct in6_addr *address)
475{
476 struct nbr_connected *ifc;
477 struct prefix p;
478
479 p.family = AF_INET6;
a85297a7 480 IPV6_ADDR_COPY(&p.u.prefix6, address);
bf094f69
QY
481 p.prefixlen = IPV6_MAX_PREFIXLEN;
482
8b1766b1
QY
483 ifc = listnode_head(ifp->nbr_connected);
484 if (!ifc) {
bf094f69
QY
485 /* new addition */
486 ifc = nbr_connected_new();
487 ifc->address = prefix_new();
488 ifc->ifp = ifp;
489 listnode_add(ifp->nbr_connected, ifc);
490 }
491
492 prefix_copy(ifc->address, &p);
493
494 zebra_interface_nbr_address_add_update(ifp, ifc);
495
496 if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 1);
497}
498
499void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address)
500{
501 struct nbr_connected *ifc;
502 struct prefix p;
503
504 p.family = AF_INET6;
a85297a7 505 IPV6_ADDR_COPY(&p.u.prefix6, address);
bf094f69
QY
506 p.prefixlen = IPV6_MAX_PREFIXLEN;
507
508 ifc = nbr_connected_check(ifp, &p);
509 if (!ifc)
510 return;
511
512 listnode_delete(ifp->nbr_connected, ifc);
513
514 zebra_interface_nbr_address_delete_update(ifp, ifc);
515
516 if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, address, 0);
517
518 nbr_connected_free(ifc);
519}
520
521/*
522 * The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or
523 * ZEBRA_INTERFACE_DOWN.
524 *
525 * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
526 * the clients in one of 2 situations:
527 * - an if_up is detected e.g., as a result of an RTM_IFINFO message
528 * - a vty command modifying the bandwidth of an interface is received.
529 * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
530 */
531int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
532{
533 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
534
a36898e7 535 zclient_create_header(s, cmd, ifp->vrf_id);
bf094f69
QY
536 zserv_encode_interface(s, ifp);
537
538 if (cmd == ZEBRA_INTERFACE_UP)
539 client->ifup_cnt++;
540 else
541 client->ifdown_cnt++;
542
21ccc0cf 543 return zserv_send_message(client, s);
bf094f69
QY
544}
545
86391e56
MS
546int zsend_redistribute_route(int cmd, struct zserv *client,
547 const struct prefix *p,
40f321c0
MS
548 const struct prefix *src_p,
549 const struct route_entry *re)
bf094f69
QY
550{
551 struct zapi_route api;
552 struct zapi_nexthop *api_nh;
553 struct nexthop *nexthop;
9a0d4dd3 554 uint8_t count = 0;
34fa0870 555 afi_t afi;
f3f45626
DS
556 size_t stream_size =
557 MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
bf094f69
QY
558
559 memset(&api, 0, sizeof(api));
560 api.vrf_id = re->vrf_id;
561 api.type = re->type;
e4081c0e 562 api.safi = SAFI_UNICAST;
bf094f69
QY
563 api.instance = re->instance;
564 api.flags = re->flags;
565
34fa0870
DS
566 afi = family2afi(p->family);
567 switch (afi) {
568 case AFI_IP:
569 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
570 client->redist_v4_add_cnt++;
571 else
572 client->redist_v4_del_cnt++;
573 break;
574 case AFI_IP6:
575 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
576 client->redist_v6_add_cnt++;
577 else
578 client->redist_v6_del_cnt++;
579 break;
580 default:
581 break;
582 }
583
bf094f69
QY
584 /* Prefix. */
585 api.prefix = *p;
586 if (src_p) {
587 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
588 memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
589 }
590
c415d895 591 for (nexthop = re->nhe->nhg.nexthop;
0eb97b86 592 nexthop; nexthop = nexthop->next) {
bf094f69
QY
593 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
594 continue;
595
596 api_nh = &api.nexthops[count];
597 api_nh->vrf_id = nexthop->vrf_id;
598 api_nh->type = nexthop->type;
bd054c1a 599 api_nh->weight = nexthop->weight;
bf094f69
QY
600 switch (nexthop->type) {
601 case NEXTHOP_TYPE_BLACKHOLE:
602 api_nh->bh_type = nexthop->bh_type;
603 break;
604 case NEXTHOP_TYPE_IPV4:
605 api_nh->gate.ipv4 = nexthop->gate.ipv4;
606 break;
607 case NEXTHOP_TYPE_IPV4_IFINDEX:
608 api_nh->gate.ipv4 = nexthop->gate.ipv4;
609 api_nh->ifindex = nexthop->ifindex;
610 break;
611 case NEXTHOP_TYPE_IFINDEX:
612 api_nh->ifindex = nexthop->ifindex;
613 break;
614 case NEXTHOP_TYPE_IPV6:
615 api_nh->gate.ipv6 = nexthop->gate.ipv6;
616 break;
617 case NEXTHOP_TYPE_IPV6_IFINDEX:
618 api_nh->gate.ipv6 = nexthop->gate.ipv6;
619 api_nh->ifindex = nexthop->ifindex;
620 }
621 count++;
622 }
623
9a0d4dd3
DS
624 /* Nexthops. */
625 if (count) {
626 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
627 api.nexthop_num = count;
628 }
629
bf094f69
QY
630 /* Attributes. */
631 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
632 api.distance = re->distance;
633 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
634 api.metric = re->metric;
635 if (re->tag) {
636 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
637 api.tag = re->tag;
638 }
639 SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
640 api.mtu = re->mtu;
641
f3f45626 642 struct stream *s = stream_new(stream_size);
bf094f69
QY
643
644 /* Encode route and send. */
645 if (zapi_route_encode(cmd, s, &api) < 0) {
646 stream_free(s);
647 return -1;
648 }
649
2dbe669b
DA
650 if (IS_ZEBRA_DEBUG_SEND)
651 zlog_debug("%s: %s to client %s: type %s, vrf_id %d, p %pFX",
bf094f69
QY
652 __func__, zserv_command_string(cmd),
653 zebra_route_string(client->proto),
654 zebra_route_string(api.type), api.vrf_id,
2dbe669b 655 &api.prefix);
21ccc0cf 656 return zserv_send_message(client, s);
bf094f69
QY
657}
658
659/*
660 * Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if
661 * nexthop is not found on mrib. Returns both route metric and protocol
662 * distance.
663 */
664static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
665 struct in_addr addr,
666 struct route_entry *re,
667 struct zebra_vrf *zvrf)
668{
669 struct stream *s;
670 unsigned long nump;
671 uint8_t num;
672 struct nexthop *nexthop;
673
674 /* Get output stream. */
675 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
676 stream_reset(s);
677
678 /* Fill in result. */
679 zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
680 stream_put_in_addr(s, &addr);
681
682 if (re) {
683 stream_putc(s, re->distance);
684 stream_putl(s, re->metric);
685 num = 0;
8b1766b1
QY
686 /* remember position for nexthop_num */
687 nump = stream_get_endp(s);
688 /* reserve room for nexthop_num */
689 stream_putc(s, 0);
690 /*
691 * Only non-recursive routes are elegible to resolve the
692 * nexthop we are looking up. Therefore, we will just iterate
693 * over the top chain of nexthops.
694 */
c415d895 695 for (nexthop = re->nhe->nhg.nexthop; nexthop;
6b468511 696 nexthop = nexthop->next)
bf094f69
QY
697 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
698 num += zserv_encode_nexthop(s, nexthop);
699
8b1766b1
QY
700 /* store nexthop_num */
701 stream_putc_at(s, nump, num);
bf094f69
QY
702 } else {
703 stream_putc(s, 0); /* distance */
704 stream_putl(s, 0); /* metric */
705 stream_putc(s, 0); /* nexthop_num */
706 }
707
708 stream_putw_at(s, 0, stream_get_endp(s));
709
21ccc0cf 710 return zserv_send_message(client, s);
bf094f69
QY
711}
712
ee94437e
MS
713int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id,
714 uint32_t id, enum zapi_nhg_notify_owner note)
2f35a820
DS
715{
716 struct zserv *client;
717 struct stream *s;
718
ee94437e 719 client = zserv_find_client_session(type, instance, session_id);
2f35a820
DS
720 if (!client) {
721 if (IS_ZEBRA_DEBUG_PACKET) {
722 zlog_debug("Not Notifying Owner: %u(%u) about %u(%d)",
723 type, instance, id, note);
724 }
725 return 0;
726 }
727
ee94437e
MS
728 if (IS_ZEBRA_DEBUG_SEND)
729 zlog_debug("%s: type %d, id %d, note %d",
730 __func__, type, id, note);
731
2f35a820
DS
732 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
733 stream_reset(s);
734
735 zclient_create_header(s, ZEBRA_NHG_NOTIFY_OWNER, VRF_DEFAULT);
736
2f35a820 737 stream_put(s, &note, sizeof(note));
2c7819b9 738 stream_putl(s, id);
2f35a820
DS
739
740 stream_putw_at(s, 0, stream_get_endp(s));
741
742 return zserv_send_message(client, s);
743}
744
86391e56
MS
745/*
746 * Common utility send route notification, called from a path using a
747 * route_entry and from a path using a dataplane context.
748 */
749static int route_notify_internal(const struct prefix *p, int type,
750 uint16_t instance, vrf_id_t vrf_id,
751 uint32_t table_id,
77b38a4a
S
752 enum zapi_route_notify_owner note,
753 afi_t afi, safi_t safi)
bf094f69
QY
754{
755 struct zserv *client;
756 struct stream *s;
757 uint8_t blen;
758
86391e56 759 client = zserv_find_client(type, instance);
bf094f69 760 if (!client || !client->notify_owner) {
2dbe669b 761 if (IS_ZEBRA_DEBUG_PACKET)
bf094f69 762 zlog_debug(
2dbe669b
DA
763 "Not Notifying Owner: %s about prefix %pFX(%u) %d vrf: %u",
764 zebra_route_string(type), p, table_id, note,
765 vrf_id);
bf094f69
QY
766 return 0;
767 }
768
2dbe669b
DA
769 if (IS_ZEBRA_DEBUG_PACKET)
770 zlog_debug(
771 "Notifying Owner: %s about prefix %pFX(%u) %d vrf: %u",
772 zebra_route_string(type), p, table_id, note, vrf_id);
bf094f69 773
55e74ca9
MS
774 /* We're just allocating a small-ish buffer here, since we only
775 * encode a small amount of data.
776 */
777 s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
778
bf094f69
QY
779 stream_reset(s);
780
86391e56 781 zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id);
bf094f69
QY
782
783 stream_put(s, &note, sizeof(note));
784
785 stream_putc(s, p->family);
786
787 blen = prefix_blen(p);
788 stream_putc(s, p->prefixlen);
789 stream_put(s, &p->u.prefix, blen);
790
86391e56 791 stream_putl(s, table_id);
bf094f69 792
77b38a4a
S
793 /* Encode AFI, SAFI in the message */
794 stream_putc(s, afi);
795 stream_putc(s, safi);
796
bf094f69
QY
797 stream_putw_at(s, 0, stream_get_endp(s));
798
21ccc0cf 799 return zserv_send_message(client, s);
bf094f69
QY
800}
801
86391e56 802int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p,
77b38a4a
S
803 enum zapi_route_notify_owner note,
804 afi_t afi, safi_t safi)
86391e56
MS
805{
806 return (route_notify_internal(p, re->type, re->instance, re->vrf_id,
77b38a4a 807 re->table, note, afi, safi));
86391e56
MS
808}
809
7cdb1a84
MS
810/*
811 * Route-owner notification using info from dataplane update context.
812 */
25779064 813int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
7cdb1a84
MS
814 enum zapi_route_notify_owner note)
815{
816 return (route_notify_internal(dplane_ctx_get_dest(ctx),
817 dplane_ctx_get_type(ctx),
818 dplane_ctx_get_instance(ctx),
819 dplane_ctx_get_vrf(ctx),
820 dplane_ctx_get_table(ctx),
77b38a4a
S
821 note,
822 dplane_ctx_get_afi(ctx),
823 dplane_ctx_get_safi(ctx)));
824}
825
826static void zread_route_notify_request(ZAPI_HANDLER_ARGS)
827{
828 uint8_t notify;
829
830 STREAM_GETC(msg, notify);
831 client->notify_owner = notify;
832stream_failure:
833 return;
86391e56
MS
834}
835
f62e5480 836void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
bf094f69
QY
837 enum zapi_rule_notify_owner note)
838{
839 struct listnode *node;
840 struct zserv *client;
841 struct stream *s;
842
843 if (IS_ZEBRA_DEBUG_PACKET)
f62e5480
JU
844 zlog_debug("%s: Notifying %u", __func__,
845 dplane_ctx_rule_get_unique(ctx));
bf094f69 846
161e9ab7 847 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
f62e5480 848 if (dplane_ctx_rule_get_sock(ctx) == client->sock)
bf094f69
QY
849 break;
850 }
851
852 if (!client)
853 return;
854
855 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
856
857 zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
858 stream_put(s, &note, sizeof(note));
f62e5480
JU
859 stream_putl(s, dplane_ctx_rule_get_seq(ctx));
860 stream_putl(s, dplane_ctx_rule_get_priority(ctx));
861 stream_putl(s, dplane_ctx_rule_get_unique(ctx));
58a1d249 862 stream_put(s, dplane_ctx_rule_get_ifname(ctx), INTERFACE_NAMSIZ);
bf094f69
QY
863
864 stream_putw_at(s, 0, stream_get_endp(s));
865
21ccc0cf 866 zserv_send_message(client, s);
bf094f69
QY
867}
868
ef524230
PG
869void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
870 uint16_t note)
bf094f69
QY
871{
872 struct listnode *node;
873 struct zserv *client;
874 struct stream *s;
ef524230
PG
875 struct zebra_pbr_iptable ipt;
876 uint16_t cmd = ZEBRA_IPTABLE_NOTIFY_OWNER;
877
878 if (!dplane_ctx_get_pbr_iptable(ctx, &ipt))
879 return;
bf094f69
QY
880
881 if (IS_ZEBRA_DEBUG_PACKET)
ef524230
PG
882 zlog_debug("%s: Notifying %s id %u note %u", __func__,
883 zserv_command_string(cmd), ipt.unique, note);
bf094f69 884
161e9ab7 885 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
ef524230 886 if (ipt.sock == client->sock)
bf094f69
QY
887 break;
888 }
889
890 if (!client)
891 return;
892
893 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
894
5162e000 895 zclient_create_header(s, cmd, VRF_DEFAULT);
bf094f69 896 stream_put(s, &note, sizeof(note));
ef524230
PG
897 stream_putl(s, ipt.unique);
898 stream_put(s, ipt.ipset_name, ZEBRA_IPSET_NAME_SIZE);
bf094f69
QY
899 stream_putw_at(s, 0, stream_get_endp(s));
900
21ccc0cf 901 zserv_send_message(client, s);
bf094f69
QY
902}
903
ef524230 904void zsend_ipset_notify_owner(const struct zebra_dplane_ctx *ctx, uint16_t note)
bf094f69
QY
905{
906 struct listnode *node;
907 struct zserv *client;
908 struct stream *s;
ef524230
PG
909 struct zebra_pbr_ipset ipset;
910 uint16_t cmd = ZEBRA_IPSET_NOTIFY_OWNER;
911
912 if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
913 return;
bf094f69
QY
914
915 if (IS_ZEBRA_DEBUG_PACKET)
ef524230
PG
916 zlog_debug("%s: Notifying %s id %u note %u", __func__,
917 zserv_command_string(cmd), ipset.unique, note);
bf094f69 918
161e9ab7 919 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
ef524230 920 if (ipset.sock == client->sock)
bf094f69
QY
921 break;
922 }
923
924 if (!client)
925 return;
926
927 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
928
ef524230 929 zclient_create_header(s, cmd, VRF_DEFAULT);
bf094f69 930 stream_put(s, &note, sizeof(note));
ef524230
PG
931 stream_putl(s, ipset.unique);
932 stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
bf094f69
QY
933 stream_putw_at(s, 0, stream_get_endp(s));
934
21ccc0cf 935 zserv_send_message(client, s);
bf094f69
QY
936}
937
ef524230
PG
938void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
939 uint16_t note)
bf094f69
QY
940{
941 struct listnode *node;
942 struct zserv *client;
943 struct stream *s;
ef524230
PG
944 struct zebra_pbr_ipset_entry ipent;
945 struct zebra_pbr_ipset ipset;
946 uint16_t cmd = ZEBRA_IPSET_ENTRY_NOTIFY_OWNER;
5162e000 947
ef524230
PG
948 if (!dplane_ctx_get_pbr_ipset_entry(ctx, &ipent))
949 return;
950 if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
5162e000 951 return;
bf094f69
QY
952
953 if (IS_ZEBRA_DEBUG_PACKET)
5162e000 954 zlog_debug("%s: Notifying %s id %u note %u", __func__,
ef524230 955 zserv_command_string(cmd), ipent.unique, note);
bf094f69 956
161e9ab7 957 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
ef524230 958 if (ipent.sock == client->sock)
bf094f69
QY
959 break;
960 }
961
962 if (!client)
963 return;
964
965 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
966
5162e000 967 zclient_create_header(s, cmd, VRF_DEFAULT);
bf094f69 968 stream_put(s, &note, sizeof(note));
ef524230
PG
969 stream_putl(s, ipent.unique);
970 stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
bf094f69
QY
971 stream_putw_at(s, 0, stream_get_endp(s));
972
21ccc0cf 973 zserv_send_message(client, s);
bf094f69
QY
974}
975
98a3fb0a
SM
976/* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */
977int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,
bf094f69
QY
978 vrf_id_t vrf_id)
979{
980 int blen;
98a3fb0a 981 struct stream *s;
bf094f69
QY
982
983 /* Check this client need interface information. */
98a3fb0a 984 if (!vrf_bitmap_check(client->ridinfo[afi], vrf_id))
bf094f69
QY
985 return 0;
986
98a3fb0a 987 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
bf094f69
QY
988
989 /* Message type. */
990 zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
991
992 /* Prefix information. */
993 stream_putc(s, p->family);
994 blen = prefix_blen(p);
995 stream_put(s, &p->u.prefix, blen);
996 stream_putc(s, p->prefixlen);
997
998 /* Write packet size. */
999 stream_putw_at(s, 0, stream_get_endp(s));
1000
21ccc0cf 1001 return zserv_send_message(client, s);
bf094f69
QY
1002}
1003
1004/*
1005 * Function used by Zebra to send a PW status update to LDP daemon
1006 */
1007int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
1008{
1009 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1010
1011 zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
1012 stream_write(s, pw->ifname, IF_NAMESIZE);
1013 stream_putl(s, pw->ifindex);
1014 stream_putl(s, pw->status);
1015
1016 /* Put length at the first point of the stream. */
1017 stream_putw_at(s, 0, stream_get_endp(s));
1018
21ccc0cf 1019 return zserv_send_message(client, s);
bf094f69
QY
1020}
1021
1022/* Send response to a get label chunk request to client */
e11d7c96 1023int zsend_assign_label_chunk_response(struct zserv *client, vrf_id_t vrf_id,
e11d7c96 1024 struct label_manager_chunk *lmc)
bf094f69 1025{
bf094f69
QY
1026 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1027
1028 zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id);
f004f7c3 1029 /* proto */
4cebdb9b 1030 stream_putc(s, client->proto);
f004f7c3 1031 /* instance */
4cebdb9b 1032 stream_putw(s, client->instance);
bf094f69
QY
1033
1034 if (lmc) {
1035 /* keep */
1036 stream_putc(s, lmc->keep);
1037 /* start and end labels */
1038 stream_putl(s, lmc->start);
1039 stream_putl(s, lmc->end);
1040 }
1041
1042 /* Write packet size. */
1043 stream_putw_at(s, 0, stream_get_endp(s));
1044
732d22cb 1045 return zserv_send_message(client, s);
bf094f69
QY
1046}
1047
1048/* Send response to a label manager connect request to client */
e11d7c96
EDP
1049int zsend_label_manager_connect_response(struct zserv *client, vrf_id_t vrf_id,
1050 unsigned short result)
bf094f69 1051{
bf094f69
QY
1052 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1053
1054 zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id);
1055
5dffb0e9
FR
1056 /* proto */
1057 stream_putc(s, client->proto);
1058
1059 /* instance */
1060 stream_putw(s, client->instance);
1061
bf094f69
QY
1062 /* result */
1063 stream_putc(s, result);
1064
1065 /* Write packet size. */
1066 stream_putw_at(s, 0, stream_get_endp(s));
1067
732d22cb 1068 return zserv_send_message(client, s);
bf094f69
QY
1069}
1070
1071/* Send response to a get table chunk request to client */
1072static int zsend_assign_table_chunk_response(struct zserv *client,
1073 vrf_id_t vrf_id,
1074 struct table_manager_chunk *tmc)
1075{
1076 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1077
1078 zclient_create_header(s, ZEBRA_GET_TABLE_CHUNK, vrf_id);
1079
1080 if (tmc) {
1081 /* start and end labels */
1082 stream_putl(s, tmc->start);
1083 stream_putl(s, tmc->end);
1084 }
1085
1086 /* Write packet size. */
1087 stream_putw_at(s, 0, stream_get_endp(s));
1088
21ccc0cf 1089 return zserv_send_message(client, s);
bf094f69
QY
1090}
1091
1092static int zsend_table_manager_connect_response(struct zserv *client,
1093 vrf_id_t vrf_id,
1094 uint16_t result)
1095{
1096 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1097
1098 zclient_create_header(s, ZEBRA_TABLE_MANAGER_CONNECT, vrf_id);
1099
1100 /* result */
1101 stream_putc(s, result);
1102
1103 stream_putw_at(s, 0, stream_get_endp(s));
1104
21ccc0cf 1105 return zserv_send_message(client, s);
bf094f69
QY
1106}
1107
1108/* Inbound message handling ------------------------------------------------ */
1109
2b64873d 1110const int cmd2type[] = {
bf094f69
QY
1111 [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE,
1112 [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE,
1113 [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE,
1114 [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE,
1115};
1116
1117/* Nexthop register */
1118static void zread_rnh_register(ZAPI_HANDLER_ARGS)
1119{
1120 struct rnh *rnh;
1121 struct stream *s;
1122 struct prefix p;
1123 unsigned short l = 0;
1124 uint8_t flags = 0;
1125 uint16_t type = cmd2type[hdr->command];
1d30d1f4 1126 bool exist;
906b54dd
DS
1127 bool flag_changed = false;
1128 uint8_t orig_flags;
bf094f69
QY
1129
1130 if (IS_ZEBRA_DEBUG_NHT)
1131 zlog_debug(
63efca0e 1132 "rnh_register msg from client %s: hdr->length=%d, type=%s vrf=%u",
bf094f69
QY
1133 zebra_route_string(client->proto), hdr->length,
1134 (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route",
1135 zvrf->vrf->vrf_id);
1136
1137 s = msg;
1138
469d6277
DS
1139 if (!client->nh_reg_time)
1140 client->nh_reg_time = monotime(NULL);
bf094f69
QY
1141
1142 while (l < hdr->length) {
1143 STREAM_GETC(s, flags);
1144 STREAM_GETW(s, p.family);
1145 STREAM_GETC(s, p.prefixlen);
1146 l += 4;
1147 if (p.family == AF_INET) {
ab5990d8 1148 client->v4_nh_watch_add_cnt++;
bf094f69 1149 if (p.prefixlen > IPV4_MAX_BITLEN) {
9df414fe 1150 zlog_debug(
bf094f69 1151 "%s: Specified prefix hdr->length %d is too large for a v4 address",
15569c58 1152 __func__, p.prefixlen);
bf094f69
QY
1153 return;
1154 }
1155 STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
1156 l += IPV4_MAX_BYTELEN;
1157 } else if (p.family == AF_INET6) {
ab5990d8 1158 client->v6_nh_watch_add_cnt++;
bf094f69 1159 if (p.prefixlen > IPV6_MAX_BITLEN) {
9df414fe 1160 zlog_debug(
bf094f69 1161 "%s: Specified prefix hdr->length %d is to large for a v6 address",
15569c58 1162 __func__, p.prefixlen);
bf094f69
QY
1163 return;
1164 }
1165 STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
1166 l += IPV6_MAX_BYTELEN;
1167 } else {
af4c2728 1168 flog_err(
e914ccbe 1169 EC_ZEBRA_UNKNOWN_FAMILY,
1d5453d6 1170 "rnh_register: Received unknown family type %d",
bf094f69
QY
1171 p.family);
1172 return;
1173 }
1d30d1f4
DS
1174 rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist);
1175 if (!rnh)
1176 return;
1177
906b54dd 1178 orig_flags = rnh->flags;
bf094f69
QY
1179 if (type == RNH_NEXTHOP_TYPE) {
1180 if (flags
1181 && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
1182 SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
1183 else if (!flags
1184 && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
1185 UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
1186 } else if (type == RNH_IMPORT_CHECK_TYPE) {
1187 if (flags
1188 && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
1189 SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
1190 else if (!flags
1191 && CHECK_FLAG(rnh->flags,
1192 ZEBRA_NHT_EXACT_MATCH))
1193 UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
1194 }
1195
906b54dd
DS
1196 if (orig_flags != rnh->flags)
1197 flag_changed = true;
1198
bf094f69 1199 /* Anything not AF_INET/INET6 has been filtered out above */
906b54dd 1200 if (!exist || flag_changed)
73bf60a0
RW
1201 zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type,
1202 &p);
dd25a6b3
DS
1203
1204 zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
bf094f69
QY
1205 }
1206
1207stream_failure:
1208 return;
1209}
1210
1211/* Nexthop register */
1212static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
1213{
1214 struct rnh *rnh;
1215 struct stream *s;
1216 struct prefix p;
1217 unsigned short l = 0;
1218 uint16_t type = cmd2type[hdr->command];
1219
1220 if (IS_ZEBRA_DEBUG_NHT)
1221 zlog_debug(
63efca0e 1222 "rnh_unregister msg from client %s: hdr->length=%d vrf: %u",
bf094f69
QY
1223 zebra_route_string(client->proto), hdr->length,
1224 zvrf->vrf->vrf_id);
1225
1226 s = msg;
1227
1228 while (l < hdr->length) {
1229 uint8_t flags;
1230
1231 STREAM_GETC(s, flags);
1232 if (flags != 0)
1233 goto stream_failure;
1234
1235 STREAM_GETW(s, p.family);
1236 STREAM_GETC(s, p.prefixlen);
1237 l += 4;
1238 if (p.family == AF_INET) {
ab5990d8 1239 client->v4_nh_watch_rem_cnt++;
bf094f69 1240 if (p.prefixlen > IPV4_MAX_BITLEN) {
9df414fe 1241 zlog_debug(
bf094f69 1242 "%s: Specified prefix hdr->length %d is to large for a v4 address",
15569c58 1243 __func__, p.prefixlen);
bf094f69
QY
1244 return;
1245 }
1246 STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
1247 l += IPV4_MAX_BYTELEN;
1248 } else if (p.family == AF_INET6) {
ab5990d8 1249 client->v6_nh_watch_rem_cnt++;
bf094f69 1250 if (p.prefixlen > IPV6_MAX_BITLEN) {
9df414fe 1251 zlog_debug(
bf094f69 1252 "%s: Specified prefix hdr->length %d is to large for a v6 address",
15569c58 1253 __func__, p.prefixlen);
bf094f69
QY
1254 return;
1255 }
1256 STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
1257 l += IPV6_MAX_BYTELEN;
1258 } else {
af4c2728 1259 flog_err(
e914ccbe 1260 EC_ZEBRA_UNKNOWN_FAMILY,
1d5453d6 1261 "rnh_register: Received unknown family type %d",
bf094f69
QY
1262 p.family);
1263 return;
1264 }
1265 rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type);
1266 if (rnh) {
1267 client->nh_dereg_time = monotime(NULL);
1268 zebra_remove_rnh_client(rnh, client, type);
1269 }
1270 }
1271stream_failure:
1272 return;
1273}
1274
1275#define ZEBRA_MIN_FEC_LENGTH 5
1276
1277/* FEC register */
1278static void zread_fec_register(ZAPI_HANDLER_ARGS)
1279{
1280 struct stream *s;
1281 unsigned short l = 0;
1282 struct prefix p;
1283 uint16_t flags;
57592a53 1284 uint32_t label = MPLS_INVALID_LABEL;
bf094f69
QY
1285 uint32_t label_index = MPLS_INVALID_LABEL_INDEX;
1286
1287 s = msg;
1288 zvrf = vrf_info_lookup(VRF_DEFAULT);
1289 if (!zvrf)
8b1766b1 1290 return;
bf094f69
QY
1291
1292 /*
1293 * The minimum amount of data that can be sent for one fec
1294 * registration
1295 */
1296 if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
af4c2728 1297 flog_err(
e914ccbe 1298 EC_ZEBRA_IRDP_LEN_MISMATCH,
bf094f69
QY
1299 "fec_register: Received a fec register of hdr->length %d, it is of insufficient size to properly decode",
1300 hdr->length);
1301 return;
1302 }
1303
1304 while (l < hdr->length) {
1305 STREAM_GETW(s, flags);
1306 memset(&p, 0, sizeof(p));
1307 STREAM_GETW(s, p.family);
1308 if (p.family != AF_INET && p.family != AF_INET6) {
af4c2728 1309 flog_err(
e914ccbe 1310 EC_ZEBRA_UNKNOWN_FAMILY,
1d5453d6 1311 "fec_register: Received unknown family type %d",
bf094f69
QY
1312 p.family);
1313 return;
1314 }
1315 STREAM_GETC(s, p.prefixlen);
1316 if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
1317 || (p.family == AF_INET6
1318 && p.prefixlen > IPV6_MAX_BITLEN)) {
9df414fe 1319 zlog_debug(
bf094f69 1320 "%s: Specified prefix hdr->length: %d is to long for %d",
15569c58 1321 __func__, p.prefixlen, p.family);
bf094f69
QY
1322 return;
1323 }
1324 l += 5;
1325 STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
1326 l += PSIZE(p.prefixlen);
57592a53
AD
1327 if (flags & ZEBRA_FEC_REGISTER_LABEL) {
1328 STREAM_GETL(s, label);
1329 l += 4;
1330 } else if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) {
bf094f69
QY
1331 STREAM_GETL(s, label_index);
1332 l += 4;
57592a53
AD
1333 }
1334
1335 zebra_mpls_fec_register(zvrf, &p, label, label_index, client);
bf094f69
QY
1336 }
1337
1338stream_failure:
1339 return;
1340}
1341
1342/* FEC unregister */
1343static void zread_fec_unregister(ZAPI_HANDLER_ARGS)
1344{
1345 struct stream *s;
1346 unsigned short l = 0;
1347 struct prefix p;
1348 uint16_t flags;
1349
1350 s = msg;
1351 zvrf = vrf_info_lookup(VRF_DEFAULT);
1352 if (!zvrf)
8b1766b1 1353 return;
bf094f69
QY
1354
1355 /*
1356 * The minimum amount of data that can be sent for one
1357 * fec unregistration
1358 */
1359 if (hdr->length < ZEBRA_MIN_FEC_LENGTH) {
af4c2728 1360 flog_err(
e914ccbe 1361 EC_ZEBRA_IRDP_LEN_MISMATCH,
bf094f69
QY
1362 "fec_unregister: Received a fec unregister of hdr->length %d, it is of insufficient size to properly decode",
1363 hdr->length);
1364 return;
1365 }
1366
1367 while (l < hdr->length) {
1368 STREAM_GETW(s, flags);
1369 if (flags != 0)
1370 goto stream_failure;
1371
1372 memset(&p, 0, sizeof(p));
1373 STREAM_GETW(s, p.family);
1374 if (p.family != AF_INET && p.family != AF_INET6) {
af4c2728 1375 flog_err(
e914ccbe 1376 EC_ZEBRA_UNKNOWN_FAMILY,
1d5453d6 1377 "fec_unregister: Received unknown family type %d",
bf094f69
QY
1378 p.family);
1379 return;
1380 }
1381 STREAM_GETC(s, p.prefixlen);
1382 if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN)
1383 || (p.family == AF_INET6
1384 && p.prefixlen > IPV6_MAX_BITLEN)) {
9df414fe 1385 zlog_debug(
bf094f69 1386 "%s: Received prefix hdr->length %d which is greater than %d can support",
15569c58 1387 __func__, p.prefixlen, p.family);
bf094f69
QY
1388 return;
1389 }
1390 l += 5;
1391 STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen));
1392 l += PSIZE(p.prefixlen);
1393 zebra_mpls_fec_unregister(zvrf, &p, client);
1394 }
1395
1396stream_failure:
1397 return;
1398}
1399
1400
1401/*
1402 * Register zebra server interface information.
1403 * Send current all interface and address information.
1404 */
1405static void zread_interface_add(ZAPI_HANDLER_ARGS)
1406{
1407 struct vrf *vrf;
1408 struct interface *ifp;
1409
9212d1e1 1410 vrf_id_t vrf_id = zvrf_id(zvrf);
1411 if (vrf_id != VRF_DEFAULT && vrf_id != VRF_UNKNOWN) {
1412 FOR_ALL_INTERFACES (zvrf->vrf, ifp) {
1413 /* Skip pseudo interface. */
1414 if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
1415 continue;
1416
1417 zsend_interface_add(client, ifp);
1418 zsend_interface_link_params(client, ifp);
1419 zsend_interface_addresses(client, ifp);
1420 }
1421 return;
1422 }
1423
bf094f69
QY
1424 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
1425 FOR_ALL_INTERFACES (vrf, ifp) {
1426 /* Skip pseudo interface. */
1427 if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE))
1428 continue;
1429
1430 zsend_interface_add(client, ifp);
27ecbea3 1431 zsend_interface_link_params(client, ifp);
bf094f69
QY
1432 zsend_interface_addresses(client, ifp);
1433 }
1434 }
1435}
1436
1437/* Unregister zebra server interface information. */
1438static void zread_interface_delete(ZAPI_HANDLER_ARGS)
1439{
bf094f69
QY
1440}
1441
c3bd894e
QY
1442/*
1443 * Handle message requesting interface be set up or down.
1444 */
1445static void zread_interface_set_protodown(ZAPI_HANDLER_ARGS)
1446{
1447 ifindex_t ifindex;
1448 struct interface *ifp;
1449 char down;
1450
1451 STREAM_GETL(msg, ifindex);
1452 STREAM_GETC(msg, down);
1453
1454 /* set ifdown */
1455 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
c3bd894e 1456
65dc7dd3
QY
1457 if (ifp) {
1458 zlog_info("Setting interface %s (%u): protodown %s", ifp->name,
1459 ifindex, down ? "on" : "off");
1460 zebra_if_set_protodown(ifp, down);
1461 } else {
1462 zlog_warn(
1463 "Cannot set protodown %s for interface %u; does not exist",
1464 down ? "on" : "off", ifindex);
1465 }
1466
c3bd894e
QY
1467
1468stream_failure:
1469 return;
1470}
1471
786a9bd9 1472bool zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
bf094f69
QY
1473 const unsigned int nexthop_num)
1474{
b3f2b590 1475 if (nexthop_num > zrouter.multipath_num) {
bf094f69 1476 char buff[PREFIX2STR_BUFFER];
8b1766b1 1477
e270f004
SW
1478 if (p)
1479 prefix2str(p, buff, sizeof(buff));
1480
9df414fe 1481 flog_warn(
e914ccbe 1482 EC_ZEBRA_MORE_NH_THAN_MULTIPATH,
bf094f69 1483 "%s: Prefix %s has %d nexthops, but we can only use the first %d",
e270f004
SW
1484 caller, (p ? buff : "(NULL)"), nexthop_num,
1485 zrouter.multipath_num);
786a9bd9 1486 return true;
bf094f69 1487 }
786a9bd9
DS
1488
1489 return false;
bf094f69
QY
1490}
1491
62e46303
MS
1492/*
1493 * Create a new nexthop based on a zapi nexthop.
1494 */
2f35a820
DS
1495static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh,
1496 uint32_t flags, struct prefix *p,
1497 uint16_t backup_nexthop_num)
62e46303
MS
1498{
1499 struct nexthop *nexthop = NULL;
1500 struct ipaddr vtep_ip;
1501 struct interface *ifp;
474aebd9 1502 int i;
62e46303
MS
1503 char nhbuf[INET6_ADDRSTRLEN] = "";
1504
62e46303
MS
1505 switch (api_nh->type) {
1506 case NEXTHOP_TYPE_IFINDEX:
1507 nexthop = nexthop_from_ifindex(api_nh->ifindex, api_nh->vrf_id);
1508 break;
1509 case NEXTHOP_TYPE_IPV4:
1510 if (IS_ZEBRA_DEBUG_RECV) {
1511 inet_ntop(AF_INET, &api_nh->gate.ipv4, nhbuf,
1512 sizeof(nhbuf));
1513 zlog_debug("%s: nh=%s, vrf_id=%d", __func__,
1514 nhbuf, api_nh->vrf_id);
1515 }
1516 nexthop = nexthop_from_ipv4(&api_nh->gate.ipv4, NULL,
1517 api_nh->vrf_id);
1518 break;
1519 case NEXTHOP_TYPE_IPV4_IFINDEX:
1520 if (IS_ZEBRA_DEBUG_RECV) {
1521 inet_ntop(AF_INET, &api_nh->gate.ipv4, nhbuf,
1522 sizeof(nhbuf));
1523 zlog_debug("%s: nh=%s, vrf_id=%d, ifindex=%d",
1524 __func__, nhbuf, api_nh->vrf_id,
1525 api_nh->ifindex);
1526 }
1527
1528 nexthop = nexthop_from_ipv4_ifindex(
1529 &api_nh->gate.ipv4, NULL, api_nh->ifindex,
1530 api_nh->vrf_id);
1531
62e46303
MS
1532 /* Special handling for IPv4 routes sourced from EVPN:
1533 * the nexthop and associated MAC need to be installed.
1534 */
2f35a820 1535 if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) {
62e46303
MS
1536 memset(&vtep_ip, 0, sizeof(struct ipaddr));
1537 vtep_ip.ipa_type = IPADDR_V4;
1538 memcpy(&(vtep_ip.ipaddr_v4), &(api_nh->gate.ipv4),
1539 sizeof(struct in_addr));
1540 zebra_vxlan_evpn_vrf_route_add(
ff9aca4f 1541 api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p);
62e46303
MS
1542 }
1543 break;
1544 case NEXTHOP_TYPE_IPV6:
1545 if (IS_ZEBRA_DEBUG_RECV) {
1546 inet_ntop(AF_INET6, &api_nh->gate.ipv6, nhbuf,
1547 sizeof(nhbuf));
1548 zlog_debug("%s: nh=%s, vrf_id=%d", __func__,
1549 nhbuf, api_nh->vrf_id);
1550 }
1551 nexthop = nexthop_from_ipv6(&api_nh->gate.ipv6, api_nh->vrf_id);
1552 break;
1553 case NEXTHOP_TYPE_IPV6_IFINDEX:
1554 if (IS_ZEBRA_DEBUG_RECV) {
1555 inet_ntop(AF_INET6, &api_nh->gate.ipv6, nhbuf,
1556 sizeof(nhbuf));
1557 zlog_debug("%s: nh=%s, vrf_id=%d, ifindex=%d",
1558 __func__, nhbuf, api_nh->vrf_id,
1559 api_nh->ifindex);
1560 }
1561 nexthop = nexthop_from_ipv6_ifindex(&api_nh->gate.ipv6,
1562 api_nh->ifindex,
1563 api_nh->vrf_id);
1564
1565 /* Special handling for IPv6 routes sourced from EVPN:
1566 * the nexthop and associated MAC need to be installed.
1567 */
2f35a820 1568 if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) {
62e46303
MS
1569 memset(&vtep_ip, 0, sizeof(struct ipaddr));
1570 vtep_ip.ipa_type = IPADDR_V6;
1571 memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6),
1572 sizeof(struct in6_addr));
1573 zebra_vxlan_evpn_vrf_route_add(
ff9aca4f 1574 api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p);
62e46303
MS
1575 }
1576 break;
1577 case NEXTHOP_TYPE_BLACKHOLE:
1578 if (IS_ZEBRA_DEBUG_RECV)
1579 zlog_debug("%s: nh blackhole %d",
1580 __func__, api_nh->bh_type);
1581
1582 nexthop = nexthop_from_blackhole(api_nh->bh_type);
1583 break;
1584 }
1585
1586 /* Return early if we couldn't process the zapi nexthop */
1587 if (nexthop == NULL) {
1588 goto done;
1589 }
1590
12b4d77b 1591 /* Mark nexthop as onlink either if client has explicitly told us
1592 * to or if the nexthop is on an 'unnumbered' interface.
1593 */
62e46303
MS
1594 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK))
1595 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
12b4d77b 1596 else if (api_nh->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1597 ifp = if_lookup_by_index(api_nh->ifindex, api_nh->vrf_id);
1598 if (ifp && connected_is_unnumbered(ifp))
1599 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
1600 }
62e46303
MS
1601
1602 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
1603 nexthop->weight = api_nh->weight;
1604
1d48702e 1605 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
474aebd9
MS
1606 /* Validate count */
1607 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) {
1d48702e 1608 if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
474aebd9
MS
1609 zlog_debug("%s: invalid backup nh count %d",
1610 __func__, api_nh->backup_num);
1611 nexthop_free(nexthop);
1612 nexthop = NULL;
1613 goto done;
1614 }
1615
1616 /* Copy backup info */
1617 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
1618 nexthop->backup_num = api_nh->backup_num;
1619
1620 for (i = 0; i < api_nh->backup_num; i++) {
1621 /* Validate backup index */
2f35a820 1622 if (api_nh->backup_idx[i] < backup_nexthop_num) {
474aebd9
MS
1623 nexthop->backup_idx[i] = api_nh->backup_idx[i];
1624 } else {
1625 if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
1626 zlog_debug("%s: invalid backup nh idx %d",
1627 __func__,
1628 api_nh->backup_idx[i]);
1629 nexthop_free(nexthop);
1630 nexthop = NULL;
1631 goto done;
1632 }
1d48702e
MS
1633 }
1634 }
474aebd9 1635
62e46303
MS
1636done:
1637 return nexthop;
1638}
1639
2f35a820
DS
1640static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
1641 struct zapi_nexthop *nhops, uint32_t flags,
1642 uint32_t message, uint16_t nexthop_num,
1643 uint16_t backup_nh_num,
f70da2a3
DS
1644 struct nexthop_group **png,
1645 struct nhg_backup_info **pbnhg)
bf094f69 1646{
0eb97b86 1647 struct nexthop_group *ng = NULL;
1d48702e 1648 struct nhg_backup_info *bnhg = NULL;
2f35a820 1649 uint16_t i;
f70da2a3 1650 struct nexthop *last_nh = NULL;
bf094f69 1651
f70da2a3 1652 assert(!(png && pbnhg));
c2c02b76 1653
2f35a820 1654 if (png)
66c28560 1655 ng = nexthop_group_new();
bf094f69 1656
2f35a820 1657 if (pbnhg && backup_nh_num > 0) {
f70da2a3 1658 if (IS_ZEBRA_DEBUG_RECV)
2f35a820
DS
1659 zlog_debug("%s: adding %d backup nexthops", __func__,
1660 backup_nh_num);
7fcb24bb 1661
66c28560 1662 bnhg = zebra_nhg_backup_alloc();
62e46303
MS
1663 }
1664
bf094f69
QY
1665 /*
1666 * TBD should _all_ of the nexthop add operations use
1667 * api_nh->vrf_id instead of re->vrf_id ? I only changed
1668 * for cases NEXTHOP_TYPE_IPV4 and NEXTHOP_TYPE_IPV6.
1669 */
f70da2a3
DS
1670 for (i = 0; i < nexthop_num; i++) {
1671 struct nexthop *nexthop;
1672 enum lsp_types_t label_type;
1673 char nhbuf[NEXTHOP_STRLEN];
1674 char labelbuf[MPLS_LABEL_STRLEN];
1675 struct zapi_nexthop *api_nh = &nhops[i];
7fcb24bb 1676
62e46303 1677 /* Convert zapi nexthop */
2f35a820 1678 nexthop = nexthop_from_zapi(api_nh, flags, p, backup_nh_num);
62e46303
MS
1679 if (!nexthop) {
1680 flog_warn(
1681 EC_ZEBRA_NEXTHOP_CREATION_FAILED,
f70da2a3
DS
1682 "%s: Nexthops Specified: %u(%u) but we failed to properly create one",
1683 __func__, nexthop_num, i);
1684 if (ng)
1685 nexthop_group_delete(&ng);
1686 if (bnhg)
1687 zebra_nhg_backup_free(&bnhg);
1688 return false;
62e46303 1689 }
7fcb24bb 1690
ff9aca4f
SW
1691 if (bnhg
1692 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
f70da2a3
DS
1693 if (IS_ZEBRA_DEBUG_RECV) {
1694 nexthop2str(nexthop, nhbuf, sizeof(nhbuf));
1695 zlog_debug("%s: backup nh %s with BACKUP flag!",
1696 __func__, nhbuf);
1697 }
1698 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
1699 nexthop->backup_num = 0;
1700 }
1701
2f35a820 1702 if (CHECK_FLAG(message, ZAPI_MESSAGE_SRTE)) {
31f937fb
SM
1703 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE);
1704 nexthop->srte_color = api_nh->srte_color;
1705 }
1706
62e46303
MS
1707 /* MPLS labels for BGP-LU or Segment Routing */
1708 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
1709 && api_nh->type != NEXTHOP_TYPE_IFINDEX
1710 && api_nh->type != NEXTHOP_TYPE_BLACKHOLE
1711 && api_nh->label_num > 0) {
7fcb24bb 1712
62e46303 1713 label_type = lsp_type_from_re_type(client->proto);
62e46303
MS
1714 nexthop_add_labels(nexthop, label_type,
1715 api_nh->label_num,
1716 &api_nh->labels[0]);
bf094f69 1717 }
bf094f69 1718
1d48702e
MS
1719 if (IS_ZEBRA_DEBUG_RECV) {
1720 labelbuf[0] = '\0';
1721 nhbuf[0] = '\0';
1722
1723 nexthop2str(nexthop, nhbuf, sizeof(nhbuf));
1724
1725 if (nexthop->nh_label &&
1726 nexthop->nh_label->num_labels > 0) {
1727 mpls_label2str(nexthop->nh_label->num_labels,
1728 nexthop->nh_label->label,
1729 labelbuf, sizeof(labelbuf),
1730 false);
1731 }
1732
1733 zlog_debug("%s: nh=%s, vrf_id=%d %s",
1734 __func__, nhbuf, api_nh->vrf_id, labelbuf);
1735 }
1736
66c28560 1737 if (ng) {
f70da2a3 1738 /* Add new nexthop to temporary list. This list is
ff9aca4f
SW
1739 * canonicalized - sorted - so that it can be hashed
1740 * later in route processing. We expect that the sender
1741 * has sent the list sorted, and the zapi client api
1742 * attempts to enforce that, so this should be
1743 * inexpensive - but it is necessary to support shared
1744 * nexthop-groups.
f70da2a3
DS
1745 */
1746 nexthop_group_add_sorted(ng, nexthop);
1747 }
1748 if (bnhg) {
ff9aca4f
SW
1749 /* Note that the order of the backup nexthops is
1750 * significant, so we don't sort this list as we do the
1751 * primary nexthops, we just append.
f70da2a3
DS
1752 */
1753 if (last_nh)
1754 NEXTHOP_APPEND(last_nh, nexthop);
1755 else
1756 bnhg->nhe->nhg.nexthop = nexthop;
1757
1758 last_nh = nexthop;
1759 }
62e46303
MS
1760 }
1761
66c28560
SW
1762
1763 /* succesfully read, set caller pointers now */
1764 if (png)
1765 *png = ng;
1766
1767 if (pbnhg)
1768 *pbnhg = bnhg;
1769
f70da2a3
DS
1770 return true;
1771}
62e46303 1772
5898ce6f 1773static int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
21735352
SW
1774{
1775 uint16_t i;
1776 struct zapi_nexthop *znh;
1777
1778 STREAM_GETW(s, api_nhg->proto);
1779 STREAM_GETL(s, api_nhg->id);
1780
1781 if (cmd == ZEBRA_NHG_DEL)
1782 goto done;
1783
1784 /* Nexthops */
1785 STREAM_GETW(s, api_nhg->nexthop_num);
1786
1787 if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->nexthop_num))
1788 return -1;
1789
1790 if (api_nhg->nexthop_num <= 0) {
1791 flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
1792 "%s: No nexthops sent", __func__);
1793 return -1;
1794 }
1795
1796 for (i = 0; i < api_nhg->nexthop_num; i++) {
1797 znh = &((api_nhg->nexthops)[i]);
1798
1799 if (zapi_nexthop_decode(s, znh, 0, 0) != 0) {
1800 flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
1801 "%s: Nexthop creation failed", __func__);
1802 return -1;
1803 }
1804 }
1805
1806 /* Backup Nexthops */
1807 STREAM_GETW(s, api_nhg->backup_nexthop_num);
1808
1809 if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->backup_nexthop_num))
1810 return -1;
1811
1812 for (i = 0; i < api_nhg->backup_nexthop_num; i++) {
1813 znh = &((api_nhg->backup_nexthops)[i]);
1814
1815 if (zapi_nexthop_decode(s, znh, 0, 0) != 0) {
1816 flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
1817 "%s: Backup Nexthop creation failed",
1818 __func__);
1819 return -1;
1820 }
1821 }
1822
1823done:
1824 return 0;
1825
1826stream_failure:
1827 flog_warn(
1828 EC_ZEBRA_NEXTHOP_CREATION_FAILED,
1829 "%s: Nexthop Group decode failed with some sort of stream read failure",
1830 __func__);
1831 return -1;
1832}
1833
2f35a820
DS
1834static void zread_nhg_del(ZAPI_HANDLER_ARGS)
1835{
21735352
SW
1836 struct stream *s;
1837 struct zapi_nhg api_nhg = {};
0885b1e3 1838 struct nhg_hash_entry *nhe;
2f35a820 1839
21735352
SW
1840 s = msg;
1841 if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) {
1842 if (IS_ZEBRA_DEBUG_RECV)
1843 zlog_debug("%s: Unable to decode zapi_nhg sent",
1844 __func__);
1845 return;
1846 }
2f35a820
DS
1847
1848 /*
1849 * Delete the received nhg id
2f35a820 1850 */
21735352 1851 nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto);
0885b1e3
SW
1852
1853 if (nhe) {
6fae63d2 1854 zebra_nhg_decrement_ref(nhe);
ee94437e
MS
1855 zsend_nhg_notify(api_nhg.proto, client->instance,
1856 client->session_id, api_nhg.id,
1857 ZAPI_NHG_REMOVED);
0885b1e3 1858 } else
ee94437e
MS
1859 zsend_nhg_notify(api_nhg.proto, client->instance,
1860 client->session_id, api_nhg.id,
1861 ZAPI_NHG_REMOVE_FAIL);
2f35a820
DS
1862}
1863
8b2d3a0f 1864static void zread_nhg_add(ZAPI_HANDLER_ARGS)
2f35a820
DS
1865{
1866 struct stream *s;
21735352 1867 struct zapi_nhg api_nhg = {};
2f35a820 1868 struct nexthop_group *nhg = NULL;
21735352 1869 struct nhg_backup_info *bnhg = NULL;
0885b1e3 1870 struct nhg_hash_entry *nhe;
2f35a820 1871
2f35a820 1872 s = msg;
21735352
SW
1873 if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) {
1874 if (IS_ZEBRA_DEBUG_RECV)
1875 zlog_debug("%s: Unable to decode zapi_nhg sent",
1876 __func__);
68671c74
SW
1877 return;
1878 }
1879
21735352
SW
1880 if ((!zapi_read_nexthops(client, NULL, api_nhg.nexthops, 0, 0,
1881 api_nhg.nexthop_num,
1882 api_nhg.backup_nexthop_num, &nhg, NULL))
1883 || (!zapi_read_nexthops(client, NULL, api_nhg.backup_nexthops, 0, 0,
1884 api_nhg.backup_nexthop_num,
1885 api_nhg.backup_nexthop_num, NULL, &bnhg))) {
2f35a820 1886
2f35a820 1887 flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
ff9aca4f 1888 "%s: Nexthop Group Creation failed", __func__);
2f35a820
DS
1889 return;
1890 }
0885b1e3 1891
2f35a820 1892 /*
8b2d3a0f 1893 * Create the nhg
2f35a820 1894 */
ee94437e
MS
1895 nhe = zebra_nhg_proto_add(api_nhg.id, api_nhg.proto, client->instance,
1896 client->session_id, nhg, 0);
0885b1e3
SW
1897
1898 nexthop_group_delete(&nhg);
21735352 1899 zebra_nhg_backup_free(&bnhg);
0885b1e3
SW
1900
1901 /*
1902 * TODO:
1903 * Assume fully resolved for now and install.
1904 *
1905 * Resolution is going to need some more work.
1906 */
ee94437e
MS
1907
1908 /* If there's a failure, notify sender immediately */
1909 if (nhe == NULL)
1910 zsend_nhg_notify(api_nhg.proto, client->instance,
1911 client->session_id, api_nhg.id,
1912 ZAPI_NHG_FAIL_INSTALL);
2f35a820
DS
1913}
1914
f70da2a3
DS
1915static void zread_route_add(ZAPI_HANDLER_ARGS)
1916{
1917 struct stream *s;
1918 struct zapi_route api;
1919 afi_t afi;
1920 struct prefix_ipv6 *src_p = NULL;
1921 struct route_entry *re;
1922 struct nexthop_group *ng = NULL;
1923 struct nhg_backup_info *bnhg = NULL;
1924 int ret;
1925 vrf_id_t vrf_id;
1926 struct nhg_hash_entry nhe;
0eb97b86 1927
f70da2a3
DS
1928 s = msg;
1929 if (zapi_route_decode(s, &api) < 0) {
1930 if (IS_ZEBRA_DEBUG_RECV)
1931 zlog_debug("%s: Unable to decode zapi_route sent",
1932 __func__);
1933 return;
1934 }
1d48702e 1935
f70da2a3 1936 vrf_id = zvrf_id(zvrf);
31f937fb 1937
2dbe669b
DA
1938 if (IS_ZEBRA_DEBUG_RECV)
1939 zlog_debug("%s: p=(%u:%u)%pFX, msg flags=0x%x, flags=0x%x",
1940 __func__, vrf_id, api.tableid, &api.prefix,
f70da2a3 1941 (int)api.message, api.flags);
0eb97b86 1942
f70da2a3
DS
1943 /* Allocate new route. */
1944 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
1945 re->type = api.type;
1946 re->instance = api.instance;
1947 re->flags = api.flags;
1948 re->uptime = monotime(NULL);
1949 re->vrf_id = vrf_id;
1d48702e 1950
f70da2a3
DS
1951 if (api.tableid)
1952 re->table = api.tableid;
1953 else
1954 re->table = zvrf->table_id;
1d48702e 1955
27141ea9
DS
1956 if (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NHG)
1957 && (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)
1958 || api.nexthop_num == 0)) {
ff9aca4f
SW
1959 flog_warn(
1960 EC_ZEBRA_RX_ROUTE_NO_NEXTHOPS,
1961 "%s: received a route without nexthops for prefix %pFX from client %s",
1962 __func__, &api.prefix,
1963 zebra_route_string(client->proto));
1d48702e 1964
f70da2a3
DS
1965 XFREE(MTYPE_RE, re);
1966 return;
1967 }
1d48702e 1968
f70da2a3 1969 /* Report misuse of the backup flag */
ff9aca4f
SW
1970 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)
1971 && api.backup_nexthop_num == 0) {
f70da2a3 1972 if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
ff9aca4f
SW
1973 zlog_debug(
1974 "%s: client %s: BACKUP flag set but no backup nexthops, prefix %pFX",
1975 __func__, zebra_route_string(client->proto),
1976 &api.prefix);
f70da2a3 1977 }
62e46303 1978
50db3f2f
SW
1979 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NHG))
1980 re->nhe_id = api.nhgid;
1981
1982 if (!re->nhe_id
2b5ecd4c
SW
1983 && (!zapi_read_nexthops(client, &api.prefix, api.nexthops,
1984 api.flags, api.message, api.nexthop_num,
1985 api.backup_nexthop_num, &ng, NULL)
1986 || !zapi_read_nexthops(client, &api.prefix, api.backup_nexthops,
1987 api.flags, api.message,
1988 api.backup_nexthop_num,
1989 api.backup_nexthop_num, NULL, &bnhg))) {
21735352
SW
1990
1991 nexthop_group_delete(&ng);
1992 zebra_nhg_backup_free(&bnhg);
f70da2a3
DS
1993 XFREE(MTYPE_RE, re);
1994 return;
7fcb24bb
RW
1995 }
1996
bf094f69
QY
1997 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
1998 re->distance = api.distance;
1999 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
2000 re->metric = api.metric;
2001 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
2002 re->tag = api.tag;
2003 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU))
2004 re->mtu = api.mtu;
2005
a29a6001
DS
2006 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_OPAQUE)) {
2007 re->opaque = XMALLOC(MTYPE_OPAQUE,
2008 sizeof(struct opaque) + api.opaque.length);
2009 re->opaque->length = api.opaque.length;
2010 memcpy(re->opaque->data, api.opaque.data, re->opaque->length);
2011 }
2012
bf094f69
QY
2013 afi = family2afi(api.prefix.family);
2014 if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
e914ccbe 2015 flog_warn(EC_ZEBRA_RX_SRCDEST_WRONG_AFI,
9df414fe 2016 "%s: Received SRC Prefix but afi is not v6",
15569c58 2017 __func__);
0eb97b86 2018 nexthop_group_delete(&ng);
1d48702e 2019 zebra_nhg_backup_free(&bnhg);
bf094f69
QY
2020 XFREE(MTYPE_RE, re);
2021 return;
2022 }
2023 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
2024 src_p = &api.src_prefix;
2025
5e7939a5
DS
2026 if (api.safi != SAFI_UNICAST && api.safi != SAFI_MULTICAST) {
2027 flog_warn(EC_LIB_ZAPI_MISSMATCH,
2028 "%s: Received safi: %d but we can only accept UNICAST or MULTICAST",
2029 __func__, api.safi);
2030 nexthop_group_delete(&ng);
1d48702e 2031 zebra_nhg_backup_free(&bnhg);
5e7939a5
DS
2032 XFREE(MTYPE_RE, re);
2033 return;
2034 }
1d48702e 2035
50db3f2f
SW
2036 /*
2037 * If we have an ID, this proto owns the NHG it sent along with the
2038 * route, so we just send the ID into rib code with it.
2039 *
2040 * Havent figured out how to handle backup NHs with this yet, so lets
2041 * keep that separate.
2042 * Include backup info with the route. We use a temporary nhe here;
377e29f7
MS
2043 * if this is a new/unknown nhe, a new copy will be allocated
2044 * and stored.
2045 */
50db3f2f
SW
2046 if (!re->nhe_id) {
2047 zebra_nhe_init(&nhe, afi, ng->nexthop);
2048 nhe.nhg.nexthop = ng->nexthop;
2049 nhe.backup_info = bnhg;
2050 }
1d48702e
MS
2051 ret = rib_add_multipath_nhe(afi, api.safi, &api.prefix, src_p,
2052 re, &nhe);
bf094f69 2053
377e29f7
MS
2054 /* At this point, these allocations are not needed: 're' has been
2055 * retained or freed, and if 're' still exists, it is using
2056 * a reference to a shared group object.
2057 */
2058 nexthop_group_delete(&ng);
2059 if (bnhg)
2060 zebra_nhg_backup_free(&bnhg);
2061
bf094f69
QY
2062 /* Stats */
2063 switch (api.prefix.family) {
2064 case AF_INET:
2065 if (ret > 0)
2066 client->v4_route_add_cnt++;
2067 else if (ret < 0)
2068 client->v4_route_upd8_cnt++;
2069 break;
2070 case AF_INET6:
2071 if (ret > 0)
2072 client->v6_route_add_cnt++;
2073 else if (ret < 0)
2074 client->v6_route_upd8_cnt++;
2075 break;
2076 }
2077}
2078
2079static void zread_route_del(ZAPI_HANDLER_ARGS)
2080{
2081 struct stream *s;
2082 struct zapi_route api;
2083 afi_t afi;
2084 struct prefix_ipv6 *src_p = NULL;
2085 uint32_t table_id;
2086
2087 s = msg;
2088 if (zapi_route_decode(s, &api) < 0)
2089 return;
2090
2091 afi = family2afi(api.prefix.family);
2092 if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
e914ccbe 2093 flog_warn(EC_ZEBRA_RX_SRCDEST_WRONG_AFI,
9df414fe 2094 "%s: Received a src prefix while afi is not v6",
15569c58 2095 __func__);
bf094f69
QY
2096 return;
2097 }
2098 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
2099 src_p = &api.src_prefix;
2100
60ca3cc2 2101 if (api.tableid)
bf094f69
QY
2102 table_id = api.tableid;
2103 else
2104 table_id = zvrf->table_id;
2105
2dbe669b
DA
2106 if (IS_ZEBRA_DEBUG_RECV)
2107 zlog_debug("%s: p=(%u:%u)%pFX, msg flags=0x%x, flags=0x%x",
2108 __func__, zvrf_id(zvrf), table_id, &api.prefix,
c2c02b76 2109 (int)api.message, api.flags);
c2c02b76 2110
bf094f69 2111 rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
bc541126 2112 api.flags, &api.prefix, src_p, NULL, 0, table_id, api.metric,
3ceae22b 2113 api.distance, false);
bf094f69
QY
2114
2115 /* Stats */
2116 switch (api.prefix.family) {
2117 case AF_INET:
2118 client->v4_route_del_cnt++;
2119 break;
2120 case AF_INET6:
2121 client->v6_route_del_cnt++;
2122 break;
2123 }
2124}
2125
bf094f69
QY
2126/* MRIB Nexthop lookup for IPv4. */
2127static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
2128{
2129 struct in_addr addr;
2130 struct route_entry *re;
2131
2132 STREAM_GET(&addr.s_addr, msg, IPV4_MAX_BYTELEN);
2133 re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL);
2134 zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf);
2135
2136stream_failure:
2137 return;
2138}
2139
bf094f69
QY
2140/* Register zebra server router-id information. Send current router-id */
2141static void zread_router_id_add(ZAPI_HANDLER_ARGS)
2142{
98a3fb0a
SM
2143 afi_t afi;
2144
bf094f69
QY
2145 struct prefix p;
2146
98a3fb0a
SM
2147 STREAM_GETW(msg, afi);
2148
2149 if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
2150 zlog_warn(
2151 "Invalid AFI %u while registering for router ID notifications",
2152 afi);
2153 goto stream_failure;
2154 }
2155
bf094f69 2156 /* Router-id information is needed. */
98a3fb0a 2157 vrf_bitmap_set(client->ridinfo[afi], zvrf_id(zvrf));
bf094f69 2158
98a3fb0a 2159 router_id_get(afi, &p, zvrf);
bf094f69 2160
98a3fb0a
SM
2161 zsend_router_id_update(client, afi, &p, zvrf_id(zvrf));
2162
2163stream_failure:
2164 return;
bf094f69
QY
2165}
2166
2167/* Unregister zebra server router-id information. */
2168static void zread_router_id_delete(ZAPI_HANDLER_ARGS)
2169{
98a3fb0a
SM
2170 afi_t afi;
2171
2172 STREAM_GETW(msg, afi);
2173
2174 if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
2175 zlog_warn(
2176 "Invalid AFI %u while unregistering from router ID notifications",
2177 afi);
2178 goto stream_failure;
2179 }
2180
2181 vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
2182
2183stream_failure:
2184 return;
bf094f69
QY
2185}
2186
2187static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
2188{
2189 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2190
2191 zclient_create_header(s, ZEBRA_CAPABILITIES, zvrf->vrf->vrf_id);
bb6b7f79 2192 stream_putl(s, vrf_get_backend());
bf094f69 2193 stream_putc(s, mpls_enabled);
b3f2b590 2194 stream_putl(s, zrouter.multipath_num);
02c0866d 2195 stream_putc(s, zebra_mlag_get_role());
bf094f69
QY
2196
2197 stream_putw_at(s, 0, stream_get_endp(s));
21ccc0cf 2198 zserv_send_message(client, s);
bf094f69
QY
2199}
2200
b120fe3b
DS
2201void zsend_capabilities_all_clients(void)
2202{
2203 struct listnode *node, *nnode;
2204 struct zebra_vrf *zvrf;
2205 struct zserv *client;
2206
2207 zvrf = vrf_info_lookup(VRF_DEFAULT);
2208 for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
17da84a4
KS
2209 /* Do not send unsolicited messages to synchronous clients. */
2210 if (client->synchronous)
2211 continue;
2212
b120fe3b
DS
2213 zsend_capabilities(client, zvrf);
2214 }
2215}
2216
bf094f69
QY
2217/* Tie up route-type and client->sock */
2218static void zread_hello(ZAPI_HANDLER_ARGS)
2219{
2220 /* type of protocol (lib/zebra.h) */
2221 uint8_t proto;
2222 unsigned short instance;
2223 uint8_t notify;
17da84a4 2224 uint8_t synchronous;
4e0b5b31 2225 uint32_t session_id;
bf094f69
QY
2226
2227 STREAM_GETC(msg, proto);
2228 STREAM_GETW(msg, instance);
4e0b5b31 2229 STREAM_GETL(msg, session_id);
bf094f69 2230 STREAM_GETC(msg, notify);
17da84a4 2231 STREAM_GETC(msg, synchronous);
bf094f69
QY
2232 if (notify)
2233 client->notify_owner = true;
2234
17da84a4
KS
2235 if (synchronous)
2236 client->synchronous = true;
2237
bf094f69 2238 /* accept only dynamic routing protocols */
f23cbcda 2239 if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_CONNECT)) {
bf094f69
QY
2240 zlog_notice(
2241 "client %d says hello and bids fair to announce only %s routes vrf=%u",
2242 client->sock, zebra_route_string(proto),
2243 zvrf->vrf->vrf_id);
2244 if (instance)
2245 zlog_notice("client protocol instance %d", instance);
2246
2247 client->proto = proto;
2248 client->instance = instance;
4e0b5b31 2249 client->session_id = session_id;
6f4aee61
S
2250
2251 /* Graceful restart processing for client connect */
2252 zebra_gr_client_reconnect(client);
bf094f69
QY
2253 }
2254
17da84a4
KS
2255 if (!client->synchronous) {
2256 zsend_capabilities(client, zvrf);
2257 zebra_vrf_update_all(client);
2258 }
bf094f69
QY
2259stream_failure:
2260 return;
2261}
2262
2263/* Unregister all information in a VRF. */
2264static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
2265{
2266 int i;
2267 afi_t afi;
2268
49db7a7b 2269 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
bf094f69
QY
2270 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2271 vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
49db7a7b 2272 vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
98a3fb0a 2273 vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
49db7a7b 2274 }
bf094f69
QY
2275}
2276
ff8d3c2d
MS
2277/*
2278 * Validate incoming zapi mpls lsp / labels message
2279 */
2280static int zapi_labels_validate(const struct zapi_labels *zl)
2281{
2282 int ret = -1;
2283 int i, j, idx;
2284 uint32_t bits[8];
2285 uint32_t ival;
2286 const struct zapi_nexthop *znh;
2287
2288 /* Validate backup info: no duplicates for a single primary */
2289 if (zl->backup_nexthop_num == 0) {
2290 ret = 0;
2291 goto done;
2292 }
2293
2294 for (j = 0; j < zl->nexthop_num; j++) {
2295 znh = &zl->nexthops[j];
2296
2297 memset(bits, 0, sizeof(bits));
2298
2299 for (i = 0; i < znh->backup_num; i++) {
2300 idx = znh->backup_idx[i] / 32;
2301
2302 ival = 1 << znh->backup_idx[i] % 32;
2303
2304 /* Check whether value is already used */
2305 if (ival & bits[idx]) {
2306 /* Fail */
2307
2308 if (IS_ZEBRA_DEBUG_RECV)
2309 zlog_debug("%s: invalid zapi mpls message: duplicate backup nexthop index %d",
2310 __func__,
2311 znh->backup_idx[i]);
2312 goto done;
2313 }
2314
2315 /* Mark index value */
2316 bits[idx] |= ival;
2317 }
2318 }
2319
2320 ret = 0;
2321
2322done:
2323
2324 return ret;
2325}
2326
ea6b290b
RW
2327/*
2328 * Handle request to create an MPLS LSP.
2329 *
2330 * A single message can fully specify an LSP with multiple nexthops.
2331 *
2332 * When the optional ZAPI_LABELS_FTN flag is set, the specified FEC (route) is
2333 * updated to use the received label(s).
2334 */
2335static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
bf094f69
QY
2336{
2337 struct stream *s;
bad6b0e7 2338 struct zapi_labels zl;
f2e7f4eb 2339 int ret;
bf094f69
QY
2340
2341 /* Get input stream. */
2342 s = msg;
bad6b0e7
RW
2343 if (zapi_labels_decode(s, &zl) < 0) {
2344 if (IS_ZEBRA_DEBUG_RECV)
2345 zlog_debug("%s: Unable to decode zapi_labels sent",
15569c58 2346 __func__);
bf094f69
QY
2347 return;
2348 }
bf094f69 2349
bf094f69
QY
2350 if (!mpls_enabled)
2351 return;
2352
ff8d3c2d
MS
2353 /* Validate; will debug on failure */
2354 if (zapi_labels_validate(&zl) < 0)
2355 return;
2356
f2e7f4eb
MS
2357 ret = mpls_zapi_labels_process(true, zvrf, &zl);
2358 if (ret < 0) {
2359 if (IS_ZEBRA_DEBUG_RECV)
2360 zlog_debug("%s: Error processing zapi request",
2361 __func__);
ea6b290b
RW
2362 }
2363}
2364
2365/*
2366 * Handle request to delete an MPLS LSP.
2367 *
2368 * An LSP is identified by its type and local label. When the received message
2369 * doesn't contain any nexthop, the whole LSP is deleted. Otherwise, only the
2370 * listed LSP nexthops (aka NHLFEs) are deleted.
2371 *
2372 * When the optional ZAPI_LABELS_FTN flag is set, the labels of the specified
2373 * FEC (route) nexthops are deleted.
2374 */
2375static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
2376{
2377 struct stream *s;
2378 struct zapi_labels zl;
f2e7f4eb 2379 int ret;
ea6b290b
RW
2380
2381 /* Get input stream. */
2382 s = msg;
2383 if (zapi_labels_decode(s, &zl) < 0) {
2384 if (IS_ZEBRA_DEBUG_RECV)
2385 zlog_debug("%s: Unable to decode zapi_labels sent",
15569c58 2386 __func__);
ea6b290b
RW
2387 return;
2388 }
2389
2390 if (!mpls_enabled)
2391 return;
2392
2393 if (zl.nexthop_num > 0) {
f2e7f4eb
MS
2394 ret = mpls_zapi_labels_process(false /*delete*/, zvrf, &zl);
2395 if (ret < 0) {
2396 if (IS_ZEBRA_DEBUG_RECV)
2397 zlog_debug("%s: Error processing zapi request",
2398 __func__);
ea6b290b
RW
2399 }
2400 } else {
2401 mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
2402
b3c49d0e 2403 if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
ea6b290b
RW
2404 mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
2405 zl.route.type, zl.route.instance);
2406 }
2407}
2408
2409/*
2410 * Handle request to add an MPLS LSP or change an existing one.
2411 *
2412 * A single message can fully specify an LSP with multiple nexthops.
2413 *
2414 * When the optional ZAPI_LABELS_FTN flag is set, the specified FEC (route) is
2415 * updated to use the received label(s).
2416 *
2417 * NOTE: zebra will use route replace semantics (make-before-break) to update
2418 * the LSP in the forwarding plane if that's supported by the underlying
2419 * platform.
2420 */
2421static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
2422{
2423 struct stream *s;
2424 struct zapi_labels zl;
2425
2426 /* Get input stream. */
2427 s = msg;
2428 if (zapi_labels_decode(s, &zl) < 0) {
2429 if (IS_ZEBRA_DEBUG_RECV)
2430 zlog_debug("%s: Unable to decode zapi_labels sent",
15569c58 2431 __func__);
ea6b290b
RW
2432 return;
2433 }
2434
2435 if (!mpls_enabled)
2436 return;
2437
ff8d3c2d
MS
2438 /* Validate; will debug on failure */
2439 if (zapi_labels_validate(&zl) < 0)
2440 return;
2441
f2e7f4eb
MS
2442 /* This removes everything, then re-adds from the client's
2443 * zapi message. Since the LSP will be processed later, on this
2444 * this same pthread, all of the changes will 'appear' at once.
2445 */
ea6b290b
RW
2446 mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
2447 if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
2448 mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
2449 zl.route.type, zl.route.instance);
2450
f2e7f4eb 2451 mpls_zapi_labels_process(true, zvrf, &zl);
bf094f69
QY
2452}
2453
31f937fb
SM
2454static void zread_sr_policy_set(ZAPI_HANDLER_ARGS)
2455{
2456 struct stream *s;
2457 struct zapi_sr_policy zp;
2458 struct zapi_srte_tunnel *zt;
2459 struct zebra_sr_policy *policy;
2460
2461 /* Get input stream. */
2462 s = msg;
2463 if (zapi_sr_policy_decode(s, &zp) < 0) {
2464 if (IS_ZEBRA_DEBUG_RECV)
2465 zlog_debug("%s: Unable to decode zapi_sr_policy sent",
2466 __PRETTY_FUNCTION__);
2467 return;
2468 }
2469 zt = &zp.segment_list;
2470 if (zt->label_num < 1) {
2471 if (IS_ZEBRA_DEBUG_RECV)
2472 zlog_debug(
2473 "%s: SR-TE tunnel must contain at least one label",
2474 __PRETTY_FUNCTION__);
2475 return;
2476 }
2477
2478 if (!mpls_enabled)
2479 return;
2480
2481 policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
2482 if (!policy)
2483 policy = zebra_sr_policy_add(zp.color, &zp.endpoint, zp.name);
2484 /* TODO: per-VRF list of SR-TE policies. */
2485 policy->zvrf = zvrf;
2486
2487 zebra_sr_policy_validate(policy, &zp.segment_list);
2488}
2489
2490static void zread_sr_policy_delete(ZAPI_HANDLER_ARGS)
2491{
2492 struct stream *s;
2493 struct zapi_sr_policy zp;
2494 struct zebra_sr_policy *policy;
2495
2496 /* Get input stream. */
2497 s = msg;
2498 if (zapi_sr_policy_decode(s, &zp) < 0) {
2499 if (IS_ZEBRA_DEBUG_RECV)
2500 zlog_debug("%s: Unable to decode zapi_sr_policy sent",
2501 __PRETTY_FUNCTION__);
2502 return;
2503 }
2504
2505 if (!mpls_enabled)
2506 return;
2507
2508 policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
2509 if (!policy) {
2510 if (IS_ZEBRA_DEBUG_RECV)
2511 zlog_debug("%s: Unable to find SR-TE policy",
2512 __PRETTY_FUNCTION__);
2513 return;
2514 }
2515
2516 zebra_sr_policy_del(policy);
2517}
2518
2519int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint,
2520 char *name, int status)
2521{
2522 struct zserv *client;
2523 struct stream *s;
2524
2525 client = zserv_find_client(ZEBRA_ROUTE_SRTE, 0);
2526 if (!client) {
2527 if (IS_ZEBRA_DEBUG_PACKET)
2528 zlog_debug(
2529 "Not notifying pathd about policy %s"
2530 " status change to %d",
2531 name, status);
2532 return 0;
2533 }
2534
2535 if (IS_ZEBRA_DEBUG_PACKET)
2536 zlog_debug(
2537 "Notifying pathd about policy %s status change"
2538 " to %d",
2539 name, status);
2540
2541 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2542 stream_reset(s);
2543
2544 zclient_create_header(s, ZEBRA_SR_POLICY_NOTIFY_STATUS, VRF_DEFAULT);
2545 stream_putl(s, color);
2546 stream_put_ipaddr(s, endpoint);
2547 stream_write(s, name, SRTE_POLICY_NAME_MAX_LENGTH);
2548 stream_putl(s, status);
2549
2550 stream_putw_at(s, 0, stream_get_endp(s));
2551
2552 return zserv_send_message(client, s);
2553}
2554
581e797e
KS
2555/* Send client close notify to client */
2556int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client)
2557{
2558 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2559
2560 zclient_create_header(s, ZEBRA_CLIENT_CLOSE_NOTIFY, VRF_DEFAULT);
2561
2562 stream_putc(s, closed_client->proto);
2563 stream_putw(s, closed_client->instance);
2564 stream_putl(s, closed_client->session_id);
2565
2566 stream_putw_at(s, 0, stream_get_endp(s));
2567
2568 return zserv_send_message(client, s);
2569}
2570
bf094f69
QY
2571/* Send response to a table manager connect request to client */
2572static void zread_table_manager_connect(struct zserv *client,
2573 struct stream *msg, vrf_id_t vrf_id)
2574{
2575 struct stream *s;
2576 uint8_t proto;
2577 uint16_t instance;
c479e756 2578 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
bf094f69
QY
2579
2580 s = msg;
2581
2582 /* Get data. */
2583 STREAM_GETC(s, proto);
2584 STREAM_GETW(s, instance);
2585
2586 /* accept only dynamic routing protocols */
2587 if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) {
e914ccbe 2588 flog_err(EC_ZEBRA_TM_WRONG_PROTO,
1c50c1c0
QY
2589 "client %d has wrong protocol %s", client->sock,
2590 zebra_route_string(proto));
bf094f69
QY
2591 zsend_table_manager_connect_response(client, vrf_id, 1);
2592 return;
2593 }
c479e756
DS
2594 zlog_notice("client %d with vrf %s(%u) instance %u connected as %s",
2595 client->sock, VRF_LOGNAME(vrf), vrf_id, instance,
2596 zebra_route_string(proto));
bf094f69
QY
2597 client->proto = proto;
2598 client->instance = instance;
2599
2600 /*
2601 * Release previous labels of same protocol and instance.
2602 * This is done in case it restarted from an unexpected shutdown.
2603 */
453844ab 2604 release_daemon_table_chunks(client);
bf094f69
QY
2605
2606 zsend_table_manager_connect_response(client, vrf_id, 0);
2607
2608stream_failure:
2609 return;
2610}
2611
2612static void zread_label_manager_connect(struct zserv *client,
2613 struct stream *msg, vrf_id_t vrf_id)
2614{
2615 struct stream *s;
2616 /* type of protocol (lib/zebra.h) */
2617 uint8_t proto;
2618 unsigned short instance;
2619
2620 /* Get input stream. */
2621 s = msg;
2622
2623 /* Get data. */
2624 STREAM_GETC(s, proto);
2625 STREAM_GETW(s, instance);
2626
2627 /* accept only dynamic routing protocols */
2628 if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) {
e914ccbe 2629 flog_err(EC_ZEBRA_TM_WRONG_PROTO,
1c50c1c0
QY
2630 "client %d has wrong protocol %s", client->sock,
2631 zebra_route_string(proto));
e11d7c96 2632 zsend_label_manager_connect_response(client, vrf_id, 1);
bf094f69
QY
2633 return;
2634 }
e11d7c96
EDP
2635
2636 /* recall proto and instance in this socket */
bf094f69
QY
2637 client->proto = proto;
2638 client->instance = instance;
2639
e11d7c96 2640 /* call hook for connection using wrapper */
4cebdb9b 2641 lm_client_connect_call(client, vrf_id);
bf094f69
QY
2642
2643stream_failure:
2644 return;
2645}
2646
2647static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
2648 vrf_id_t vrf_id)
2649{
2650 struct stream *s;
2651 uint8_t keep;
0e3b6a92 2652 uint32_t size, base;
e11d7c96 2653 struct label_manager_chunk *lmc = NULL;
5dffb0e9
FR
2654 uint8_t proto;
2655 unsigned short instance;
bf094f69
QY
2656
2657 /* Get input stream. */
2658 s = msg;
2659
2660 /* Get data. */
5dffb0e9
FR
2661 STREAM_GETC(s, proto);
2662 STREAM_GETW(s, instance);
bf094f69
QY
2663 STREAM_GETC(s, keep);
2664 STREAM_GETL(s, size);
0e3b6a92 2665 STREAM_GETL(s, base);
bf094f69 2666
4cebdb9b
MS
2667 assert(proto == client->proto && instance == client->instance);
2668
e11d7c96 2669 /* call hook to get a chunk using wrapper */
4cebdb9b 2670 lm_get_chunk_call(&lmc, client, keep, size, base, vrf_id);
bf094f69 2671
bf094f69
QY
2672stream_failure:
2673 return;
2674}
2675
2676static void zread_release_label_chunk(struct zserv *client, struct stream *msg)
2677{
2678 struct stream *s;
2679 uint32_t start, end;
5dffb0e9
FR
2680 uint8_t proto;
2681 unsigned short instance;
bf094f69
QY
2682
2683 /* Get input stream. */
2684 s = msg;
2685
2686 /* Get data. */
5dffb0e9
FR
2687 STREAM_GETC(s, proto);
2688 STREAM_GETW(s, instance);
bf094f69
QY
2689 STREAM_GETL(s, start);
2690 STREAM_GETL(s, end);
2691
4cebdb9b
MS
2692 assert(proto == client->proto && instance == client->instance);
2693
e11d7c96 2694 /* call hook to release a chunk using wrapper */
4cebdb9b 2695 lm_release_chunk_call(client, start, end);
bf094f69
QY
2696
2697stream_failure:
2698 return;
2699}
e11d7c96 2700
bf094f69
QY
2701static void zread_label_manager_request(ZAPI_HANDLER_ARGS)
2702{
e11d7c96
EDP
2703 if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT
2704 || hdr->command == ZEBRA_LABEL_MANAGER_CONNECT_ASYNC)
2705 zread_label_manager_connect(client, msg, zvrf_id(zvrf));
bf094f69 2706 else {
e11d7c96
EDP
2707 if (hdr->command == ZEBRA_GET_LABEL_CHUNK)
2708 zread_get_label_chunk(client, msg, zvrf_id(zvrf));
2709 else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK)
2710 zread_release_label_chunk(client, msg);
bf094f69
QY
2711 }
2712}
2713
2714static void zread_get_table_chunk(struct zserv *client, struct stream *msg,
2715 vrf_id_t vrf_id)
2716{
2717 struct stream *s;
2718 uint32_t size;
2719 struct table_manager_chunk *tmc;
2720
2721 /* Get input stream. */
2722 s = msg;
2723
2724 /* Get data. */
2725 STREAM_GETL(s, size);
2726
2727 tmc = assign_table_chunk(client->proto, client->instance, size);
2728 if (!tmc)
e914ccbe 2729 flog_err(EC_ZEBRA_TM_CANNOT_ASSIGN_CHUNK,
1c50c1c0
QY
2730 "%s: Unable to assign Table Chunk of size %u",
2731 __func__, size);
bf094f69
QY
2732 else
2733 zlog_debug("Assigned Table Chunk %u - %u", tmc->start,
2734 tmc->end);
2735 /* send response back */
2736 zsend_assign_table_chunk_response(client, vrf_id, tmc);
2737
2738stream_failure:
2739 return;
2740}
2741
2742static void zread_release_table_chunk(struct zserv *client, struct stream *msg)
2743{
2744 struct stream *s;
2745 uint32_t start, end;
2746
2747 /* Get input stream. */
2748 s = msg;
2749
2750 /* Get data. */
2751 STREAM_GETL(s, start);
2752 STREAM_GETL(s, end);
2753
2754 release_table_chunk(client->proto, client->instance, start, end);
2755
2756stream_failure:
2757 return;
2758}
2759
2760static void zread_table_manager_request(ZAPI_HANDLER_ARGS)
2761{
2762 /* to avoid sending other messages like ZERBA_INTERFACE_UP */
2763 if (hdr->command == ZEBRA_TABLE_MANAGER_CONNECT)
2764 zread_table_manager_connect(client, msg, zvrf_id(zvrf));
2765 else {
2766 /* Sanity: don't allow 'unidentified' requests */
2767 if (!client->proto) {
af4c2728 2768 flog_err(
e914ccbe 2769 EC_ZEBRA_TM_ALIENS,
bf094f69
QY
2770 "Got table request from an unidentified client");
2771 return;
2772 }
2773 if (hdr->command == ZEBRA_GET_TABLE_CHUNK)
2774 zread_get_table_chunk(client, msg, zvrf_id(zvrf));
2775 else if (hdr->command == ZEBRA_RELEASE_TABLE_CHUNK)
2776 zread_release_table_chunk(client, msg);
2777 }
2778}
2779
2780static void zread_pseudowire(ZAPI_HANDLER_ARGS)
2781{
2782 struct stream *s;
2783 char ifname[IF_NAMESIZE];
2784 ifindex_t ifindex;
2785 int type;
2786 int af;
2787 union g_addr nexthop;
2788 uint32_t local_label;
2789 uint32_t remote_label;
2790 uint8_t flags;
2791 union pw_protocol_fields data;
2792 uint8_t protocol;
2793 struct zebra_pw *pw;
2794
2795 /* Get input stream. */
2796 s = msg;
2797
2798 /* Get data. */
2799 STREAM_GET(ifname, s, IF_NAMESIZE);
f223b3d1 2800 ifname[IF_NAMESIZE - 1] = '\0';
bf094f69
QY
2801 STREAM_GETL(s, ifindex);
2802 STREAM_GETL(s, type);
2803 STREAM_GETL(s, af);
2804 switch (af) {
2805 case AF_INET:
2806 STREAM_GET(&nexthop.ipv4.s_addr, s, IPV4_MAX_BYTELEN);
2807 break;
2808 case AF_INET6:
2809 STREAM_GET(&nexthop.ipv6, s, 16);
2810 break;
2811 default:
2812 return;
2813 }
2814 STREAM_GETL(s, local_label);
2815 STREAM_GETL(s, remote_label);
2816 STREAM_GETC(s, flags);
2817 STREAM_GET(&data, s, sizeof(data));
2818 protocol = client->proto;
2819
2820 pw = zebra_pw_find(zvrf, ifname);
2821 switch (hdr->command) {
2822 case ZEBRA_PW_ADD:
2823 if (pw) {
e914ccbe 2824 flog_warn(EC_ZEBRA_PSEUDOWIRE_EXISTS,
9df414fe 2825 "%s: pseudowire %s already exists [%s]",
bf094f69
QY
2826 __func__, ifname,
2827 zserv_command_string(hdr->command));
2828 return;
2829 }
2830
2831 zebra_pw_add(zvrf, ifname, protocol, client);
2832 break;
2833 case ZEBRA_PW_DELETE:
2834 if (!pw) {
e914ccbe 2835 flog_warn(EC_ZEBRA_PSEUDOWIRE_NONEXISTENT,
9df414fe 2836 "%s: pseudowire %s not found [%s]", __func__,
bf094f69
QY
2837 ifname, zserv_command_string(hdr->command));
2838 return;
2839 }
2840
2841 zebra_pw_del(zvrf, pw);
2842 break;
2843 case ZEBRA_PW_SET:
2844 case ZEBRA_PW_UNSET:
2845 if (!pw) {
e914ccbe 2846 flog_warn(EC_ZEBRA_PSEUDOWIRE_NONEXISTENT,
9df414fe 2847 "%s: pseudowire %s not found [%s]", __func__,
bf094f69
QY
2848 ifname, zserv_command_string(hdr->command));
2849 return;
2850 }
2851
2852 switch (hdr->command) {
2853 case ZEBRA_PW_SET:
2854 pw->enabled = 1;
2855 break;
2856 case ZEBRA_PW_UNSET:
2857 pw->enabled = 0;
2858 break;
2859 }
2860
2861 zebra_pw_change(pw, ifindex, type, af, &nexthop, local_label,
2862 remote_label, flags, &data);
2863 break;
2864 }
2865
2866stream_failure:
2867 return;
2868}
2869
2870static void zread_interface_set_master(ZAPI_HANDLER_ARGS)
2871{
2872 struct interface *master;
2873 struct interface *slave;
2874 struct stream *s = msg;
2875 int ifindex;
2876 vrf_id_t vrf_id;
2877
2878 STREAM_GETL(s, vrf_id);
2879 STREAM_GETL(s, ifindex);
2880 master = if_lookup_by_index(ifindex, vrf_id);
2881
2882 STREAM_GETL(s, vrf_id);
2883 STREAM_GETL(s, ifindex);
2884 slave = if_lookup_by_index(ifindex, vrf_id);
2885
2886 if (!master || !slave)
2887 return;
2888
2889 kernel_interface_set_master(master, slave);
2890
2891stream_failure:
2892 return;
2893}
2894
2895
2896static void zread_vrf_label(ZAPI_HANDLER_ARGS)
2897{
2898 struct interface *ifp;
2899 mpls_label_t nlabel;
2900 afi_t afi;
2901 struct stream *s;
2902 struct zebra_vrf *def_zvrf;
2903 enum lsp_types_t ltype;
2904
2905 s = msg;
2906 STREAM_GETL(s, nlabel);
2907 STREAM_GETC(s, afi);
663d3a91
QY
2908
2909 if (!(IS_VALID_AFI(afi))) {
2910 zlog_warn("Invalid AFI for VRF label: %u", afi);
2911 return;
2912 }
2913
bf094f69
QY
2914 if (nlabel == zvrf->label[afi]) {
2915 /*
2916 * Nothing to do here move along
2917 */
2918 return;
2919 }
2920
2921 STREAM_GETC(s, ltype);
2922
2923 if (zvrf->vrf->vrf_id != VRF_DEFAULT)
a36898e7 2924 ifp = if_lookup_by_name(zvrf->vrf->name, zvrf->vrf->vrf_id);
bf094f69 2925 else
a36898e7 2926 ifp = if_lookup_by_name("lo", VRF_DEFAULT);
bf094f69
QY
2927
2928 if (!ifp) {
2929 zlog_debug("Unable to find specified Interface for %s",
2930 zvrf->vrf->name);
2931 return;
2932 }
2933
2934 def_zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
2935
2936 if (zvrf->label[afi] != MPLS_LABEL_NONE) {
2937 afi_t scrubber;
2938 bool really_remove;
2939
2940 really_remove = true;
2941 for (scrubber = AFI_IP; scrubber < AFI_MAX; scrubber++) {
2942 if (scrubber == afi)
2943 continue;
2944
2945 if (zvrf->label[scrubber] == MPLS_LABEL_NONE)
2946 continue;
2947
2948 if (zvrf->label[afi] == zvrf->label[scrubber]) {
2949 really_remove = false;
2950 break;
2951 }
2952 }
2953
2954 if (really_remove)
2955 mpls_lsp_uninstall(def_zvrf, ltype, zvrf->label[afi],
2956 NEXTHOP_TYPE_IFINDEX, NULL,
cc1b9746 2957 ifp->ifindex, false /*backup*/);
bf094f69
QY
2958 }
2959
5065db0a
RW
2960 if (nlabel != MPLS_LABEL_NONE) {
2961 mpls_label_t out_label = MPLS_LABEL_IMPLICIT_NULL;
2962 mpls_lsp_install(def_zvrf, ltype, nlabel, 1, &out_label,
2963 NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex);
2964 }
bf094f69
QY
2965
2966 zvrf->label[afi] = nlabel;
2967stream_failure:
2968 return;
2969}
2970
2971static inline void zread_rule(ZAPI_HANDLER_ARGS)
2972{
2973 struct zebra_pbr_rule zpr;
2974 struct stream *s;
2975 uint32_t total, i;
58a1d249 2976 char ifname[INTERFACE_NAMSIZ + 1] = {};
bf094f69
QY
2977
2978 s = msg;
2979 STREAM_GETL(s, total);
2980
2981 for (i = 0; i < total; i++) {
2982 memset(&zpr, 0, sizeof(zpr));
2983
2984 zpr.sock = client->sock;
2985 zpr.rule.vrf_id = hdr->vrf_id;
2986 STREAM_GETL(s, zpr.rule.seq);
2987 STREAM_GETL(s, zpr.rule.priority);
2988 STREAM_GETL(s, zpr.rule.unique);
2989 STREAM_GETC(s, zpr.rule.filter.src_ip.family);
2990 STREAM_GETC(s, zpr.rule.filter.src_ip.prefixlen);
2991 STREAM_GET(&zpr.rule.filter.src_ip.u.prefix, s,
2992 prefix_blen(&zpr.rule.filter.src_ip));
2993 STREAM_GETW(s, zpr.rule.filter.src_port);
2994 STREAM_GETC(s, zpr.rule.filter.dst_ip.family);
2995 STREAM_GETC(s, zpr.rule.filter.dst_ip.prefixlen);
2996 STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s,
2997 prefix_blen(&zpr.rule.filter.dst_ip));
2998 STREAM_GETW(s, zpr.rule.filter.dst_port);
01f23aff 2999 STREAM_GETC(s, zpr.rule.filter.dsfield);
bf094f69
QY
3000 STREAM_GETL(s, zpr.rule.filter.fwmark);
3001 STREAM_GETL(s, zpr.rule.action.table);
58a1d249 3002 STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
bf094f69 3003
58a1d249
DS
3004 strlcpy(zpr.ifname, ifname, sizeof(zpr.ifname));
3005 strlcpy(zpr.rule.ifname, ifname, sizeof(zpr.rule.ifname));
bf094f69
QY
3006
3007 if (!is_default_prefix(&zpr.rule.filter.src_ip))
3008 zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_IP;
3009
3010 if (!is_default_prefix(&zpr.rule.filter.dst_ip))
3011 zpr.rule.filter.filter_bm |= PBR_FILTER_DST_IP;
3012
3013 if (zpr.rule.filter.src_port)
3014 zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_PORT;
3015
3016 if (zpr.rule.filter.dst_port)
3017 zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT;
3018
01f23aff
WC
3019 if (zpr.rule.filter.dsfield)
3020 zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD;
3021
bf094f69
QY
3022 if (zpr.rule.filter.fwmark)
3023 zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK;
3024
4719fd76
QY
3025 if (!(zpr.rule.filter.src_ip.family == AF_INET
3026 || zpr.rule.filter.src_ip.family == AF_INET6)) {
cc815be7 3027 zlog_warn(
6cde4b45 3028 "Unsupported PBR source IP family: %s (%hhu)",
cc815be7
QY
3029 family2str(zpr.rule.filter.src_ip.family),
3030 zpr.rule.filter.src_ip.family);
4719fd76
QY
3031 return;
3032 }
3033 if (!(zpr.rule.filter.dst_ip.family == AF_INET
3034 || zpr.rule.filter.dst_ip.family == AF_INET6)) {
cec72d49 3035 zlog_warn(
6cde4b45 3036 "Unsupported PBR destination IP family: %s (%hhu)",
cec72d49
DA
3037 family2str(zpr.rule.filter.dst_ip.family),
3038 zpr.rule.filter.dst_ip.family);
4719fd76
QY
3039 return;
3040 }
3041
3042
7f0ea8a4 3043 zpr.vrf_id = zvrf->vrf->vrf_id;
bf094f69 3044 if (hdr->command == ZEBRA_RULE_ADD)
7f0ea8a4 3045 zebra_pbr_add_rule(&zpr);
bf094f69 3046 else
7f0ea8a4 3047 zebra_pbr_del_rule(&zpr);
bf094f69
QY
3048 }
3049
3050stream_failure:
3051 return;
3052}
3053
3054static inline void zread_ipset(ZAPI_HANDLER_ARGS)
3055{
3056 struct zebra_pbr_ipset zpi;
3057 struct stream *s;
3058 uint32_t total, i;
3059
3060 s = msg;
3061 STREAM_GETL(s, total);
3062
3063 for (i = 0; i < total; i++) {
3064 memset(&zpi, 0, sizeof(zpi));
3065
3066 zpi.sock = client->sock;
be2028d1 3067 zpi.vrf_id = zvrf->vrf->vrf_id;
bf094f69
QY
3068 STREAM_GETL(s, zpi.unique);
3069 STREAM_GETL(s, zpi.type);
a60b7031 3070 STREAM_GETC(s, zpi.family);
bf094f69
QY
3071 STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
3072
3073 if (hdr->command == ZEBRA_IPSET_CREATE)
62f20a52 3074 zebra_pbr_create_ipset(&zpi);
bf094f69 3075 else
62f20a52 3076 zebra_pbr_destroy_ipset(&zpi);
bf094f69
QY
3077 }
3078
3079stream_failure:
3080 return;
3081}
3082
3083static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
3084{
3085 struct zebra_pbr_ipset_entry zpi;
3086 struct zebra_pbr_ipset ipset;
3087 struct stream *s;
3088 uint32_t total, i;
3089
3090 s = msg;
3091 STREAM_GETL(s, total);
3092
3093 for (i = 0; i < total; i++) {
3094 memset(&zpi, 0, sizeof(zpi));
3095 memset(&ipset, 0, sizeof(ipset));
3096
3097 zpi.sock = client->sock;
3098 STREAM_GETL(s, zpi.unique);
3099 STREAM_GET(&ipset.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
261462c3 3100 ipset.ipset_name[ZEBRA_IPSET_NAME_SIZE - 1] = '\0';
bf094f69
QY
3101 STREAM_GETC(s, zpi.src.family);
3102 STREAM_GETC(s, zpi.src.prefixlen);
3103 STREAM_GET(&zpi.src.u.prefix, s, prefix_blen(&zpi.src));
3104 STREAM_GETC(s, zpi.dst.family);
3105 STREAM_GETC(s, zpi.dst.prefixlen);
3106 STREAM_GET(&zpi.dst.u.prefix, s, prefix_blen(&zpi.dst));
3107
25d760c5
PG
3108 STREAM_GETW(s, zpi.src_port_min);
3109 STREAM_GETW(s, zpi.src_port_max);
3110 STREAM_GETW(s, zpi.dst_port_min);
3111 STREAM_GETW(s, zpi.dst_port_max);
3112 STREAM_GETC(s, zpi.proto);
bf094f69
QY
3113 if (!is_default_prefix(&zpi.src))
3114 zpi.filter_bm |= PBR_FILTER_SRC_IP;
3115
3116 if (!is_default_prefix(&zpi.dst))
3117 zpi.filter_bm |= PBR_FILTER_DST_IP;
be729dd7 3118 if (zpi.dst_port_min != 0 || zpi.proto == IPPROTO_ICMP)
25d760c5 3119 zpi.filter_bm |= PBR_FILTER_DST_PORT;
be729dd7 3120 if (zpi.src_port_min != 0 || zpi.proto == IPPROTO_ICMP)
25d760c5
PG
3121 zpi.filter_bm |= PBR_FILTER_SRC_PORT;
3122 if (zpi.dst_port_max != 0)
3123 zpi.filter_bm |= PBR_FILTER_DST_PORT_RANGE;
3124 if (zpi.src_port_max != 0)
3125 zpi.filter_bm |= PBR_FILTER_SRC_PORT_RANGE;
3126 if (zpi.proto != 0)
3127 zpi.filter_bm |= PBR_FILTER_PROTO;
bf094f69 3128
9863725c
QY
3129 if (!(zpi.dst.family == AF_INET
3130 || zpi.dst.family == AF_INET6)) {
cec72d49 3131 zlog_warn(
6cde4b45 3132 "Unsupported PBR destination IP family: %s (%hhu)",
cec72d49 3133 family2str(zpi.dst.family), zpi.dst.family);
9863725c
QY
3134 goto stream_failure;
3135 }
3136 if (!(zpi.src.family == AF_INET
3137 || zpi.src.family == AF_INET6)) {
cec72d49 3138 zlog_warn(
6cde4b45 3139 "Unsupported PBR source IP family: %s (%hhu)",
cec72d49 3140 family2str(zpi.src.family), zpi.src.family);
9863725c
QY
3141 goto stream_failure;
3142 }
3143
bf094f69 3144 /* calculate backpointer */
62f20a52
DS
3145 zpi.backpointer =
3146 zebra_pbr_lookup_ipset_pername(ipset.ipset_name);
f096bae4
DS
3147
3148 if (!zpi.backpointer) {
3149 zlog_warn("ipset name specified: %s does not exist",
3150 ipset.ipset_name);
3151 goto stream_failure;
3152 }
3153
bf094f69 3154 if (hdr->command == ZEBRA_IPSET_ENTRY_ADD)
62f20a52 3155 zebra_pbr_add_ipset_entry(&zpi);
bf094f69 3156 else
62f20a52 3157 zebra_pbr_del_ipset_entry(&zpi);
bf094f69
QY
3158 }
3159
3160stream_failure:
3161 return;
3162}
3163
3164static inline void zread_iptable(ZAPI_HANDLER_ARGS)
3165{
8b5c4dce
QY
3166 struct zebra_pbr_iptable *zpi =
3167 XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
bf094f69
QY
3168 struct stream *s;
3169
3170 s = msg;
3171
8b5c4dce
QY
3172 zpi->interface_name_list = list_new();
3173 zpi->sock = client->sock;
3174 zpi->vrf_id = zvrf->vrf->vrf_id;
3175 STREAM_GETL(s, zpi->unique);
3176 STREAM_GETL(s, zpi->type);
3177 STREAM_GETL(s, zpi->filter_bm);
3178 STREAM_GETL(s, zpi->action);
3179 STREAM_GETL(s, zpi->fwmark);
3180 STREAM_GET(&zpi->ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
a60b7031 3181 STREAM_GETC(s, zpi->family);
8b5c4dce
QY
3182 STREAM_GETW(s, zpi->pkt_len_min);
3183 STREAM_GETW(s, zpi->pkt_len_max);
3184 STREAM_GETW(s, zpi->tcp_flags);
3185 STREAM_GETW(s, zpi->tcp_mask_flags);
3186 STREAM_GETC(s, zpi->dscp_value);
3187 STREAM_GETC(s, zpi->fragment);
3188 STREAM_GETC(s, zpi->protocol);
a60b7031 3189 STREAM_GETW(s, zpi->flow_label);
8b5c4dce
QY
3190 STREAM_GETL(s, zpi->nb_interface);
3191 zebra_pbr_iptable_update_interfacelist(s, zpi);
bf094f69
QY
3192
3193 if (hdr->command == ZEBRA_IPTABLE_ADD)
8b5c4dce 3194 zebra_pbr_add_iptable(zpi);
bf094f69 3195 else
8b5c4dce
QY
3196 zebra_pbr_del_iptable(zpi);
3197
bf094f69 3198stream_failure:
8b5c4dce
QY
3199 zebra_pbr_iptable_free(zpi);
3200 zpi = NULL;
bf094f69
QY
3201 return;
3202}
3203
d68e74b4
JU
3204static inline void zread_neigh_discover(ZAPI_HANDLER_ARGS)
3205{
3206 struct stream *s;
3207 ifindex_t ifindex;
3208 struct interface *ifp;
3209 struct prefix p;
3210 struct ipaddr ip;
3211
3212 s = msg;
3213
3214 STREAM_GETL(s, ifindex);
3215
3216 ifp = if_lookup_by_index_per_ns(zvrf->zns, ifindex);
3217 if (!ifp) {
3218 zlog_debug("Failed to lookup ifindex: %u", ifindex);
3219 return;
3220 }
3221
3222 STREAM_GETC(s, p.family);
3223 STREAM_GETC(s, p.prefixlen);
3224 STREAM_GET(&p.u.prefix, s, prefix_blen(&p));
3225
3226 if (p.family == AF_INET)
3227 SET_IPADDR_V4(&ip);
3228 else
3229 SET_IPADDR_V6(&ip);
3230
3231 memcpy(&ip.ip.addr, &p.u.prefix, prefix_blen(&p));
3232
3233 dplane_neigh_discover(ifp, &ip);
3234
3235stream_failure:
3236 return;
3237}
3238
9ab0b2a3
SW
3239static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
3240 struct zmsghdr *bad_hdr)
3241{
3242
3243 struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
3244
3245 zclient_create_header(s, ZEBRA_ERROR, bad_hdr->vrf_id);
3246
3247 zserv_encode_error(s, error);
3248
3249 client->error_cnt++;
3250 zserv_send_message(client, s);
3251}
3252
3253static void zserv_error_no_vrf(ZAPI_HANDLER_ARGS)
3254{
3255 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
3256 zlog_debug("ZAPI message specifies unknown VRF: %d",
3257 hdr->vrf_id);
3258
5ee080f0 3259 zsend_error_msg(client, ZEBRA_NO_VRF, hdr);
9ab0b2a3
SW
3260}
3261
3262static void zserv_error_invalid_msg_type(ZAPI_HANDLER_ARGS)
3263{
3264 zlog_info("Zebra received unknown command %d", hdr->command);
3265
5ee080f0 3266 zsend_error_msg(client, ZEBRA_INVALID_MSG_TYPE, hdr);
9ab0b2a3
SW
3267}
3268
2b64873d 3269void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
bf094f69
QY
3270 [ZEBRA_ROUTER_ID_ADD] = zread_router_id_add,
3271 [ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete,
3272 [ZEBRA_INTERFACE_ADD] = zread_interface_add,
3273 [ZEBRA_INTERFACE_DELETE] = zread_interface_delete,
c3bd894e 3274 [ZEBRA_INTERFACE_SET_PROTODOWN] = zread_interface_set_protodown,
bf094f69
QY
3275 [ZEBRA_ROUTE_ADD] = zread_route_add,
3276 [ZEBRA_ROUTE_DELETE] = zread_route_del,
bf094f69
QY
3277 [ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add,
3278 [ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
3279 [ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
3280 [ZEBRA_REDISTRIBUTE_DEFAULT_DELETE] = zebra_redistribute_default_delete,
3281 [ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB] = zread_ipv4_nexthop_lookup_mrib,
3282 [ZEBRA_HELLO] = zread_hello,
3283 [ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register,
3284 [ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister,
3285 [ZEBRA_IMPORT_ROUTE_REGISTER] = zread_rnh_register,
3286 [ZEBRA_IMPORT_ROUTE_UNREGISTER] = zread_rnh_unregister,
3287 [ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register,
3288 [ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register,
3289 [ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister,
d3af6147
RZ
3290#if HAVE_BFDD > 0
3291 [ZEBRA_BFD_DEST_REPLAY] = zebra_ptm_bfd_dst_replay,
3292#endif /* HAVE_BFDD */
bf094f69
QY
3293 [ZEBRA_VRF_UNREGISTER] = zread_vrf_unregister,
3294 [ZEBRA_VRF_LABEL] = zread_vrf_label,
3295 [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register,
bf094f69
QY
3296 [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable,
3297 [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable,
31f937fb
SM
3298 [ZEBRA_SR_POLICY_SET] = zread_sr_policy_set,
3299 [ZEBRA_SR_POLICY_DELETE] = zread_sr_policy_delete,
ea6b290b
RW
3300 [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add,
3301 [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels_delete,
3302 [ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace,
bf094f69
QY
3303 [ZEBRA_IPMR_ROUTE_STATS] = zebra_ipmr_route_stats,
3304 [ZEBRA_LABEL_MANAGER_CONNECT] = zread_label_manager_request,
f533be73 3305 [ZEBRA_LABEL_MANAGER_CONNECT_ASYNC] = zread_label_manager_request,
bf094f69
QY
3306 [ZEBRA_GET_LABEL_CHUNK] = zread_label_manager_request,
3307 [ZEBRA_RELEASE_LABEL_CHUNK] = zread_label_manager_request,
3308 [ZEBRA_FEC_REGISTER] = zread_fec_register,
3309 [ZEBRA_FEC_UNREGISTER] = zread_fec_unregister,
3310 [ZEBRA_ADVERTISE_DEFAULT_GW] = zebra_vxlan_advertise_gw_macip,
278e26de 3311 [ZEBRA_ADVERTISE_SVI_MACIP] = zebra_vxlan_advertise_svi_macip,
bf094f69
QY
3312 [ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet,
3313 [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni,
ce5160c0
AK
3314 [ZEBRA_REMOTE_ES_VTEP_ADD] = zebra_evpn_proc_remote_es,
3315 [ZEBRA_REMOTE_ES_VTEP_DEL] = zebra_evpn_proc_remote_es,
bf094f69
QY
3316 [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add,
3317 [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del,
3318 [ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add,
3319 [ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del,
3950b52c 3320 [ZEBRA_DUPLICATE_ADDR_DETECTION] = zebra_vxlan_dup_addr_detection,
bf094f69
QY
3321 [ZEBRA_INTERFACE_SET_MASTER] = zread_interface_set_master,
3322 [ZEBRA_PW_ADD] = zread_pseudowire,
3323 [ZEBRA_PW_DELETE] = zread_pseudowire,
3324 [ZEBRA_PW_SET] = zread_pseudowire,
3325 [ZEBRA_PW_UNSET] = zread_pseudowire,
3326 [ZEBRA_RULE_ADD] = zread_rule,
3327 [ZEBRA_RULE_DELETE] = zread_rule,
3328 [ZEBRA_TABLE_MANAGER_CONNECT] = zread_table_manager_request,
3329 [ZEBRA_GET_TABLE_CHUNK] = zread_table_manager_request,
3330 [ZEBRA_RELEASE_TABLE_CHUNK] = zread_table_manager_request,
3331 [ZEBRA_IPSET_CREATE] = zread_ipset,
3332 [ZEBRA_IPSET_DESTROY] = zread_ipset,
3333 [ZEBRA_IPSET_ENTRY_ADD] = zread_ipset_entry,
3334 [ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry,
3335 [ZEBRA_IPTABLE_ADD] = zread_iptable,
3336 [ZEBRA_IPTABLE_DELETE] = zread_iptable,
fbac9605 3337 [ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control,
ecbbc3a7 3338 [ZEBRA_VXLAN_SG_REPLAY] = zebra_vxlan_sg_replay,
ee235396
SK
3339 [ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
3340 [ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
3341 [ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
d68e74b4 3342 [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities,
2f35a820 3343 [ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
8b2d3a0f 3344 [ZEBRA_NHG_ADD] = zread_nhg_add,
2f35a820 3345 [ZEBRA_NHG_DEL] = zread_nhg_del,
77b38a4a 3346 [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
2f35a820 3347};
bf094f69 3348
79b3664a
MS
3349/*
3350 * Process a batch of zapi messages.
3351 */
3352void zserv_handle_commands(struct zserv *client, struct stream_fifo *fifo)
bf094f69 3353{
904e0d88
QY
3354 struct zmsghdr hdr;
3355 struct zebra_vrf *zvrf;
79b3664a
MS
3356 struct stream *msg;
3357 struct stream_fifo temp_fifo;
904e0d88 3358
79b3664a 3359 stream_fifo_init(&temp_fifo);
aa8cb964 3360
79b3664a
MS
3361 while (stream_fifo_head(fifo)) {
3362 msg = stream_fifo_pop(fifo);
bf094f69 3363
79b3664a
MS
3364 if (STREAM_READABLE(msg) > ZEBRA_MAX_PACKET_SIZ) {
3365 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
3366 zlog_debug(
3367 "ZAPI message is %zu bytes long but the maximum packet size is %u; dropping",
3368 STREAM_READABLE(msg),
3369 ZEBRA_MAX_PACKET_SIZ);
3370 goto continue_loop;
3371 }
3372
3373 zapi_parse_header(msg, &hdr);
3374
ec64a77b
DS
3375 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV
3376 && IS_ZEBRA_DEBUG_DETAIL)
79b3664a 3377 zserv_log_message(NULL, msg, &hdr);
49b3b01f 3378
79b3664a 3379 hdr.length -= ZEBRA_HEADER_SIZE;
904e0d88 3380
79b3664a
MS
3381 /* Before checking for a handler function, check for
3382 * special messages that are handled in another module;
3383 * we'll treat these as opaque.
3384 */
3385 if (zebra_opaque_handles_msgid(hdr.command)) {
3386 /* Reset message buffer */
3387 stream_set_getp(msg, 0);
3388
3389 stream_fifo_push(&temp_fifo, msg);
3390
3391 /* Continue without freeing the message */
3392 msg = NULL;
3393 goto continue_loop;
3394 }
3395
3396 /* lookup vrf */
3397 zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id);
3398 if (!zvrf) {
3399 zserv_error_no_vrf(client, &hdr, msg, zvrf);
3400 goto continue_loop;
3401 }
3402
3403 if (hdr.command >= array_size(zserv_handlers)
3404 || zserv_handlers[hdr.command] == NULL) {
3405 zserv_error_invalid_msg_type(client, &hdr, msg, zvrf);
3406 goto continue_loop;
3407 }
3408
3409 zserv_handlers[hdr.command](client, &hdr, msg, zvrf);
3410
3411continue_loop:
3412 stream_free(msg);
3413 }
904e0d88 3414
79b3664a
MS
3415 /* Dispatch any special messages from the temp fifo */
3416 if (stream_fifo_head(&temp_fifo) != NULL)
3417 zebra_opaque_enqueue_batch(&temp_fifo);
9ab0b2a3 3418
79b3664a 3419 stream_fifo_deinit(&temp_fifo);
bf094f69 3420}