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