]> git.proxmox.com Git - mirror_frr.git/blame - lib/zclient.c
Merge pull request #9848 from ton31337/feature/as-path_autocomplete
[mirror_frr.git] / lib / zclient.c
CommitLineData
718e3744 1/* Zebra's client library.
2 * Copyright (C) 1999 Kunihiro Ishiguro
634f9ea2 3 * Copyright (C) 2005 Andrew J. Schorr
718e3744 4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "stream.h"
634f9ea2 26#include "buffer.h"
718e3744 27#include "network.h"
7922fc65
DS
28#include "vrf.h"
29#include "vrf_int.h"
718e3744 30#include "if.h"
31#include "log.h"
32#include "thread.h"
33#include "zclient.h"
34#include "memory.h"
35#include "table.h"
5b30316e 36#include "nexthop.h"
fea12efb 37#include "mpls.h"
342213ea 38#include "sockopt.h"
0031a6bb 39#include "pbr.h"
98cbbaea 40#include "nexthop_group.h"
1ca3850c 41#include "lib_errors.h"
31f937fb 42#include "srte.h"
61e6de9d 43#include "printfrr.h"
f2867068 44#include "srv6.h"
6b0655a2 45
bf8d3d6a
DL
46DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient");
47DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs");
4a1ab8e4 48
718e3744 49/* Zebra client events. */
d62a17ae 50enum event { ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT };
718e3744 51
52/* Prototype for event manager. */
d62a17ae 53static void zclient_event(enum event, struct zclient *);
718e3744 54
41ce5384
QY
55static void zebra_interface_if_set_value(struct stream *s,
56 struct interface *ifp);
26f8f6fe 57
17da84a4
KS
58struct zclient_options zclient_options_default = {.receive_notify = false,
59 .synchronous = false};
c17faa4b 60
689f5a8c
DL
61struct sockaddr_storage zclient_addr;
62socklen_t zclient_addr_len;
b5114685 63
718e3744 64/* This file local debug flag. */
c17faa4b 65static int zclient_debug;
e1a1880d 66
718e3744 67/* Allocate zclient structure. */
26f63a1e
DS
68struct zclient *zclient_new(struct thread_master *master,
69 struct zclient_options *opt)
718e3744 70{
d62a17ae 71 struct zclient *zclient;
f3f45626
DS
72 size_t stream_size =
73 MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
74
d62a17ae 75 zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient));
718e3744 76
f3f45626
DS
77 zclient->ibuf = stream_new(stream_size);
78 zclient->obuf = stream_new(stream_size);
d62a17ae 79 zclient->wb = buffer_new(0);
80 zclient->master = master;
718e3744 81
e1a1880d 82 zclient->receive_notify = opt->receive_notify;
17da84a4 83 zclient->synchronous = opt->synchronous;
e1a1880d 84
d62a17ae 85 return zclient;
718e3744 86}
87
228da428 88/* This function is only called when exiting, because
634f9ea2 89 many parts of the code do not check for I/O errors, so they could
90 reference an invalid pointer if the structure was ever freed.
634f9ea2 91
228da428 92 Free zclient structure. */
d62a17ae 93void zclient_free(struct zclient *zclient)
718e3744 94{
d62a17ae 95 if (zclient->ibuf)
96 stream_free(zclient->ibuf);
97 if (zclient->obuf)
98 stream_free(zclient->obuf);
99 if (zclient->wb)
100 buffer_free(zclient->wb);
101
102 XFREE(MTYPE_ZCLIENT, zclient);
718e3744 103}
104
d7c0a89a
QY
105unsigned short *redist_check_instance(struct redist_proto *red,
106 unsigned short instance)
7c8ff89e 107{
d62a17ae 108 struct listnode *node;
d7c0a89a 109 unsigned short *id;
7c8ff89e 110
d62a17ae 111 if (!red->instances)
112 return NULL;
7c8ff89e 113
d62a17ae 114 for (ALL_LIST_ELEMENTS_RO(red->instances, node, id))
115 if (*id == instance)
116 return id;
7c8ff89e 117
d62a17ae 118 return NULL;
7c8ff89e
DS
119}
120
d7c0a89a 121void redist_add_instance(struct redist_proto *red, unsigned short instance)
7c8ff89e 122{
d7c0a89a 123 unsigned short *in;
7c8ff89e 124
d62a17ae 125 red->enabled = 1;
7c8ff89e 126
d62a17ae 127 if (!red->instances)
128 red->instances = list_new();
7c8ff89e 129
d7c0a89a 130 in = XMALLOC(MTYPE_REDIST_INST, sizeof(unsigned short));
d62a17ae 131 *in = instance;
132 listnode_add(red->instances, in);
7c8ff89e
DS
133}
134
d7c0a89a 135void redist_del_instance(struct redist_proto *red, unsigned short instance)
7c8ff89e 136{
d7c0a89a 137 unsigned short *id;
d62a17ae 138
139 id = redist_check_instance(red, instance);
140 if (!id)
141 return;
142
143 listnode_delete(red->instances, id);
144 XFREE(MTYPE_REDIST_INST, id);
145 if (!red->instances->count) {
146 red->enabled = 0;
6a154c88 147 list_delete(&red->instances);
d62a17ae 148 }
7c8ff89e
DS
149}
150
24c370dd
QY
151void redist_del_all_instances(struct redist_proto *red)
152{
153 struct listnode *ln, *nn;
154 unsigned short *id;
155
156 if (!red->instances)
157 return;
158
159 for (ALL_LIST_ELEMENTS(red->instances, ln, nn, id))
160 redist_del_instance(red, *id);
161}
162
718e3744 163/* Stop zebra client services. */
d62a17ae 164void zclient_stop(struct zclient *zclient)
718e3744 165{
d62a17ae 166 afi_t afi;
167 int i;
168
169 if (zclient_debug)
2be4d61a 170 zlog_debug("zclient %p stopped", zclient);
d62a17ae 171
172 /* Stop threads. */
173 THREAD_OFF(zclient->t_read);
174 THREAD_OFF(zclient->t_connect);
175 THREAD_OFF(zclient->t_write);
176
177 /* Reset streams. */
178 stream_reset(zclient->ibuf);
179 stream_reset(zclient->obuf);
180
181 /* Empty the write buffer. */
182 buffer_reset(zclient->wb);
183
184 /* Close socket. */
185 if (zclient->sock >= 0) {
186 close(zclient->sock);
187 zclient->sock = -1;
188 }
189 zclient->fail = 0;
190
191 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
192 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
193 vrf_bitmap_free(zclient->redist[afi][i]);
194 zclient->redist[afi][i] = VRF_BITMAP_NULL;
195 }
196 redist_del_instance(
197 &zclient->mi_redist[afi][zclient->redist_default],
198 zclient->instance);
41246cb6 199
49db7a7b
RW
200 vrf_bitmap_free(zclient->default_information[afi]);
201 zclient->default_information[afi] = VRF_BITMAP_NULL;
202 }
718e3744 203}
204
d62a17ae 205void zclient_reset(struct zclient *zclient)
718e3744 206{
d62a17ae 207 afi_t afi;
3d68677e 208
d62a17ae 209 zclient_stop(zclient);
3d68677e 210
d62a17ae 211 for (afi = AFI_IP; afi < AFI_MAX; afi++)
212 redist_del_instance(
213 &zclient->mi_redist[afi][zclient->redist_default],
214 zclient->instance);
3d68677e 215
996c9314
LB
216 zclient_init(zclient, zclient->redist_default, zclient->instance,
217 zclient->privs);
718e3744 218}
219
689f5a8c
DL
220/**
221 * Connect to zebra daemon.
222 * @param zclient a pointer to zclient structure
223 * @return socket fd just to make sure that connection established
224 * @see zclient_init
26f63a1e 225 * @see zclient_new
689f5a8c
DL
226 */
227int zclient_socket_connect(struct zclient *zclient)
718e3744 228{
d62a17ae 229 int sock;
230 int ret;
d62a17ae 231
232 /* We should think about IPv6 connection. */
689f5a8c 233 sock = socket(zclient_addr.ss_family, SOCK_STREAM, 0);
d62a17ae 234 if (sock < 0)
235 return -1;
236
689f5a8c 237 set_cloexec(sock);
338b8e91 238 setsockopt_so_sendbuf(sock, 1048576);
342213ea 239
d62a17ae 240 /* Connect to zebra. */
996c9314 241 ret = connect(sock, (struct sockaddr *)&zclient_addr, zclient_addr_len);
d62a17ae 242 if (ret < 0) {
243 if (zclient_debug)
15569c58
DA
244 zlog_debug("%s connect failure: %d(%s)", __func__,
245 errno, safe_strerror(errno));
d62a17ae 246 close(sock);
247 return -1;
248 }
718e3744 249
689f5a8c 250 zclient->sock = sock;
d62a17ae 251 return sock;
718e3744 252}
253
8a3f8f2e 254static enum zclient_send_status zclient_failed(struct zclient *zclient)
634f9ea2 255{
d62a17ae 256 zclient->fail++;
257 zclient_stop(zclient);
258 zclient_event(ZCLIENT_CONNECT, zclient);
8a3f8f2e 259 return ZCLIENT_SEND_FAILURE;
634f9ea2 260}
261
d62a17ae 262static int zclient_flush_data(struct thread *thread)
634f9ea2 263{
d62a17ae 264 struct zclient *zclient = THREAD_ARG(thread);
265
266 zclient->t_write = NULL;
267 if (zclient->sock < 0)
268 return -1;
269 switch (buffer_flush_available(zclient->wb, zclient->sock)) {
270 case BUFFER_ERROR:
ade6974d 271 flog_err(
450971aa 272 EC_LIB_ZAPI_SOCKET,
ade6974d
QY
273 "%s: buffer_flush_available failed on zclient fd %d, closing",
274 __func__, zclient->sock);
d62a17ae 275 return zclient_failed(zclient);
d62a17ae 276 case BUFFER_PENDING:
277 zclient->t_write = NULL;
278 thread_add_write(zclient->master, zclient_flush_data, zclient,
279 zclient->sock, &zclient->t_write);
280 break;
281 case BUFFER_EMPTY:
db71415b
DS
282 if (zclient->zebra_buffer_write_ready)
283 (*zclient->zebra_buffer_write_ready)();
d62a17ae 284 break;
285 }
286 return 0;
634f9ea2 287}
288
db71415b 289/*
8a3f8f2e
DS
290 * Returns:
291 * ZCLIENT_SEND_FAILED - is a failure
292 * ZCLIENT_SEND_SUCCESS - means we sent data to zebra
293 * ZCLIENT_SEND_BUFFERED - means we are buffering
db71415b 294 */
8a3f8f2e 295enum zclient_send_status zclient_send_message(struct zclient *zclient)
634f9ea2 296{
d62a17ae 297 if (zclient->sock < 0)
8a3f8f2e 298 return ZCLIENT_SEND_FAILURE;
d62a17ae 299 switch (buffer_write(zclient->wb, zclient->sock,
300 STREAM_DATA(zclient->obuf),
301 stream_get_endp(zclient->obuf))) {
302 case BUFFER_ERROR:
450971aa 303 flog_err(EC_LIB_ZAPI_SOCKET,
decbd929
DS
304 "%s: buffer_write failed to zclient fd %d, closing",
305 __func__, zclient->sock);
d62a17ae 306 return zclient_failed(zclient);
d62a17ae 307 case BUFFER_EMPTY:
308 THREAD_OFF(zclient->t_write);
8a3f8f2e 309 return ZCLIENT_SEND_SUCCESS;
d62a17ae 310 case BUFFER_PENDING:
311 thread_add_write(zclient->master, zclient_flush_data, zclient,
312 zclient->sock, &zclient->t_write);
8a3f8f2e 313 return ZCLIENT_SEND_BUFFERED;
d62a17ae 314 }
db71415b
DS
315
316 /* should not get here */
8a3f8f2e 317 return ZCLIENT_SEND_SUCCESS;
634f9ea2 318}
319
6e8e0925
DS
320/*
321 * If we add more data to this structure please ensure that
322 * struct zmsghdr in lib/zclient.h is updated as appropriate.
323 */
d62a17ae 324void zclient_create_header(struct stream *s, uint16_t command, vrf_id_t vrf_id)
c1b9800a 325{
d62a17ae 326 /* length placeholder, caller can update */
327 stream_putw(s, ZEBRA_HEADER_SIZE);
328 stream_putc(s, ZEBRA_HEADER_MARKER);
329 stream_putc(s, ZSERV_VERSION);
a9ff90c4 330 stream_putl(s, vrf_id);
d62a17ae 331 stream_putw(s, command);
c1b9800a 332}
333
d7c0a89a
QY
334int zclient_read_header(struct stream *s, int sock, uint16_t *size,
335 uint8_t *marker, uint8_t *version, vrf_id_t *vrf_id,
336 uint16_t *cmd)
55119089 337{
d62a17ae 338 if (stream_read(s, sock, ZEBRA_HEADER_SIZE) != ZEBRA_HEADER_SIZE)
339 return -1;
340
ec93aa12
DS
341 STREAM_GETW(s, *size);
342 *size -= ZEBRA_HEADER_SIZE;
343 STREAM_GETC(s, *marker);
344 STREAM_GETC(s, *version);
a9ff90c4 345 STREAM_GETL(s, *vrf_id);
ec93aa12 346 STREAM_GETW(s, *cmd);
d62a17ae 347
348 if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) {
1c50c1c0
QY
349 flog_err(
350 EC_LIB_ZAPI_MISSMATCH,
351 "%s: socket %d version mismatch, marker %d, version %d",
352 __func__, sock, *marker, *version);
d62a17ae 353 return -1;
354 }
355
356 if (*size && stream_read(s, sock, *size) != *size)
357 return -1;
358
359 return 0;
6a2b0d9a
RW
360stream_failure:
361 return -1;
55119089
ND
362}
363
124ead27
QY
364bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr)
365{
366 STREAM_GETW(zmsg, hdr->length);
367 STREAM_GETC(zmsg, hdr->marker);
368 STREAM_GETC(zmsg, hdr->version);
107afcd1 369 STREAM_GETL(zmsg, hdr->vrf_id);
124ead27
QY
370 STREAM_GETW(zmsg, hdr->command);
371 return true;
372stream_failure:
373 return false;
374}
375
634f9ea2 376/* Send simple Zebra message. */
7cfdb485
DS
377static enum zclient_send_status zebra_message_send(struct zclient *zclient,
378 int command, vrf_id_t vrf_id)
718e3744 379{
d62a17ae 380 struct stream *s;
718e3744 381
d62a17ae 382 /* Get zclient output buffer. */
383 s = zclient->obuf;
384 stream_reset(s);
718e3744 385
d62a17ae 386 /* Send very simple command only Zebra message. */
387 zclient_create_header(s, command, vrf_id);
388
389 return zclient_send_message(zclient);
718e3744 390}
391
7cfdb485 392enum zclient_send_status zclient_send_hello(struct zclient *zclient)
2ea1ab1c 393{
d62a17ae 394 struct stream *s;
395
17da84a4 396 if (zclient->redist_default || zclient->synchronous) {
d62a17ae 397 s = zclient->obuf;
398 stream_reset(s);
399
400 /* The VRF ID in the HELLO message is always 0. */
401 zclient_create_header(s, ZEBRA_HELLO, VRF_DEFAULT);
402 stream_putc(s, zclient->redist_default);
403 stream_putw(s, zclient->instance);
4e0b5b31 404 stream_putl(s, zclient->session_id);
e1a1880d
DS
405 if (zclient->receive_notify)
406 stream_putc(s, 1);
407 else
408 stream_putc(s, 0);
17da84a4
KS
409 if (zclient->synchronous)
410 stream_putc(s, 1);
411 else
412 stream_putc(s, 0);
e1a1880d 413
d62a17ae 414 stream_putw_at(s, 0, stream_get_endp(s));
415 return zclient_send_message(zclient);
416 }
417
7cfdb485 418 return ZCLIENT_SEND_SUCCESS;
2ea1ab1c
VT
419}
420
7cfdb485
DS
421enum zclient_send_status zclient_send_vrf_label(struct zclient *zclient,
422 vrf_id_t vrf_id, afi_t afi,
423 mpls_label_t label,
424 enum lsp_types_t ltype)
c83c5e44
DS
425{
426 struct stream *s;
427
428 s = zclient->obuf;
429 stream_reset(s);
430
431 zclient_create_header(s, ZEBRA_VRF_LABEL, vrf_id);
432 stream_putl(s, label);
7d061b3c 433 stream_putc(s, afi);
339e36d2 434 stream_putc(s, ltype);
c83c5e44 435 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 436 return zclient_send_message(zclient);
c83c5e44
DS
437}
438
618538f8
HS
439enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
440 const struct in6_addr *sid, ifindex_t oif,
441 enum seg6local_action_t action,
442 const struct seg6local_context *context)
443{
1bda3e62
HS
444 struct prefix_ipv6 p = {};
445 struct zapi_route api = {};
446 struct nexthop nh = {};
618538f8 447
618538f8 448 p.family = AF_INET6;
13ccce6e 449 p.prefixlen = IPV6_MAX_BITLEN;
618538f8
HS
450 p.prefix = *sid;
451
618538f8
HS
452 api.vrf_id = VRF_DEFAULT;
453 api.type = ZEBRA_ROUTE_BGP;
454 api.instance = 0;
455 api.safi = SAFI_UNICAST;
456 memcpy(&api.prefix, &p, sizeof(p));
457
458 if (action == ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
459 return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
460
461 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
618538f8
HS
462 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
463
618538f8
HS
464 nh.type = NEXTHOP_TYPE_IFINDEX;
465 nh.ifindex = oif;
c60c1ade 466 SET_FLAG(nh.flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
eab0f8f0 467 nexthop_add_srv6_seg6local(&nh, action, context);
618538f8
HS
468
469 zapi_nexthop_from_nexthop(&api.nexthops[0], &nh);
470 api.nexthop_num = 1;
471
472 return zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
473}
474
0e5223e7 475/* Send register requests to zebra daemon for the information in a VRF. */
d62a17ae 476void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
7076bb2f 477{
d62a17ae 478 int i;
479 afi_t afi;
480
d62a17ae 481 /* If not connected to the zebra yet. */
482 if (zclient->sock < 0)
483 return;
484
485 if (zclient_debug)
486 zlog_debug("%s: send register messages for VRF %u", __func__,
487 vrf_id);
488
489 /* We need router-id information. */
98a3fb0a
SM
490 zclient_send_router_id_update(zclient, ZEBRA_ROUTER_ID_ADD, AFI_IP,
491 vrf_id);
d62a17ae 492
eeb2dfa3
DS
493 /* We need interface information. */
494 zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, vrf_id);
495
d62a17ae 496 /* Set unwanted redistribute route. */
497 for (afi = AFI_IP; afi < AFI_MAX; afi++)
498 vrf_bitmap_set(zclient->redist[afi][zclient->redist_default],
499 vrf_id);
500
501 /* Flush all redistribute request. */
0d9e7f45
DS
502 if (vrf_id == VRF_DEFAULT) {
503 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
504 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
505 if (!zclient->mi_redist[afi][i].enabled)
506 continue;
507
508 struct listnode *node;
d7c0a89a 509 unsigned short *id;
0d9e7f45
DS
510
511 for (ALL_LIST_ELEMENTS_RO(
512 zclient->mi_redist[afi][i]
996c9314
LB
513 .instances,
514 node, id))
0d9e7f45
DS
515 if (!(i == zclient->redist_default
516 && *id == zclient->instance))
517 zebra_redistribute_send(
518 ZEBRA_REDISTRIBUTE_ADD,
996c9314 519 zclient, afi, i, *id,
0d9e7f45
DS
520 VRF_DEFAULT);
521 }
522 }
523 }
d62a17ae 524
70172b1c 525 /* Resend all redistribute request. */
49db7a7b 526 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
d62a17ae 527 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
528 if (i != zclient->redist_default
529 && vrf_bitmap_check(zclient->redist[afi][i],
530 vrf_id))
531 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD,
532 zclient, afi, i, 0,
533 vrf_id);
534
49db7a7b 535 /* If default information is needed. */
d7637898 536 if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
49db7a7b
RW
537 zebra_redistribute_default_send(
538 ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, afi,
539 vrf_id);
540 }
7076bb2f
FL
541}
542
0e5223e7 543/* Send unregister requests to zebra daemon for the information in a VRF. */
d62a17ae 544void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
0e5223e7 545{
d62a17ae 546 int i;
547 afi_t afi;
548
d62a17ae 549 /* If not connected to the zebra yet. */
550 if (zclient->sock < 0)
551 return;
552
553 if (zclient_debug)
554 zlog_debug("%s: send deregister messages for VRF %u", __func__,
555 vrf_id);
556
557 /* We need router-id information. */
98a3fb0a
SM
558 zclient_send_router_id_update(zclient, ZEBRA_ROUTER_ID_DELETE, AFI_IP,
559 vrf_id);
d62a17ae 560
eeb2dfa3 561 zebra_message_send(zclient, ZEBRA_INTERFACE_DELETE, vrf_id);
d62a17ae 562
d62a17ae 563 /* Set unwanted redistribute route. */
564 for (afi = AFI_IP; afi < AFI_MAX; afi++)
09eef679
DS
565 vrf_bitmap_unset(zclient->redist[afi][zclient->redist_default],
566 vrf_id);
d62a17ae 567
568 /* Flush all redistribute request. */
0d9e7f45
DS
569 if (vrf_id == VRF_DEFAULT) {
570 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
571 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
572 if (!zclient->mi_redist[afi][i].enabled)
573 continue;
574
575 struct listnode *node;
d7c0a89a 576 unsigned short *id;
0d9e7f45
DS
577
578 for (ALL_LIST_ELEMENTS_RO(
579 zclient->mi_redist[afi][i]
996c9314
LB
580 .instances,
581 node, id))
0d9e7f45
DS
582 if (!(i == zclient->redist_default
583 && *id == zclient->instance))
584 zebra_redistribute_send(
585 ZEBRA_REDISTRIBUTE_DELETE,
996c9314 586 zclient, afi, i, *id,
0d9e7f45
DS
587 VRF_DEFAULT);
588 }
589 }
590 }
d62a17ae 591
592 /* Flush all redistribute request. */
49db7a7b 593 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
d62a17ae 594 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
595 if (i != zclient->redist_default
596 && vrf_bitmap_check(zclient->redist[afi][i],
597 vrf_id))
598 zebra_redistribute_send(
599 ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
600 i, 0, vrf_id);
601
49db7a7b 602 /* If default information is needed. */
d7637898 603 if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
49db7a7b
RW
604 zebra_redistribute_default_send(
605 ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, afi,
606 vrf_id);
607 }
0e5223e7 608}
609
7cfdb485
DS
610enum zclient_send_status
611zclient_send_router_id_update(struct zclient *zclient,
612 zebra_message_types_t type, afi_t afi,
613 vrf_id_t vrf_id)
98a3fb0a
SM
614{
615 struct stream *s = zclient->obuf;
616 stream_reset(s);
617 zclient_create_header(s, type, vrf_id);
618 stream_putw(s, afi);
619 stream_putw_at(s, 0, stream_get_endp(s));
620 return zclient_send_message(zclient);
621}
622
4a04e5f7 623/* Send request to zebra daemon to start or stop RA. */
7cfdb485
DS
624enum zclient_send_status
625zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
626 struct interface *ifp, int enable,
bbad0276 627 uint32_t ra_interval)
4a04e5f7 628{
d62a17ae 629 struct stream *s;
4a04e5f7 630
d62a17ae 631 /* If not connected to the zebra yet. */
632 if (zclient->sock < 0)
7cfdb485 633 return ZCLIENT_SEND_FAILURE;
4a04e5f7 634
d62a17ae 635 /* Form and send message. */
636 s = zclient->obuf;
637 stream_reset(s);
4a04e5f7 638
d62a17ae 639 if (enable)
640 zclient_create_header(s, ZEBRA_INTERFACE_ENABLE_RADV, vrf_id);
641 else
642 zclient_create_header(s, ZEBRA_INTERFACE_DISABLE_RADV, vrf_id);
4a04e5f7 643
d62a17ae 644 stream_putl(s, ifp->ifindex);
645 stream_putl(s, ra_interval);
4a04e5f7 646
d62a17ae 647 stream_putw_at(s, 0, stream_get_endp(s));
4a04e5f7 648
db71415b 649 return zclient_send_message(zclient);
4a04e5f7 650}
651
7cfdb485
DS
652enum zclient_send_status
653zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id,
654 struct interface *ifp, bool down)
c3bd894e
QY
655{
656 struct stream *s;
657
658 if (zclient->sock < 0)
7cfdb485 659 return ZCLIENT_SEND_FAILURE;
c3bd894e
QY
660
661 s = zclient->obuf;
662 stream_reset(s);
663 zclient_create_header(s, ZEBRA_INTERFACE_SET_PROTODOWN, vrf_id);
664 stream_putl(s, ifp->ifindex);
665 stream_putc(s, !!down);
666 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 667 return zclient_send_message(zclient);
c3bd894e
QY
668}
669
718e3744 670/* Make connection to zebra daemon. */
d62a17ae 671int zclient_start(struct zclient *zclient)
718e3744 672{
d62a17ae 673 if (zclient_debug)
674 zlog_info("zclient_start is called");
675
d62a17ae 676 /* If already connected to the zebra. */
677 if (zclient->sock >= 0)
678 return 0;
679
680 /* Check connect thread. */
681 if (zclient->t_connect)
682 return 0;
683
684 if (zclient_socket_connect(zclient) < 0) {
685 if (zclient_debug)
686 zlog_debug("zclient connection fail");
687 zclient->fail++;
688 zclient_event(ZCLIENT_CONNECT, zclient);
689 return -1;
690 }
718e3744 691
d62a17ae 692 if (set_nonblocking(zclient->sock) < 0)
450971aa 693 flog_err(EC_LIB_ZAPI_SOCKET, "%s: set_nonblocking(%d) failed",
ade6974d 694 __func__, zclient->sock);
718e3744 695
d62a17ae 696 /* Clear fail count. */
697 zclient->fail = 0;
698 if (zclient_debug)
699 zlog_debug("zclient connect success with socket [%d]",
700 zclient->sock);
718e3744 701
d62a17ae 702 /* Create read thread. */
703 zclient_event(ZCLIENT_READ, zclient);
718e3744 704
17da84a4 705 zclient_send_hello(zclient);
718e3744 706
22761baa
DS
707 zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, VRF_DEFAULT);
708
d62a17ae 709 /* Inform the successful connection. */
710 if (zclient->zebra_connected)
711 (*zclient->zebra_connected)(zclient);
718e3744 712
d62a17ae 713 return 0;
718e3744 714}
6b0655a2 715
078430f6
DS
716/* Initialize zebra client. Argument redist_default is unwanted
717 redistribute route type. */
d7c0a89a
QY
718void zclient_init(struct zclient *zclient, int redist_default,
719 unsigned short instance, struct zebra_privs_t *privs)
078430f6 720{
d62a17ae 721 int afi, i;
722
d62a17ae 723 /* Set -1 to the default socket value. */
724 zclient->sock = -1;
342213ea 725 zclient->privs = privs;
d62a17ae 726
727 /* Clear redistribution flags. */
728 for (afi = AFI_IP; afi < AFI_MAX; afi++)
729 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
730 zclient->redist[afi][i] = vrf_bitmap_init();
731
732 /* Set unwanted redistribute route. bgpd does not need BGP route
733 redistribution. */
734 zclient->redist_default = redist_default;
735 zclient->instance = instance;
736 /* Pending: make afi(s) an arg. */
49db7a7b 737 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
d62a17ae 738 redist_add_instance(&zclient->mi_redist[afi][redist_default],
739 instance);
740
49db7a7b
RW
741 /* Set default-information redistribute to zero. */
742 zclient->default_information[afi] = vrf_bitmap_init();
743 }
d62a17ae 744
745 if (zclient_debug)
cdc6ed90 746 zlog_debug("scheduling zclient connection");
d62a17ae 747
748 zclient_event(ZCLIENT_SCHEDULE, zclient);
7076bb2f 749}
078430f6 750
7076bb2f
FL
751/* This function is a wrapper function for calling zclient_start from
752 timer or event thread. */
d62a17ae 753static int zclient_connect(struct thread *t)
7076bb2f 754{
d62a17ae 755 struct zclient *zclient;
078430f6 756
d62a17ae 757 zclient = THREAD_ARG(t);
758 zclient->t_connect = NULL;
078430f6 759
d62a17ae 760 if (zclient_debug)
761 zlog_debug("zclient_connect is called");
078430f6 762
d62a17ae 763 return zclient_start(zclient);
078430f6
DS
764}
765
7cfdb485
DS
766enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command,
767 const struct prefix *p,
6cd9a93d 768 bool connected,
ed6cec97 769 bool resolve_via_def, vrf_id_t vrf_id)
3c192540
DS
770{
771 struct stream *s;
772
773 s = zclient->obuf;
774 stream_reset(s);
775 zclient_create_header(s, command, vrf_id);
6cd9a93d 776 stream_putc(s, (connected) ? 1 : 0);
ed6cec97 777 stream_putc(s, (resolve_via_def) ? 1 : 0);
027db469 778 stream_putw(s, SAFI_UNICAST);
3c192540
DS
779 stream_putw(s, PREFIX_FAMILY(p));
780 stream_putc(s, p->prefixlen);
781 switch (PREFIX_FAMILY(p)) {
782 case AF_INET:
783 stream_put_in_addr(s, &p->u.prefix4);
784 break;
785 case AF_INET6:
786 stream_put(s, &(p->u.prefix6), 16);
787 break;
788 default:
789 break;
790 }
791 stream_putw_at(s, 0, stream_get_endp(s));
792
793 return zclient_send_message(zclient);
794}
795
d62a17ae 796/*
797 * "xdr_encode"-like interface that allows daemon (client) to send
798 * a message to zebra server for a route that needs to be
799 * added/deleted to the kernel. Info about the route is specified
04772760 800 * by the caller in a struct zapi_route. zapi_route_encode() then writes
d62a17ae 801 * the info down the zclient socket using the stream_* functions.
802 *
803 * The corresponding read ("xdr_decode") function on the server
04772760 804 * side is zapi_route_decode().
d62a17ae 805 *
d62a17ae 806 * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
807 * byte value.
808 *
32f7e999 809 * If ZAPI_MESSAGE_METRIC is set, the metric value is written as a 4
d62a17ae 810 * byte value.
811 *
812 * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 4 byte value
813 *
814 * If ZAPI_MESSAGE_MTU is set, the mtu value is written as a 4 byte value
815 *
816 * XXX: No attention paid to alignment.
817 */
8a3f8f2e
DS
818enum zclient_send_status
819zclient_route_send(uint8_t cmd, struct zclient *zclient, struct zapi_route *api)
657cde12 820{
0e51b4a3 821 if (zapi_route_encode(cmd, zclient->obuf, api) < 0)
8a3f8f2e 822 return ZCLIENT_SEND_FAILURE;
0e51b4a3
RW
823 return zclient_send_message(zclient);
824}
825
3c6e0bd4
SW
826static int zapi_nexthop_labels_cmp(const struct zapi_nexthop *next1,
827 const struct zapi_nexthop *next2)
828{
829 if (next1->label_num > next2->label_num)
830 return 1;
831
832 if (next1->label_num < next2->label_num)
833 return -1;
834
835 return memcmp(next1->labels, next2->labels, next1->label_num);
836}
837
fbaa42f7
HS
838static int zapi_nexthop_srv6_cmp(const struct zapi_nexthop *next1,
839 const struct zapi_nexthop *next2)
cb7775a9 840{
fbaa42f7
HS
841 int ret = 0;
842
843 ret = memcmp(&next1->seg6_segs, &next2->seg6_segs,
844 sizeof(struct in6_addr));
845 if (ret != 0)
846 return ret;
847
cb7775a9
HS
848 if (next1->seg6local_action > next2->seg6local_action)
849 return 1;
850
851 if (next1->seg6local_action < next2->seg6local_action)
852 return -1;
853
854 return memcmp(&next1->seg6local_ctx, &next2->seg6local_ctx,
855 sizeof(struct seg6local_context));
856}
857
3c6e0bd4
SW
858static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
859 const struct zapi_nexthop *next2)
860{
861 int ret = 0;
862
863 if (next1->vrf_id < next2->vrf_id)
864 return -1;
865
866 if (next1->vrf_id > next2->vrf_id)
867 return 1;
868
869 if (next1->type < next2->type)
870 return -1;
871
872 if (next1->type > next2->type)
873 return 1;
874
bd054c1a
DS
875 if (next1->weight < next2->weight)
876 return -1;
877
878 if (next1->weight > next2->weight)
879 return 1;
880
3c6e0bd4
SW
881 switch (next1->type) {
882 case NEXTHOP_TYPE_IPV4:
883 case NEXTHOP_TYPE_IPV6:
884 ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
885 &next2->gate);
886 if (ret != 0)
887 return ret;
888 break;
889 case NEXTHOP_TYPE_IPV4_IFINDEX:
890 case NEXTHOP_TYPE_IPV6_IFINDEX:
891 ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
892 &next2->gate);
893 if (ret != 0)
894 return ret;
895 /* Intentional Fall-Through */
896 case NEXTHOP_TYPE_IFINDEX:
897 if (next1->ifindex < next2->ifindex)
898 return -1;
899
900 if (next1->ifindex > next2->ifindex)
901 return 1;
902 break;
903 case NEXTHOP_TYPE_BLACKHOLE:
904 if (next1->bh_type < next2->bh_type)
905 return -1;
906
907 if (next1->bh_type > next2->bh_type)
908 return 1;
909 break;
910 }
911
38fd3eda
MS
912 if (next1->srte_color < next2->srte_color)
913 return -1;
914 if (next1->srte_color > next2->srte_color)
915 return 1;
916
917 if (CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) ||
918 CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
919
920 if (!CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) &&
921 CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP))
922 return -1;
923
924 if (CHECK_FLAG(next1->flags, NEXTHOP_FLAG_HAS_BACKUP) &&
925 !CHECK_FLAG(next2->flags, NEXTHOP_FLAG_HAS_BACKUP))
926 return 1;
927
928 if (next1->backup_num > 0 || next2->backup_num > 0) {
929
930 if (next1->backup_num < next2->backup_num)
931 return -1;
932
933 if (next1->backup_num > next2->backup_num)
934 return 1;
935
936 ret = memcmp(next1->backup_idx,
937 next2->backup_idx, next1->backup_num);
938 if (ret != 0)
939 return ret;
940 }
941 }
942
3c6e0bd4
SW
943 return 0;
944}
945
946static int zapi_nexthop_cmp(const void *item1, const void *item2)
947{
948 int ret = 0;
949
950 const struct zapi_nexthop *next1 = item1;
951 const struct zapi_nexthop *next2 = item2;
952
953 ret = zapi_nexthop_cmp_no_labels(next1, next2);
954 if (ret != 0)
955 return ret;
956
957 ret = zapi_nexthop_labels_cmp(next1, next2);
cb7775a9
HS
958 if (ret != 0)
959 return ret;
960
fbaa42f7 961 ret = zapi_nexthop_srv6_cmp(next1, next2);
3c6e0bd4
SW
962
963 return ret;
964}
965
966static void zapi_nexthop_group_sort(struct zapi_nexthop *nh_grp,
967 uint16_t nexthop_num)
968{
969 qsort(nh_grp, nexthop_num, sizeof(struct zapi_nexthop),
970 &zapi_nexthop_cmp);
971}
972
68a02e06
MS
973/*
974 * Encode a single zapi nexthop
975 */
976int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
31f937fb 977 uint32_t api_flags, uint32_t api_message)
68a02e06 978{
474aebd9 979 int i, ret = 0;
68a02e06
MS
980 int nh_flags = api_nh->flags;
981
982 stream_putl(s, api_nh->vrf_id);
983 stream_putc(s, api_nh->type);
984
985 /* If needed, set 'labelled nexthop' flag */
986 if (api_nh->label_num > 0) {
987 SET_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_LABEL);
988
989 /* Validate label count */
990 if (api_nh->label_num > MPLS_MAX_LABELS) {
991 ret = -1;
992 goto done;
993 }
994 }
995
0a8881b4 996 /* If present, set 'weight' flag before encoding flags */
bd054c1a
DS
997 if (api_nh->weight)
998 SET_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_WEIGHT);
999
68a02e06
MS
1000 /* Note that we're only encoding a single octet */
1001 stream_putc(s, nh_flags);
1002
1003 switch (api_nh->type) {
1004 case NEXTHOP_TYPE_BLACKHOLE:
1005 stream_putc(s, api_nh->bh_type);
1006 break;
1007 case NEXTHOP_TYPE_IPV4:
68a02e06
MS
1008 case NEXTHOP_TYPE_IPV4_IFINDEX:
1009 stream_put_in_addr(s, &api_nh->gate.ipv4);
1010 stream_putl(s, api_nh->ifindex);
1011 break;
1012 case NEXTHOP_TYPE_IFINDEX:
1013 stream_putl(s, api_nh->ifindex);
1014 break;
1015 case NEXTHOP_TYPE_IPV6:
68a02e06
MS
1016 case NEXTHOP_TYPE_IPV6_IFINDEX:
1017 stream_write(s, (uint8_t *)&api_nh->gate.ipv6,
1018 16);
1019 stream_putl(s, api_nh->ifindex);
1020 break;
1021 }
1022
1023 /* We only encode labels if we have >0 - we use
1024 * the per-nexthop flag above to signal that the count
1025 * is present in the payload.
1026 */
1027 if (api_nh->label_num > 0) {
1028 stream_putc(s, api_nh->label_num);
1029 stream_put(s, &api_nh->labels[0],
1030 api_nh->label_num * sizeof(mpls_label_t));
1031 }
1032
bd054c1a
DS
1033 if (api_nh->weight)
1034 stream_putl(s, api_nh->weight);
1035
68a02e06
MS
1036 /* Router MAC for EVPN routes. */
1037 if (CHECK_FLAG(api_flags, ZEBRA_FLAG_EVPN_ROUTE))
1038 stream_put(s, &(api_nh->rmac),
1039 sizeof(struct ethaddr));
1040
31f937fb
SM
1041 /* Color for Segment Routing TE. */
1042 if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
1043 stream_putl(s, api_nh->srte_color);
1044
018c6488 1045 /* Index of backup nexthop */
474aebd9
MS
1046 if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
1047 /* Validate backup count */
1048 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) {
1049 ret = -1;
1050 goto done;
1051 }
1052
1053 stream_putc(s, api_nh->backup_num);
1054 for (i = 0; i < api_nh->backup_num; i++)
1055 stream_putc(s, api_nh->backup_idx[i]);
1056 }
018c6488 1057
c60c1ade 1058 if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
cb7775a9
HS
1059 stream_putl(s, api_nh->seg6local_action);
1060 stream_write(s, &api_nh->seg6local_ctx,
1061 sizeof(struct seg6local_context));
1062 }
1063
c60c1ade 1064 if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6))
2aa01034
HS
1065 stream_write(s, &api_nh->seg6_segs,
1066 sizeof(struct in6_addr));
1067
68a02e06
MS
1068done:
1069 return ret;
1070}
1071
ac6a9479
HS
1072int zapi_srv6_locator_chunk_encode(struct stream *s,
1073 const struct srv6_locator_chunk *c)
1074{
ac6a9479
HS
1075 stream_putw(s, strlen(c->locator_name));
1076 stream_put(s, c->locator_name, strlen(c->locator_name));
1077 stream_putw(s, c->prefix.prefixlen);
1078 stream_put(s, &c->prefix.prefix, sizeof(c->prefix.prefix));
1079 stream_putc(s, c->block_bits_length);
1080 stream_putc(s, c->node_bits_length);
1081 stream_putc(s, c->function_bits_length);
1082 stream_putc(s, c->argument_bits_length);
1083 return 0;
1084}
1085
1086int zapi_srv6_locator_chunk_decode(struct stream *s,
1087 struct srv6_locator_chunk *c)
1088{
1089 uint16_t len = 0;
1090
05485926
HS
1091 c->prefix.family = AF_INET6;
1092
ac6a9479
HS
1093 STREAM_GETW(s, len);
1094 if (len > SRV6_LOCNAME_SIZE)
1095 goto stream_failure;
1096
1097 STREAM_GET(c->locator_name, s, len);
1098 STREAM_GETW(s, c->prefix.prefixlen);
1099 STREAM_GET(&c->prefix.prefix, s, sizeof(c->prefix.prefix));
1100 STREAM_GETC(s, c->block_bits_length);
1101 STREAM_GETC(s, c->node_bits_length);
1102 STREAM_GETC(s, c->function_bits_length);
1103 STREAM_GETC(s, c->argument_bits_length);
1104 return 0;
1105
1106stream_failure:
1107 return -1;
1108}
1109
15588d7b
HS
1110int zapi_srv6_locator_encode(struct stream *s, const struct srv6_locator *l)
1111{
1112 stream_putw(s, strlen(l->name));
1113 stream_put(s, l->name, strlen(l->name));
1114 stream_putw(s, l->prefix.prefixlen);
1115 stream_put(s, &l->prefix.prefix, sizeof(l->prefix.prefix));
1116 return 0;
1117}
1118
1119int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
1120{
1121 uint16_t len = 0;
1122
1123 STREAM_GETW(s, len);
1124 if (len > SRV6_LOCNAME_SIZE)
1125 goto stream_failure;
1126
1127 STREAM_GET(l->name, s, len);
1128 STREAM_GETW(s, l->prefix.prefixlen);
1129 STREAM_GET(&l->prefix.prefix, s, sizeof(l->prefix.prefix));
1130 l->prefix.family = AF_INET6;
1131 return 0;
1132
1133stream_failure:
1134 return -1;
1135}
1136
5898ce6f 1137static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
2f35a820 1138{
21735352
SW
1139 int i;
1140
c6ce9334
SW
1141 if (cmd != ZEBRA_NHG_DEL && cmd != ZEBRA_NHG_ADD) {
1142 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1143 "%s: Specified zapi NHG command (%d) doesn't exist",
c6ce9334
SW
1144 __func__, cmd);
1145 return -1;
1146 }
2f35a820 1147
5898ce6f
MS
1148 if (api_nhg->nexthop_num >= MULTIPATH_NUM ||
1149 api_nhg->backup_nexthop_num >= MULTIPATH_NUM) {
1150 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1151 "%s: zapi NHG encode with invalid input", __func__);
5898ce6f
MS
1152 return -1;
1153 }
1154
2f35a820 1155 stream_reset(s);
c6ce9334 1156 zclient_create_header(s, cmd, VRF_DEFAULT);
2f35a820 1157
21735352 1158 stream_putw(s, api_nhg->proto);
c6ce9334 1159 stream_putl(s, api_nhg->id);
2f35a820 1160
c6ce9334 1161 if (cmd == ZEBRA_NHG_ADD) {
21735352 1162 /* Nexthops */
c6ce9334
SW
1163 zapi_nexthop_group_sort(api_nhg->nexthops,
1164 api_nhg->nexthop_num);
2f35a820 1165
c6ce9334 1166 stream_putw(s, api_nhg->nexthop_num);
2f35a820 1167
21735352 1168 for (i = 0; i < api_nhg->nexthop_num; i++)
c6ce9334 1169 zapi_nexthop_encode(s, &api_nhg->nexthops[i], 0, 0);
21735352
SW
1170
1171 /* Backup nexthops */
21735352
SW
1172 stream_putw(s, api_nhg->backup_nexthop_num);
1173
1174 for (i = 0; i < api_nhg->backup_nexthop_num; i++)
1175 zapi_nexthop_encode(s, &api_nhg->backup_nexthops[i], 0,
1176 0);
2f35a820
DS
1177 }
1178
1179 stream_putw_at(s, 0, stream_get_endp(s));
c6ce9334
SW
1180
1181 return 0;
2f35a820
DS
1182}
1183
7cfdb485
DS
1184enum zclient_send_status zclient_nhg_send(struct zclient *zclient, int cmd,
1185 struct zapi_nhg *api_nhg)
2f35a820 1186{
21735352
SW
1187 api_nhg->proto = zclient->redist_default;
1188
1189 if (zapi_nhg_encode(zclient->obuf, cmd, api_nhg))
c6ce9334 1190 return -1;
2f35a820 1191
c6ce9334 1192 return zclient_send_message(zclient);
2f35a820
DS
1193}
1194
d7c0a89a 1195int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
0e51b4a3
RW
1196{
1197 struct zapi_nexthop *api_nh;
d62a17ae 1198 int i;
1199 int psize;
d62a17ae 1200
d62a17ae 1201 stream_reset(s);
d62a17ae 1202 zclient_create_header(s, cmd, api->vrf_id);
1203
e4081c0e
RW
1204 if (api->type >= ZEBRA_ROUTE_MAX) {
1205 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1206 "%s: Specified route type (%u) is not a legal value",
15569c58 1207 __func__, api->type);
e4081c0e
RW
1208 return -1;
1209 }
d62a17ae 1210 stream_putc(s, api->type);
e4081c0e 1211
d62a17ae 1212 stream_putw(s, api->instance);
1213 stream_putl(s, api->flags);
31f937fb 1214 stream_putl(s, api->message);
e4081c0e
RW
1215
1216 if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
1217 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1218 "%s: Specified route SAFI (%u) is not a legal value",
15569c58 1219 __func__, api->safi);
e4081c0e
RW
1220 return -1;
1221 }
832d0f56 1222 stream_putc(s, api->safi);
d62a17ae 1223
1224 /* Put prefix information. */
0e51b4a3 1225 stream_putc(s, api->prefix.family);
bb1b9c47
RW
1226 psize = PSIZE(api->prefix.prefixlen);
1227 stream_putc(s, api->prefix.prefixlen);
c4efd0f4 1228 stream_write(s, &api->prefix.u.prefix, psize);
d62a17ae 1229
1230 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
bb1b9c47
RW
1231 psize = PSIZE(api->src_prefix.prefixlen);
1232 stream_putc(s, api->src_prefix.prefixlen);
d7c0a89a 1233 stream_write(s, (uint8_t *)&api->src_prefix.prefix, psize);
d62a17ae 1234 }
1235
27141ea9
DS
1236 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG))
1237 stream_putl(s, api->nhgid);
1238
0e51b4a3 1239 /* Nexthops. */
d62a17ae 1240 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
bb1b9c47
RW
1241 /* limit the number of nexthops if necessary */
1242 if (api->nexthop_num > MULTIPATH_NUM) {
ade6974d 1243 flog_err(
450971aa 1244 EC_LIB_ZAPI_ENCODE,
2dbe669b
DA
1245 "%s: prefix %pFX: can't encode %u nexthops (maximum is %u)",
1246 __func__, &api->prefix, api->nexthop_num,
1247 MULTIPATH_NUM);
a74e593b 1248 return -1;
bb1b9c47
RW
1249 }
1250
018c6488
MS
1251 /* We canonicalize the nexthops by sorting them; this allows
1252 * zebra to resolve the list of nexthops to a nexthop-group
1253 * more efficiently.
1254 */
3c6e0bd4
SW
1255 zapi_nexthop_group_sort(api->nexthops, api->nexthop_num);
1256
b5f79651 1257 stream_putw(s, api->nexthop_num);
d62a17ae 1258
1259 for (i = 0; i < api->nexthop_num; i++) {
bb1b9c47
RW
1260 api_nh = &api->nexthops[i];
1261
52dd3aa4 1262 /* MPLS labels for BGP-LU or Segment Routing */
68a02e06 1263 if (api_nh->label_num > MPLS_MAX_LABELS) {
2dbe669b
DA
1264 flog_err(
1265 EC_LIB_ZAPI_ENCODE,
1266 "%s: prefix %pFX: can't encode %u labels (maximum is %u)",
1267 __func__, &api->prefix,
1268 api_nh->label_num, MPLS_MAX_LABELS);
68a02e06 1269 return -1;
52dd3aa4 1270 }
a317a9b9 1271
31f937fb
SM
1272 if (zapi_nexthop_encode(s, api_nh, api->flags,
1273 api->message)
1274 != 0)
68a02e06 1275 return -1;
d62a17ae 1276 }
1277 }
1278
018c6488
MS
1279 /* Backup nexthops */
1280 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
1281 /* limit the number of nexthops if necessary */
1282 if (api->backup_nexthop_num > MULTIPATH_NUM) {
018c6488
MS
1283 flog_err(
1284 EC_LIB_ZAPI_ENCODE,
2dbe669b
DA
1285 "%s: prefix %pFX: can't encode %u backup nexthops (maximum is %u)",
1286 __func__, &api->prefix, api->backup_nexthop_num,
018c6488
MS
1287 MULTIPATH_NUM);
1288 return -1;
1289 }
1290
1291 /* Note that we do not sort the list of backup nexthops -
1292 * this list is treated as an array and indexed by each
1293 * primary nexthop that is associated with a backup.
1294 */
1295
1296 stream_putw(s, api->backup_nexthop_num);
1297
1298 for (i = 0; i < api->backup_nexthop_num; i++) {
1299 api_nh = &api->backup_nexthops[i];
1300
1301 /* MPLS labels for BGP-LU or Segment Routing */
1302 if (api_nh->label_num > MPLS_MAX_LABELS) {
2dbe669b
DA
1303 flog_err(
1304 EC_LIB_ZAPI_ENCODE,
1305 "%s: prefix %pFX: backup: can't encode %u labels (maximum is %u)",
1306 __func__, &api->prefix,
1307 api_nh->label_num, MPLS_MAX_LABELS);
018c6488
MS
1308 return -1;
1309 }
1310
31f937fb
SM
1311 if (zapi_nexthop_encode(s, api_nh, api->flags,
1312 api->message)
1313 != 0)
018c6488
MS
1314 return -1;
1315 }
1316 }
1317
0e51b4a3 1318 /* Attributes. */
d62a17ae 1319 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
1320 stream_putc(s, api->distance);
1321 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
1322 stream_putl(s, api->metric);
1323 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
1324 stream_putl(s, api->tag);
1325 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
1326 stream_putl(s, api->mtu);
ba1849ef
DS
1327 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID))
1328 stream_putl(s, api->tableid);
d62a17ae 1329
71c4870b 1330 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_OPAQUE)) {
1ae0e1b3
DS
1331 if (api->opaque.length > ZAPI_MESSAGE_OPAQUE_LENGTH) {
1332 flog_err(
1333 EC_LIB_ZAPI_ENCODE,
1334 "%s: opaque length %u is greater than allowed value",
1335 __func__, api->opaque.length);
1336 return -1;
1337 }
71c4870b
DS
1338
1339 stream_putw(s, api->opaque.length);
1340 stream_write(s, api->opaque.data, api->opaque.length);
1341 }
d62a17ae 1342 /* Put length at the first point of the stream. */
1343 stream_putw_at(s, 0, stream_get_endp(s));
1344
0e51b4a3
RW
1345 return 0;
1346}
1347
68a02e06
MS
1348/*
1349 * Decode a single zapi nexthop object
1350 */
2f35a820
DS
1351int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
1352 uint32_t api_flags, uint32_t api_message)
68a02e06 1353{
474aebd9 1354 int i, ret = -1;
68a02e06
MS
1355
1356 STREAM_GETL(s, api_nh->vrf_id);
1357 STREAM_GETC(s, api_nh->type);
1358
1359 /* Note that we're only using a single octet of flags */
1360 STREAM_GETC(s, api_nh->flags);
1361
1362 switch (api_nh->type) {
1363 case NEXTHOP_TYPE_BLACKHOLE:
1364 STREAM_GETC(s, api_nh->bh_type);
1365 break;
1366 case NEXTHOP_TYPE_IPV4:
68a02e06
MS
1367 case NEXTHOP_TYPE_IPV4_IFINDEX:
1368 STREAM_GET(&api_nh->gate.ipv4.s_addr, s,
1369 IPV4_MAX_BYTELEN);
1370 STREAM_GETL(s, api_nh->ifindex);
1371 break;
1372 case NEXTHOP_TYPE_IFINDEX:
1373 STREAM_GETL(s, api_nh->ifindex);
1374 break;
1375 case NEXTHOP_TYPE_IPV6:
68a02e06
MS
1376 case NEXTHOP_TYPE_IPV6_IFINDEX:
1377 STREAM_GET(&api_nh->gate.ipv6, s, 16);
1378 STREAM_GETL(s, api_nh->ifindex);
1379 break;
1380 }
1381
1382 /* MPLS labels for BGP-LU or Segment Routing */
1383 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)) {
1384 STREAM_GETC(s, api_nh->label_num);
1385 if (api_nh->label_num > MPLS_MAX_LABELS) {
1386 flog_err(
1387 EC_LIB_ZAPI_ENCODE,
1388 "%s: invalid number of MPLS labels (%u)",
1389 __func__, api_nh->label_num);
1390 return -1;
1391 }
1392
1393 STREAM_GET(&api_nh->labels[0], s,
1394 api_nh->label_num * sizeof(mpls_label_t));
1395 }
1396
bd054c1a
DS
1397 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
1398 STREAM_GETL(s, api_nh->weight);
1399
68a02e06
MS
1400 /* Router MAC for EVPN routes. */
1401 if (CHECK_FLAG(api_flags, ZEBRA_FLAG_EVPN_ROUTE))
1402 STREAM_GET(&(api_nh->rmac), s,
1403 sizeof(struct ethaddr));
1404
31f937fb
SM
1405 /* Color for Segment Routing TE. */
1406 if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
1407 STREAM_GETL(s, api_nh->srte_color);
1408
018c6488 1409 /* Backup nexthop index */
474aebd9
MS
1410 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
1411 STREAM_GETC(s, api_nh->backup_num);
1412
1413 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS)
1414 return -1;
1415
1416 for (i = 0; i < api_nh->backup_num; i++)
1417 STREAM_GETC(s, api_nh->backup_idx[i]);
1418 }
018c6488 1419
c60c1ade 1420 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
cb7775a9
HS
1421 STREAM_GETL(s, api_nh->seg6local_action);
1422 STREAM_GET(&api_nh->seg6local_ctx, s,
1423 sizeof(struct seg6local_context));
1424 }
1425
c60c1ade 1426 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6))
2aa01034
HS
1427 STREAM_GET(&api_nh->seg6_segs, s,
1428 sizeof(struct in6_addr));
1429
68a02e06
MS
1430 /* Success */
1431 ret = 0;
1432
1433stream_failure:
1434
1435 return ret;
1436}
1437
0e51b4a3
RW
1438int zapi_route_decode(struct stream *s, struct zapi_route *api)
1439{
1440 struct zapi_nexthop *api_nh;
1441 int i;
1442
1443 memset(api, 0, sizeof(*api));
1444
1445 /* Type, flags, message. */
ec93aa12 1446 STREAM_GETC(s, api->type);
e4081c0e 1447 if (api->type >= ZEBRA_ROUTE_MAX) {
450971aa 1448 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1449 "%s: Specified route type: %d is not a legal value",
15569c58 1450 __func__, api->type);
ec93aa12
DS
1451 return -1;
1452 }
1453
1454 STREAM_GETW(s, api->instance);
1455 STREAM_GETL(s, api->flags);
31f937fb 1456 STREAM_GETL(s, api->message);
832d0f56 1457 STREAM_GETC(s, api->safi);
e4081c0e
RW
1458 if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
1459 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1460 "%s: Specified route SAFI (%u) is not a legal value",
15569c58 1461 __func__, api->safi);
e4081c0e
RW
1462 return -1;
1463 }
0e51b4a3
RW
1464
1465 /* Prefix. */
ec93aa12
DS
1466 STREAM_GETC(s, api->prefix.family);
1467 STREAM_GETC(s, api->prefix.prefixlen);
0e51b4a3
RW
1468 switch (api->prefix.family) {
1469 case AF_INET:
936fbaef 1470 if (api->prefix.prefixlen > IPV4_MAX_BITLEN) {
ade6974d 1471 flog_err(
450971aa 1472 EC_LIB_ZAPI_ENCODE,
ade6974d 1473 "%s: V4 prefixlen is %d which should not be more than 32",
15569c58 1474 __func__, api->prefix.prefixlen);
ec93aa12
DS
1475 return -1;
1476 }
0e51b4a3
RW
1477 break;
1478 case AF_INET6:
f4d81e55 1479 if (api->prefix.prefixlen > IPV6_MAX_BITLEN) {
ade6974d 1480 flog_err(
450971aa 1481 EC_LIB_ZAPI_ENCODE,
ade6974d 1482 "%s: v6 prefixlen is %d which should not be more than 128",
15569c58 1483 __func__, api->prefix.prefixlen);
ec93aa12
DS
1484 return -1;
1485 }
0e51b4a3 1486 break;
ec93aa12 1487 default:
450971aa 1488 flog_err(EC_LIB_ZAPI_ENCODE,
15569c58
DA
1489 "%s: Specified family %d is not v4 or v6", __func__,
1490 api->prefix.family);
ec93aa12 1491 return -1;
0e51b4a3 1492 }
ec93aa12
DS
1493 STREAM_GET(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen));
1494
0e51b4a3
RW
1495 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
1496 api->src_prefix.family = AF_INET6;
ec93aa12 1497 STREAM_GETC(s, api->src_prefix.prefixlen);
f4d81e55 1498 if (api->src_prefix.prefixlen > IPV6_MAX_BITLEN) {
ade6974d 1499 flog_err(
450971aa 1500 EC_LIB_ZAPI_ENCODE,
ade6974d 1501 "%s: SRC Prefix prefixlen received: %d is too large",
15569c58 1502 __func__, api->src_prefix.prefixlen);
ec93aa12
DS
1503 return -1;
1504 }
1505 STREAM_GET(&api->src_prefix.prefix, s,
0e51b4a3
RW
1506 PSIZE(api->src_prefix.prefixlen));
1507
1508 if (api->prefix.family != AF_INET6
ec93aa12 1509 || api->src_prefix.prefixlen == 0) {
ade6974d 1510 flog_err(
450971aa 1511 EC_LIB_ZAPI_ENCODE,
ade6974d 1512 "%s: SRC prefix specified in some manner that makes no sense",
15569c58 1513 __func__);
ec93aa12
DS
1514 return -1;
1515 }
0e51b4a3
RW
1516 }
1517
27141ea9
DS
1518 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG))
1519 STREAM_GETL(s, api->nhgid);
1520
0e51b4a3
RW
1521 /* Nexthops. */
1522 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
ec93aa12 1523 STREAM_GETW(s, api->nexthop_num);
0e51b4a3 1524 if (api->nexthop_num > MULTIPATH_NUM) {
450971aa 1525 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
1526 "%s: invalid number of nexthops (%u)",
1527 __func__, api->nexthop_num);
0e51b4a3
RW
1528 return -1;
1529 }
1530
1531 for (i = 0; i < api->nexthop_num; i++) {
1532 api_nh = &api->nexthops[i];
1533
31f937fb
SM
1534 if (zapi_nexthop_decode(s, api_nh, api->flags,
1535 api->message)
1536 != 0)
68a02e06 1537 return -1;
0e51b4a3
RW
1538 }
1539 }
1540
018c6488
MS
1541 /* Backup nexthops. */
1542 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
1543 STREAM_GETW(s, api->backup_nexthop_num);
1544 if (api->backup_nexthop_num > MULTIPATH_NUM) {
1545 flog_err(EC_LIB_ZAPI_ENCODE,
1546 "%s: invalid number of backup nexthops (%u)",
1547 __func__, api->backup_nexthop_num);
1548 return -1;
1549 }
1550
1551 for (i = 0; i < api->backup_nexthop_num; i++) {
1552 api_nh = &api->backup_nexthops[i];
1553
31f937fb
SM
1554 if (zapi_nexthop_decode(s, api_nh, api->flags,
1555 api->message)
1556 != 0)
018c6488
MS
1557 return -1;
1558 }
1559 }
1560
0e51b4a3
RW
1561 /* Attributes. */
1562 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
ec93aa12 1563 STREAM_GETC(s, api->distance);
0e51b4a3 1564 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
ec93aa12 1565 STREAM_GETL(s, api->metric);
0e51b4a3 1566 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
ec93aa12 1567 STREAM_GETL(s, api->tag);
0e51b4a3 1568 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
ec93aa12 1569 STREAM_GETL(s, api->mtu);
ba1849ef
DS
1570 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID))
1571 STREAM_GETL(s, api->tableid);
0e51b4a3 1572
71c4870b
DS
1573 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_OPAQUE)) {
1574 STREAM_GETW(s, api->opaque.length);
1ae0e1b3
DS
1575 if (api->opaque.length > ZAPI_MESSAGE_OPAQUE_LENGTH) {
1576 flog_err(
1577 EC_LIB_ZAPI_ENCODE,
1578 "%s: opaque length %u is greater than allowed value",
1579 __func__, api->opaque.length);
1580 return -1;
1581 }
71c4870b
DS
1582
1583 STREAM_GET(api->opaque.data, s, api->opaque.length);
1584 }
1585
0e51b4a3 1586 return 0;
6a2b0d9a
RW
1587stream_failure:
1588 return -1;
657cde12
DS
1589}
1590
0313523d
FR
1591static void zapi_encode_prefix(struct stream *s, struct prefix *p,
1592 uint8_t family)
0031a6bb
PG
1593{
1594 struct prefix any;
1595
1596 if (!p) {
1597 memset(&any, 0, sizeof(any));
1598 any.family = family;
1599 p = &any;
1600 }
1601
1602 stream_putc(s, p->family);
1603 stream_putc(s, p->prefixlen);
1604 stream_put(s, &p->u.prefix, prefix_blen(p));
1605}
1606
0313523d 1607int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule)
0031a6bb
PG
1608{
1609 stream_reset(s);
1610 zclient_create_header(s, cmd, zrule->vrf_id);
1611
1612 /*
1613 * We are sending one item at a time at the moment
1614 */
1615 stream_putl(s, 1);
1616
1617 stream_putl(s, zrule->seq);
1618 stream_putl(s, zrule->priority);
1619 stream_putl(s, zrule->unique);
1620
1621 zapi_encode_prefix(s, &(zrule->filter.src_ip),
1622 zrule->filter.src_ip.family);
0313523d 1623 stream_putw(s, zrule->filter.src_port); /* src port */
0031a6bb
PG
1624 zapi_encode_prefix(s, &(zrule->filter.dst_ip),
1625 zrule->filter.src_ip.family);
0313523d
FR
1626 stream_putw(s, zrule->filter.dst_port); /* dst port */
1627 stream_putw(s, zrule->filter.fwmark); /* fwmark */
0031a6bb
PG
1628
1629 stream_putl(s, zrule->action.table);
58a1d249 1630 stream_put(s, zrule->ifname, INTERFACE_NAMSIZ);
0031a6bb
PG
1631
1632 /* Put length at the first point of the stream. */
1633 stream_putw_at(s, 0, stream_get_endp(s));
1634
1635 return 0;
1636}
1637
2f35a820
DS
1638bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id,
1639 enum zapi_nhg_notify_owner *note)
1640{
2c7819b9 1641 uint32_t read_id;
2f35a820 1642
2f35a820 1643 STREAM_GET(note, s, sizeof(*note));
2c7819b9 1644 STREAM_GETL(s, read_id);
2f35a820
DS
1645
1646 *id = read_id;
1647
1648 return true;
1649
1650stream_failure:
1651 return false;
1652}
1653
7ea7b86e 1654bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
28610f7e 1655 uint32_t *tableid,
77b38a4a
S
1656 enum zapi_route_notify_owner *note,
1657 afi_t *afi, safi_t *safi)
7ea7b86e 1658{
7a1eb44b 1659 uint32_t t;
77b38a4a
S
1660 afi_t afi_val;
1661 safi_t safi_val;
7a1eb44b 1662
7ea7b86e
DS
1663 STREAM_GET(note, s, sizeof(*note));
1664
1665 STREAM_GETC(s, p->family);
1666 STREAM_GETC(s, p->prefixlen);
996c9314 1667 STREAM_GET(&p->u.prefix, s, prefix_blen(p));
7a1eb44b 1668 STREAM_GETL(s, t);
77b38a4a
S
1669 STREAM_GETC(s, afi_val);
1670 STREAM_GETC(s, safi_val);
7a1eb44b
DS
1671
1672 *tableid = t;
7ea7b86e 1673
77b38a4a
S
1674 if (afi)
1675 *afi = afi_val;
1676 if (safi)
1677 *safi = safi_val;
1678
7ea7b86e
DS
1679 return true;
1680
1681stream_failure:
1682 return false;
1683}
1684
b6c5d343 1685bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
58a1d249 1686 uint32_t *priority, uint32_t *unique, char *ifname,
b6c5d343
DS
1687 enum zapi_rule_notify_owner *note)
1688{
1689 uint32_t prio, seq, uni;
b6c5d343
DS
1690
1691 STREAM_GET(note, s, sizeof(*note));
1692
1693 STREAM_GETL(s, seq);
1694 STREAM_GETL(s, prio);
1695 STREAM_GETL(s, uni);
58a1d249 1696 STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
b6c5d343
DS
1697
1698 if (zclient_debug)
58a1d249 1699 zlog_debug("%s: %u %u %u %s", __func__, seq, prio, uni, ifname);
b6c5d343
DS
1700 *seqno = seq;
1701 *priority = prio;
1702 *unique = uni;
b6c5d343
DS
1703
1704 return true;
1705
1706stream_failure:
1707 return false;
1708}
1709
0313523d
FR
1710bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique,
1711 enum zapi_ipset_notify_owner *note)
425bdd6b
PG
1712{
1713 uint32_t uni;
ef524230 1714 uint16_t notew;
425bdd6b 1715
ef524230 1716 STREAM_GETW(s, notew);
425bdd6b
PG
1717
1718 STREAM_GETL(s, uni);
1719
1720 if (zclient_debug)
15569c58 1721 zlog_debug("%s: %u", __func__, uni);
425bdd6b 1722 *unique = uni;
ef524230 1723 *note = (enum zapi_ipset_notify_owner)notew;
425bdd6b
PG
1724 return true;
1725
1726stream_failure:
1727 return false;
1728}
1729
0313523d
FR
1730bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
1731 char *ipset_name,
1732 enum zapi_ipset_entry_notify_owner *note)
425bdd6b
PG
1733{
1734 uint32_t uni;
ef524230 1735 uint16_t notew;
425bdd6b 1736
ef524230 1737 STREAM_GETW(s, notew);
425bdd6b
PG
1738
1739 STREAM_GETL(s, uni);
1740
0313523d 1741 STREAM_GET(ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
425bdd6b
PG
1742
1743 if (zclient_debug)
15569c58 1744 zlog_debug("%s: %u", __func__, uni);
425bdd6b 1745 *unique = uni;
ef524230 1746 *note = (enum zapi_ipset_entry_notify_owner)notew;
425bdd6b
PG
1747
1748 return true;
1749
1750stream_failure:
1751 return false;
1752}
1753
c16a0a62
PG
1754bool zapi_iptable_notify_decode(struct stream *s,
1755 uint32_t *unique,
1756 enum zapi_iptable_notify_owner *note)
1757{
1758 uint32_t uni;
ef524230 1759 uint16_t notew;
c16a0a62 1760
ef524230 1761 STREAM_GETW(s, notew);
c16a0a62
PG
1762
1763 STREAM_GETL(s, uni);
1764
1765 if (zclient_debug)
15569c58 1766 zlog_debug("%s: %u", __func__, uni);
c16a0a62 1767 *unique = uni;
ef524230 1768 *note = (enum zapi_iptable_notify_owner)notew;
c16a0a62
PG
1769
1770 return true;
1771
1772stream_failure:
1773 return false;
1774}
1775
e4a1ec74 1776struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
4a749e2c
DS
1777{
1778 struct nexthop *n = nexthop_new();
1779
1780 n->type = znh->type;
4a7371e9 1781 n->vrf_id = znh->vrf_id;
4a749e2c
DS
1782 n->ifindex = znh->ifindex;
1783 n->gate = znh->gate;
31f937fb 1784 n->srte_color = znh->srte_color;
4a749e2c
DS
1785
1786 /*
960035b2 1787 * This function currently handles labels
4a749e2c 1788 */
960035b2
PZ
1789 if (znh->label_num) {
1790 nexthop_add_labels(n, ZEBRA_LSP_NONE, znh->label_num,
0313523d 1791 znh->labels);
960035b2 1792 }
4a749e2c 1793
0a8881b4
MS
1794 if (CHECK_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
1795 SET_FLAG(n->flags, NEXTHOP_FLAG_HAS_BACKUP);
474aebd9
MS
1796 n->backup_num = znh->backup_num;
1797 memcpy(n->backup_idx, znh->backup_idx, n->backup_num);
0a8881b4
MS
1798 }
1799
eab0f8f0
HS
1800 if (znh->seg6local_action != ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
1801 nexthop_add_srv6_seg6local(n, znh->seg6local_action,
1802 &znh->seg6local_ctx);
cb7775a9 1803
eab0f8f0
HS
1804 if (!sid_zero(&znh->seg6_segs))
1805 nexthop_add_srv6_seg6(n, &znh->seg6_segs);
2aa01034 1806
4a749e2c
DS
1807 return n;
1808}
1809
68a02e06
MS
1810/*
1811 * Convert nexthop to zapi nexthop
1812 */
1813int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
1814 const struct nexthop *nh)
1815{
1816 int i;
1817
1818 memset(znh, 0, sizeof(*znh));
1819
1820 znh->type = nh->type;
1821 znh->vrf_id = nh->vrf_id;
1df3b1dc 1822 znh->weight = nh->weight;
68a02e06
MS
1823 znh->ifindex = nh->ifindex;
1824 znh->gate = nh->gate;
1825
e90284d7
SW
1826 if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK))
1827 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
1828
68a02e06 1829 if (nh->nh_label && (nh->nh_label->num_labels > 0)) {
018c6488
MS
1830
1831 /* Validate */
1832 if (nh->nh_label->num_labels > MPLS_MAX_LABELS)
1833 return -1;
1834
68a02e06
MS
1835 for (i = 0; i < nh->nh_label->num_labels; i++)
1836 znh->labels[i] = nh->nh_label->label[i];
1837
1838 znh->label_num = i;
1839 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
1840 }
1841
0a8881b4 1842 if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
474aebd9
MS
1843 if (nh->backup_num > NEXTHOP_MAX_BACKUPS)
1844 return -1;
1845
0a8881b4 1846 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
474aebd9
MS
1847 znh->backup_num = nh->backup_num;
1848 memcpy(znh->backup_idx, nh->backup_idx, znh->backup_num);
0a8881b4
MS
1849 }
1850
eab0f8f0
HS
1851 if (nh->nh_srv6) {
1852 if (nh->nh_srv6->seg6local_action !=
1853 ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) {
c60c1ade 1854 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
eab0f8f0
HS
1855 znh->seg6local_action = nh->nh_srv6->seg6local_action;
1856 memcpy(&znh->seg6local_ctx,
1857 &nh->nh_srv6->seg6local_ctx,
1858 sizeof(struct seg6local_context));
1859 }
cb7775a9 1860
c60c1ade
HS
1861 if (!sid_zero(&nh->nh_srv6->seg6_segs)) {
1862 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
eab0f8f0
HS
1863 memcpy(&znh->seg6_segs, &nh->nh_srv6->seg6_segs,
1864 sizeof(struct in6_addr));
c60c1ade 1865 }
eab0f8f0 1866 }
2aa01034 1867
68a02e06
MS
1868 return 0;
1869}
1870
0a8881b4
MS
1871/*
1872 * Wrapper that converts backup nexthop
1873 */
1874int zapi_backup_nexthop_from_nexthop(struct zapi_nexthop *znh,
1875 const struct nexthop *nh)
1876{
1877 int ret;
1878
1879 /* Ensure that zapi flags are correct: backups don't have backups */
1880 ret = zapi_nexthop_from_nexthop(znh, nh);
1881 if (ret == 0)
1882 UNSET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
1883
1884 return ret;
1885}
1886
ae076fc2
MS
1887/*
1888 * Format some info about a zapi nexthop, for debug or logging.
1889 */
1890const char *zapi_nexthop2str(const struct zapi_nexthop *znh, char *buf,
1891 int bufsize)
1892{
1893 char tmp[INET6_ADDRSTRLEN];
1894
1895 switch (znh->type) {
1896 case NEXTHOP_TYPE_IFINDEX:
1897 snprintf(buf, bufsize, "if %u", znh->ifindex);
1898 break;
1899 case NEXTHOP_TYPE_IPV4:
1900 case NEXTHOP_TYPE_IPV4_IFINDEX:
1901 inet_ntop(AF_INET, &znh->gate.ipv4, tmp, sizeof(tmp));
1902 snprintf(buf, bufsize, "%s if %u", tmp, znh->ifindex);
1903 break;
1904 case NEXTHOP_TYPE_IPV6:
1905 case NEXTHOP_TYPE_IPV6_IFINDEX:
1906 inet_ntop(AF_INET6, &znh->gate.ipv6, tmp, sizeof(tmp));
1907 snprintf(buf, bufsize, "%s if %u", tmp, znh->ifindex);
1908 break;
1909 case NEXTHOP_TYPE_BLACKHOLE:
1910 snprintf(buf, bufsize, "blackhole");
1911 break;
1912 default:
1913 snprintf(buf, bufsize, "unknown");
1914 break;
1915 }
1916
1917 return buf;
1918}
1919
68a02e06
MS
1920/*
1921 * Decode the nexthop-tracking update message
1922 */
4a749e2c
DS
1923bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
1924{
1925 uint32_t i;
1926
1927 memset(nhr, 0, sizeof(*nhr));
1928
31f937fb 1929 STREAM_GETL(s, nhr->message);
027db469 1930 STREAM_GETW(s, nhr->safi);
4a749e2c
DS
1931 STREAM_GETW(s, nhr->prefix.family);
1932 STREAM_GETC(s, nhr->prefix.prefixlen);
996c9314 1933 switch (nhr->prefix.family) {
4a749e2c
DS
1934 case AF_INET:
1935 STREAM_GET(&nhr->prefix.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
1936 break;
1937 case AF_INET6:
1938 STREAM_GET(&nhr->prefix.u.prefix6, s, IPV6_MAX_BYTELEN);
1939 break;
1940 default:
1941 break;
1942 }
31f937fb
SM
1943 if (CHECK_FLAG(nhr->message, ZAPI_MESSAGE_SRTE))
1944 STREAM_GETL(s, nhr->srte_color);
4a749e2c 1945
05dd5aaf
DS
1946 STREAM_GETC(s, nhr->type);
1947 STREAM_GETW(s, nhr->instance);
4a749e2c
DS
1948 STREAM_GETC(s, nhr->distance);
1949 STREAM_GETL(s, nhr->metric);
1950 STREAM_GETC(s, nhr->nexthop_num);
1951
996c9314 1952 for (i = 0; i < nhr->nexthop_num; i++) {
31f937fb 1953 if (zapi_nexthop_decode(s, &(nhr->nexthops[i]), 0, 0) != 0)
2fec17cd 1954 return false;
4a749e2c
DS
1955 }
1956
1957 return true;
1958stream_failure:
1959 return false;
1960}
1961
9ab0b2a3
SW
1962bool zapi_error_decode(struct stream *s, enum zebra_error_types *error)
1963{
1964 memset(error, 0, sizeof(*error));
1965
1966 STREAM_GET(error, s, sizeof(*error));
1967
1968 if (zclient_debug)
1969 zlog_debug("%s: type: %s", __func__,
1970 zebra_error_type2str(*error));
1971
1972 return true;
1973stream_failure:
1974 return false;
1975}
1976
d62a17ae 1977/*
0a589359 1978 * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
1979 * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
d62a17ae 1980 * then set/unset redist[type] in the client handle (a struct zserv) for the
0a589359 1981 * sending client
1982 */
7cfdb485
DS
1983enum zclient_send_status
1984zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi,
1985 int type, unsigned short instance, vrf_id_t vrf_id)
718e3744 1986{
d62a17ae 1987 struct stream *s;
1988
1989 s = zclient->obuf;
1990 stream_reset(s);
1991
1992 zclient_create_header(s, command, vrf_id);
1993 stream_putc(s, afi);
1994 stream_putc(s, type);
1995 stream_putw(s, instance);
1996
1997 stream_putw_at(s, 0, stream_get_endp(s));
1998
1999 return zclient_send_message(zclient);
718e3744 2000}
2001
7cfdb485
DS
2002enum zclient_send_status
2003zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi,
2004 vrf_id_t vrf_id)
49db7a7b
RW
2005{
2006 struct stream *s;
2007
2008 s = zclient->obuf;
2009 stream_reset(s);
2010
2011 zclient_create_header(s, command, vrf_id);
2012 stream_putc(s, afi);
2013
2014 stream_putw_at(s, 0, stream_get_endp(s));
2015
2016 return zclient_send_message(zclient);
2017}
2018
77b38a4a
S
2019/* Send route notify request to zebra */
2020int zebra_route_notify_send(int command, struct zclient *zclient, bool set)
2021{
2022 struct stream *s;
2023
2024 s = zclient->obuf;
2025 stream_reset(s);
2026
2027 zclient_create_header(s, command, 0);
2028 stream_putc(s, !!set);
2029
2030 stream_putw_at(s, 0, stream_get_endp(s));
2031
2032 return zclient_send_message(zclient);
2033}
2034
d9178828 2035/* Get prefix in ZServ format; family should be filled in on prefix */
efc7191b 2036static int zclient_stream_get_prefix(struct stream *s, struct prefix *p)
d9178828 2037{
d62a17ae 2038 size_t plen = prefix_blen(p);
d7c0a89a 2039 uint8_t c;
d62a17ae 2040 p->prefixlen = 0;
2041
2042 if (plen == 0)
efc7191b 2043 return -1;
d62a17ae 2044
efc7191b 2045 STREAM_GET(&p->u.prefix, s, plen);
ec93aa12 2046 STREAM_GETC(s, c);
d62a17ae 2047 p->prefixlen = MIN(plen * 8, c);
ec93aa12 2048
efc7191b 2049 return 0;
ec93aa12 2050stream_failure:
efc7191b 2051 return -1;
d9178828
PJ
2052}
2053
18a6dce6 2054/* Router-id update from zebra daemon. */
efc7191b 2055int zebra_router_id_update_read(struct stream *s, struct prefix *rid)
18a6dce6 2056{
d62a17ae 2057 /* Fetch interface address. */
ec93aa12 2058 STREAM_GETC(s, rid->family);
d62a17ae 2059
efc7191b 2060 return zclient_stream_get_prefix(s, rid);
ec93aa12
DS
2061
2062stream_failure:
efc7191b 2063 return -1;
18a6dce6 2064}
2065
718e3744 2066/* Interface addition from zebra daemon. */
d62a17ae 2067/*
0a589359 2068 * The format of the message sent with type ZEBRA_INTERFACE_ADD or
2069 * ZEBRA_INTERFACE_DELETE from zebra to the client is:
2070 * 0 1 2 3
2071 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
0a589359 2072 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2073 * | ifname |
2074 * | |
2075 * | |
2076 * | |
2077 * | |
2078 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2079 * | ifindex |
2080 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2081 * | status |
0a589359 2082 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2083 * | if_flags |
c77d4546 2084 * | |
0a589359 2085 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2086 * | metric |
2087 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2d7f0d76
DS
2088 * | speed |
2089 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2090 * | ifmtu |
2091 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2092 * | ifmtu6 |
2093 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2094 * | bandwidth |
2095 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53e60e5c
QY
2096 * | parent ifindex |
2097 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2098 * | Link Layer Type |
0a589359 2099 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2100 * | Harware Address Length |
0a589359 2101 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2102 * | Hardware Address if HW lenght different from 0 |
2103 * | ... max INTERFACE_HWADDR_MAX |
0a589359 2104 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2105 * | Link_params? | Whether a link-params follows: 1 or 0.
0a589359 2106 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2107 * | Link_params 0 or 1 INTERFACE_LINK_PARAMS_SIZE sized |
2108 * | .... (struct if_link_params). |
0a589359 2109 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2110 */
2111
efc7191b 2112static int zclient_vrf_add(struct zclient *zclient, vrf_id_t vrf_id)
1892f15e 2113{
d62a17ae 2114 struct vrf *vrf;
f17a9d0a 2115 char vrfname_tmp[VRF_NAMSIZ + 1] = {};
d62a17ae 2116 struct vrf_data data;
1892f15e 2117
efc7191b 2118 STREAM_GET(&data, zclient->ibuf, sizeof(struct vrf_data));
d62a17ae 2119 /* Read interface name. */
efc7191b 2120 STREAM_GET(vrfname_tmp, zclient->ibuf, VRF_NAMSIZ);
1892f15e 2121
f17a9d0a
QY
2122 if (strlen(vrfname_tmp) == 0)
2123 goto stream_failure;
2124
cff0de12 2125 /* Lookup/create vrf by name, then vrf_id. */
d62a17ae 2126 vrf = vrf_get(vrf_id, vrfname_tmp);
f17a9d0a 2127
cff0de12
QY
2128 /* If there's already a VRF with this name, don't create vrf */
2129 if (!vrf)
f17a9d0a
QY
2130 return 0;
2131
4691b65a
PG
2132 vrf->data.l.table_id = data.l.table_id;
2133 memcpy(vrf->data.l.netns_name, data.l.netns_name, NS_NAMSIZ);
4931a365
PG
2134 /* overwrite default vrf */
2135 if (vrf_id == VRF_DEFAULT)
4fe52e76 2136 vrf_set_default_name(vrfname_tmp, false);
d62a17ae 2137 vrf_enable(vrf);
efc7191b
QY
2138
2139 return 0;
2140stream_failure:
2141 return -1;
1892f15e
DS
2142}
2143
d62a17ae 2144static void zclient_vrf_delete(struct zclient *zclient, vrf_id_t vrf_id)
1892f15e 2145{
d62a17ae 2146 struct vrf *vrf;
1892f15e 2147
d62a17ae 2148 /* Lookup vrf by vrf_id. */
2149 vrf = vrf_lookup_by_id(vrf_id);
1892f15e 2150
d62a17ae 2151 /*
2152 * If a routing protocol doesn't know about a
2153 * vrf that is about to be deleted. There is
2154 * no point in attempting to delete it.
2155 */
2156 if (!vrf)
2157 return;
beef1990 2158
d62a17ae 2159 vrf_delete(vrf);
1892f15e
DS
2160}
2161
efc7191b 2162static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id)
718e3744 2163{
d62a17ae 2164 struct interface *ifp;
b98edbcc 2165 char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
ef7bd2a3 2166 struct stream *s = zclient->ibuf;
f60a1188 2167 struct vrf *vrf;
718e3744 2168
d62a17ae 2169 /* Read interface name. */
efc7191b 2170 STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
718e3744 2171
d62a17ae 2172 /* Lookup/create interface by name. */
f60a1188
IR
2173 vrf = vrf_lookup_by_id(vrf_id);
2174 if (!vrf) {
229d0d4e
QY
2175 zlog_debug(
2176 "Rx'd interface add from Zebra, but VRF %u does not exist",
2177 vrf_id);
2178 return -1;
2179 }
2180
f60a1188 2181 ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name);
a41c4e1b 2182
d62a17ae 2183 zebra_interface_if_set_value(s, ifp);
718e3744 2184
ef7bd2a3 2185 if_new_via_zapi(ifp);
efc7191b
QY
2186
2187 return 0;
2188stream_failure:
2189 return -1;
718e3744 2190}
2191
d62a17ae 2192/*
0a589359 2193 * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN)
2194 * from zebra server. The format of this message is the same as
ef7bd2a3
DS
2195 * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE,
2196 * except that no sockaddr_dl is sent at the tail of the message.
0a589359 2197 */
d62a17ae 2198struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t vrf_id)
718e3744 2199{
d62a17ae 2200 struct interface *ifp;
f17a9d0a 2201 char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
d62a17ae 2202
2203 /* Read interface name. */
efc7191b 2204 STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
d62a17ae 2205
2206 /* Lookup this by interface index. */
a36898e7 2207 ifp = if_lookup_by_name(ifname_tmp, vrf_id);
d62a17ae 2208 if (ifp == NULL) {
450971aa 2209 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
2210 "INTERFACE_STATE: Cannot find IF %s in VRF %d",
2211 ifname_tmp, vrf_id);
d62a17ae 2212 return NULL;
2213 }
2214
2215 zebra_interface_if_set_value(s, ifp);
2216
2217 return ifp;
efc7191b
QY
2218stream_failure:
2219 return NULL;
718e3744 2220}
2221
3c3c3252
DS
2222static void zclient_interface_delete(struct zclient *zclient, vrf_id_t vrf_id)
2223{
2224 struct interface *ifp;
2225 struct stream *s = zclient->ibuf;
2226
2227 ifp = zebra_interface_state_read(s, vrf_id);
2228
2229 if (ifp == NULL)
2230 return;
2231
2232 if_destroy_via_zapi(ifp);
2233 return;
2234}
2235
ddbf3e60
DS
2236static void zclient_interface_up(struct zclient *zclient, vrf_id_t vrf_id)
2237{
2238 struct interface *ifp;
2239 struct stream *s = zclient->ibuf;
2240
2241 ifp = zebra_interface_state_read(s, vrf_id);
2242
2243 if (!ifp)
2244 return;
2245
2246 if_up_via_zapi(ifp);
2247}
2248
b0b69e59
DS
2249static void zclient_interface_down(struct zclient *zclient, vrf_id_t vrf_id)
2250{
2251 struct interface *ifp;
2252 struct stream *s = zclient->ibuf;
2253
2254 ifp = zebra_interface_state_read(s, vrf_id);
2255
2256 if (!ifp)
2257 return;
2258
2259 if_down_via_zapi(ifp);
2260}
2261
9ab0b2a3
SW
2262static void zclient_handle_error(ZAPI_CALLBACK_ARGS)
2263{
2264 enum zebra_error_types error;
2265 struct stream *s = zclient->ibuf;
2266
2267 zapi_error_decode(s, &error);
2268
2269 if (zclient->handle_error)
2270 (*zclient->handle_error)(error);
2271}
2272
efc7191b 2273static int link_params_set_value(struct stream *s, struct if_link_params *iflp)
16f1b9ee
OD
2274{
2275
d62a17ae 2276 if (iflp == NULL)
efc7191b 2277 return -1;
d62a17ae 2278
efc7191b
QY
2279 uint32_t bwclassnum;
2280
2281 STREAM_GETL(s, iflp->lp_status);
2282 STREAM_GETL(s, iflp->te_metric);
2283 STREAM_GETF(s, iflp->max_bw);
2284 STREAM_GETF(s, iflp->max_rsv_bw);
2285 STREAM_GETL(s, bwclassnum);
d62a17ae 2286 {
2287 unsigned int i;
2288 for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++)
efc7191b 2289 STREAM_GETF(s, iflp->unrsv_bw[i]);
d62a17ae 2290 if (i < bwclassnum)
1c50c1c0
QY
2291 flog_err(
2292 EC_LIB_ZAPI_MISSMATCH,
3efd0893 2293 "%s: received %d > %d (MAX_CLASS_TYPE) bw entries - outdated library?",
1c50c1c0 2294 __func__, bwclassnum, MAX_CLASS_TYPE);
d62a17ae 2295 }
efc7191b
QY
2296 STREAM_GETL(s, iflp->admin_grp);
2297 STREAM_GETL(s, iflp->rmt_as);
d62a17ae 2298 iflp->rmt_ip.s_addr = stream_get_ipv4(s);
2299
efc7191b
QY
2300 STREAM_GETL(s, iflp->av_delay);
2301 STREAM_GETL(s, iflp->min_delay);
2302 STREAM_GETL(s, iflp->max_delay);
2303 STREAM_GETL(s, iflp->delay_var);
2304
2305 STREAM_GETF(s, iflp->pkt_loss);
2306 STREAM_GETF(s, iflp->res_bw);
2307 STREAM_GETF(s, iflp->ava_bw);
2308 STREAM_GETF(s, iflp->use_bw);
d62a17ae 2309
efc7191b
QY
2310 return 0;
2311stream_failure:
2312 return -1;
16f1b9ee
OD
2313}
2314
edc12762 2315struct interface *zebra_interface_link_params_read(struct stream *s,
0b4124c1
KS
2316 vrf_id_t vrf_id,
2317 bool *changed)
16f1b9ee 2318{
d62a17ae 2319 struct if_link_params *iflp;
0b4124c1 2320 struct if_link_params iflp_copy;
d62a17ae 2321 ifindex_t ifindex;
0b4124c1 2322 bool params_changed = false;
c28e5b2a 2323
efc7191b 2324 STREAM_GETL(s, ifindex);
16f1b9ee 2325
a36898e7 2326 struct interface *ifp = if_lookup_by_index(ifindex, vrf_id);
16f1b9ee 2327
d62a17ae 2328 if (ifp == NULL) {
450971aa 2329 flog_err(EC_LIB_ZAPI_ENCODE,
1c50c1c0
QY
2330 "%s: unknown ifindex %u, shouldn't happen", __func__,
2331 ifindex);
d62a17ae 2332 return NULL;
2333 }
16f1b9ee 2334
0b4124c1
KS
2335 if (ifp->link_params == NULL)
2336 params_changed = true;
2337
d62a17ae 2338 if ((iflp = if_link_params_get(ifp)) == NULL)
2339 return NULL;
16f1b9ee 2340
0b4124c1
KS
2341 memcpy(&iflp_copy, iflp, sizeof(iflp_copy));
2342
efc7191b
QY
2343 if (link_params_set_value(s, iflp) != 0)
2344 goto stream_failure;
16f1b9ee 2345
0b4124c1
KS
2346 if (memcmp(&iflp_copy, iflp, sizeof(iflp_copy)))
2347 params_changed = true;
2348
2349 if (changed)
2350 *changed = params_changed;
2351
d62a17ae 2352 return ifp;
efc7191b
QY
2353
2354stream_failure:
2355 return NULL;
16f1b9ee
OD
2356}
2357
41ce5384
QY
2358static void zebra_interface_if_set_value(struct stream *s,
2359 struct interface *ifp)
16f1b9ee 2360{
d7c0a89a 2361 uint8_t link_params_status = 0;
41ce5384 2362 ifindex_t old_ifindex, new_ifindex;
efc7191b 2363
e7ff0253 2364 old_ifindex = ifp->oldifindex;
d62a17ae 2365 /* Read interface's index. */
41ce5384
QY
2366 STREAM_GETL(s, new_ifindex);
2367 if_set_index(ifp, new_ifindex);
2368 STREAM_GETC(s, ifp->status);
d62a17ae 2369
2370 /* Read interface's value. */
41ce5384
QY
2371 STREAM_GETQ(s, ifp->flags);
2372 STREAM_GETC(s, ifp->ptm_enable);
2373 STREAM_GETC(s, ifp->ptm_status);
2374 STREAM_GETL(s, ifp->metric);
2375 STREAM_GETL(s, ifp->speed);
2376 STREAM_GETL(s, ifp->mtu);
2377 STREAM_GETL(s, ifp->mtu6);
2378 STREAM_GETL(s, ifp->bandwidth);
2379 STREAM_GETL(s, ifp->link_ifindex);
2380 STREAM_GETL(s, ifp->ll_type);
2381 STREAM_GETL(s, ifp->hw_addr_len);
2382 if (ifp->hw_addr_len)
2383 STREAM_GET(ifp->hw_addr, s,
2384 MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
d62a17ae 2385
2386 /* Read Traffic Engineering status */
41ce5384 2387 link_params_status = stream_getc(s);
d62a17ae 2388 /* Then, Traffic Engineering parameters if any */
2389 if (link_params_status) {
41ce5384
QY
2390 struct if_link_params *iflp = if_link_params_get(ifp);
2391 link_params_set_value(s, iflp);
d62a17ae 2392 }
98cbbaea
DS
2393
2394 nexthop_group_interface_state_change(ifp, old_ifindex);
efc7191b 2395
41ce5384 2396 return;
efc7191b 2397stream_failure:
41ce5384
QY
2398 zlog_err("Could not parse interface values; aborting");
2399 assert(!"Failed to parse interface values");
16f1b9ee
OD
2400}
2401
d62a17ae 2402size_t zebra_interface_link_params_write(struct stream *s,
2403 struct interface *ifp)
16f1b9ee 2404{
d62a17ae 2405 size_t w;
2406 struct if_link_params *iflp;
2407 int i;
16f1b9ee 2408
d62a17ae 2409 if (s == NULL || ifp == NULL || ifp->link_params == NULL)
2410 return 0;
16f1b9ee 2411
d62a17ae 2412 iflp = ifp->link_params;
2413 w = 0;
16f1b9ee 2414
d62a17ae 2415 w += stream_putl(s, iflp->lp_status);
16f1b9ee 2416
d62a17ae 2417 w += stream_putl(s, iflp->te_metric);
2418 w += stream_putf(s, iflp->max_bw);
2419 w += stream_putf(s, iflp->max_rsv_bw);
16f1b9ee 2420
d62a17ae 2421 w += stream_putl(s, MAX_CLASS_TYPE);
2422 for (i = 0; i < MAX_CLASS_TYPE; i++)
2423 w += stream_putf(s, iflp->unrsv_bw[i]);
16f1b9ee 2424
d62a17ae 2425 w += stream_putl(s, iflp->admin_grp);
2426 w += stream_putl(s, iflp->rmt_as);
2427 w += stream_put_in_addr(s, &iflp->rmt_ip);
16f1b9ee 2428
d62a17ae 2429 w += stream_putl(s, iflp->av_delay);
2430 w += stream_putl(s, iflp->min_delay);
2431 w += stream_putl(s, iflp->max_delay);
2432 w += stream_putl(s, iflp->delay_var);
16f1b9ee 2433
d62a17ae 2434 w += stream_putf(s, iflp->pkt_loss);
2435 w += stream_putf(s, iflp->res_bw);
2436 w += stream_putf(s, iflp->ava_bw);
2437 w += stream_putf(s, iflp->use_bw);
16f1b9ee 2438
d62a17ae 2439 return w;
16f1b9ee
OD
2440}
2441
2442/*
0a589359 2443 * format of message for address additon is:
2444 * 0
2445 * 0 1 2 3 4 5 6 7
2446 * +-+-+-+-+-+-+-+-+
2447 * | type | ZEBRA_INTERFACE_ADDRESS_ADD or
2448 * +-+-+-+-+-+-+-+-+ ZEBRA_INTERFACE_ADDRES_DELETE
2449 * | |
2450 * + +
2451 * | ifindex |
2452 * + +
2453 * | |
2454 * + +
2455 * | |
2456 * +-+-+-+-+-+-+-+-+
2457 * | ifc_flags | flags for connected address
2458 * +-+-+-+-+-+-+-+-+
2459 * | addr_family |
2460 * +-+-+-+-+-+-+-+-+
2461 * | addr... |
2462 * : :
2463 * | |
2464 * +-+-+-+-+-+-+-+-+
2465 * | addr_len | len of addr. E.g., addr_len = 4 for ipv4 addrs.
2466 * +-+-+-+-+-+-+-+-+
2467 * | daddr.. |
2468 * : :
2469 * | |
2470 * +-+-+-+-+-+-+-+-+
0a589359 2471 */
2472
d62a17ae 2473static int memconstant(const void *s, int c, size_t n)
3fb9cd6e 2474{
d7c0a89a 2475 const uint8_t *p = s;
3fb9cd6e 2476
d62a17ae 2477 while (n-- > 0)
2478 if (*p++ != c)
2479 return 0;
2480 return 1;
3fb9cd6e 2481}
2482
d5a5c8f0 2483
d62a17ae 2484struct connected *zebra_interface_address_read(int type, struct stream *s,
2485 vrf_id_t vrf_id)
718e3744 2486{
d62a17ae 2487 ifindex_t ifindex;
2488 struct interface *ifp;
2489 struct connected *ifc;
2490 struct prefix p, d, *dp;
2491 int plen;
d7c0a89a 2492 uint8_t ifc_flags;
d62a17ae 2493
2494 memset(&p, 0, sizeof(p));
2495 memset(&d, 0, sizeof(d));
2496
2497 /* Get interface index. */
efc7191b 2498 STREAM_GETL(s, ifindex);
d62a17ae 2499
2500 /* Lookup index. */
2501 ifp = if_lookup_by_index(ifindex, vrf_id);
2502 if (ifp == NULL) {
450971aa 2503 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
2504 "INTERFACE_ADDRESS_%s: Cannot find IF %u in VRF %d",
2505 (type == ZEBRA_INTERFACE_ADDRESS_ADD) ? "ADD" : "DEL",
2506 ifindex, vrf_id);
d62a17ae 2507 return NULL;
2508 }
2509
2510 /* Fetch flag. */
efc7191b 2511 STREAM_GETC(s, ifc_flags);
d62a17ae 2512
2513 /* Fetch interface address. */
efc7191b 2514 STREAM_GETC(s, d.family);
e4f5680d 2515 p.family = d.family;
d62a17ae 2516 plen = prefix_blen(&d);
2517
efc7191b
QY
2518 if (zclient_stream_get_prefix(s, &p) != 0)
2519 goto stream_failure;
d62a17ae 2520
2521 /* Fetch destination address. */
efc7191b 2522 STREAM_GET(&d.u.prefix, s, plen);
d62a17ae 2523
2524 /* N.B. NULL destination pointers are encoded as all zeroes */
2525 dp = memconstant(&d.u.prefix, 0, plen) ? NULL : &d;
2526
2527 if (type == ZEBRA_INTERFACE_ADDRESS_ADD) {
2528 ifc = connected_lookup_prefix_exact(ifp, &p);
2529 if (!ifc) {
2530 /* N.B. NULL destination pointers are encoded as all
2531 * zeroes */
2532 ifc = connected_add_by_prefix(ifp, &p, dp);
2533 }
2534 if (ifc) {
2535 ifc->flags = ifc_flags;
2536 if (ifc->destination)
2537 ifc->destination->prefixlen =
2538 ifc->address->prefixlen;
2539 else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
2540 /* carp interfaces on OpenBSD with 0.0.0.0/0 as
2541 * "peer" */
ade6974d 2542 flog_err(
450971aa 2543 EC_LIB_ZAPI_ENCODE,
a0ee6f32 2544 "interface %s address %pFX with peer flag set, but no peer address!",
2dbe669b 2545 ifp->name, ifc->address);
d62a17ae 2546 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
2547 }
2548 }
2549 } else {
2550 assert(type == ZEBRA_INTERFACE_ADDRESS_DELETE);
2551 ifc = connected_delete_by_prefix(ifp, &p);
2552 }
2553
2554 return ifc;
efc7191b
QY
2555
2556stream_failure:
2557 return NULL;
718e3744 2558}
0a589359 2559
a80beece
DS
2560/*
2561 * format of message for neighbor connected address is:
2562 * 0
2563 * 0 1 2 3 4 5 6 7
2564 * +-+-+-+-+-+-+-+-+
2565 * | type | ZEBRA_INTERFACE_NBR_ADDRESS_ADD or
2566 * +-+-+-+-+-+-+-+-+ ZEBRA_INTERFACE_NBR_ADDRES_DELETE
2567 * | |
2568 * + +
2569 * | ifindex |
2570 * + +
2571 * | |
2572 * + +
2573 * | |
2574 * +-+-+-+-+-+-+-+-+
2575 * | addr_family |
2576 * +-+-+-+-+-+-+-+-+
2577 * | addr... |
2578 * : :
2579 * | |
2580 * +-+-+-+-+-+-+-+-+
2581 * | addr_len | len of addr.
2582 * +-+-+-+-+-+-+-+-+
2583 */
2584struct nbr_connected *
d62a17ae 2585zebra_interface_nbr_address_read(int type, struct stream *s, vrf_id_t vrf_id)
a80beece 2586{
d62a17ae 2587 unsigned int ifindex;
2588 struct interface *ifp;
2589 struct prefix p;
2590 struct nbr_connected *ifc;
2591
2592 /* Get interface index. */
efc7191b 2593 STREAM_GETL(s, ifindex);
d62a17ae 2594
2595 /* Lookup index. */
2596 ifp = if_lookup_by_index(ifindex, vrf_id);
2597 if (ifp == NULL) {
450971aa 2598 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
2599 "INTERFACE_NBR_%s: Cannot find IF %u in VRF %d",
2600 (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) ? "ADD"
ade6974d
QY
2601 : "DELETE",
2602 ifindex, vrf_id);
d62a17ae 2603 return NULL;
2604 }
2605
efc7191b
QY
2606 STREAM_GETC(s, p.family);
2607 STREAM_GET(&p.u.prefix, s, prefix_blen(&p));
2608 STREAM_GETC(s, p.prefixlen);
d62a17ae 2609
2610 if (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) {
2611 /* Currently only supporting P2P links, so any new RA source
2612 address is
2613 considered as the replacement of the previously learnt
2614 Link-Local address. */
2615 if (!(ifc = listnode_head(ifp->nbr_connected))) {
2616 ifc = nbr_connected_new();
2617 ifc->address = prefix_new();
2618 ifc->ifp = ifp;
2619 listnode_add(ifp->nbr_connected, ifc);
2620 }
2621
2622 prefix_copy(ifc->address, &p);
2623 } else {
2624 assert(type == ZEBRA_INTERFACE_NBR_ADDRESS_DELETE);
2625
2626 ifc = nbr_connected_check(ifp, &p);
2627 if (ifc)
2628 listnode_delete(ifp->nbr_connected, ifc);
2629 }
2630
2631 return ifc;
efc7191b
QY
2632
2633stream_failure:
2634 return NULL;
a80beece 2635}
6b0655a2 2636
d62a17ae 2637struct interface *zebra_interface_vrf_update_read(struct stream *s,
2638 vrf_id_t vrf_id,
2639 vrf_id_t *new_vrf_id)
c8e264b6 2640{
f17a9d0a 2641 char ifname[INTERFACE_NAMSIZ + 1] = {};
d62a17ae 2642 struct interface *ifp;
a9ff90c4 2643 vrf_id_t new_id;
d62a17ae 2644
91d227b7 2645 /* Read interface name. */
efc7191b 2646 STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
d62a17ae 2647
2648 /* Lookup interface. */
a36898e7 2649 ifp = if_lookup_by_name(ifname, vrf_id);
d62a17ae 2650 if (ifp == NULL) {
450971aa 2651 flog_err(EC_LIB_ZAPI_ENCODE,
91d227b7
RW
2652 "INTERFACE_VRF_UPDATE: Cannot find IF %s in VRF %d",
2653 ifname, vrf_id);
d62a17ae 2654 return NULL;
2655 }
2656
2657 /* Fetch new VRF Id. */
efc7191b 2658 STREAM_GETL(s, new_id);
d62a17ae 2659
2660 *new_vrf_id = new_id;
2661 return ifp;
efc7191b
QY
2662
2663stream_failure:
2664 return NULL;
c8e264b6 2665}
5c7ef8dc 2666
2667/* filter unwanted messages until the expected one arrives */
d62a17ae 2668static int zclient_read_sync_response(struct zclient *zclient,
d7c0a89a 2669 uint16_t expected_cmd)
5c7ef8dc 2670{
d62a17ae 2671 struct stream *s;
d7c0a89a
QY
2672 uint16_t size = -1;
2673 uint8_t marker;
2674 uint8_t version;
d62a17ae 2675 vrf_id_t vrf_id;
d7c0a89a 2676 uint16_t cmd;
d62a17ae 2677 fd_set readfds;
2678 int ret;
2679
2680 ret = 0;
2681 cmd = expected_cmd + 1;
2682 while (ret == 0 && cmd != expected_cmd) {
2683 s = zclient->ibuf;
2684 stream_reset(s);
2685
2686 /* wait until response arrives */
2687 FD_ZERO(&readfds);
2688 FD_SET(zclient->sock, &readfds);
2689 select(zclient->sock + 1, &readfds, NULL, NULL, NULL);
2690 if (!FD_ISSET(zclient->sock, &readfds))
2691 continue;
2692 /* read response */
2693 ret = zclient_read_header(s, zclient->sock, &size, &marker,
2694 &version, &vrf_id, &cmd);
2695 if (zclient_debug)
2696 zlog_debug("%s: Response (%d bytes) received", __func__,
2697 size);
2698 }
2699 if (ret != 0) {
1c50c1c0
QY
2700 flog_err(EC_LIB_ZAPI_ENCODE, "%s: Invalid Sync Message Reply",
2701 __func__);
d62a17ae 2702 return -1;
2703 }
2704
2705 return 0;
5c7ef8dc 2706}
fea12efb 2707/**
2708 * Connect to label manager in a syncronous way
2709 *
2710 * It first writes the request to zcient output buffer and then
2711 * immediately reads the answer from the input buffer.
2712 *
2713 * @param zclient Zclient used to connect to label manager (zebra)
f533be73 2714 * @param async Synchronous (0) or asynchronous (1) operation
fea12efb 2715 * @result Result of response
2716 */
f533be73 2717int lm_label_manager_connect(struct zclient *zclient, int async)
fea12efb 2718{
d62a17ae 2719 int ret;
2720 struct stream *s;
d7c0a89a 2721 uint8_t result;
f533be73 2722 uint16_t cmd = async ? ZEBRA_LABEL_MANAGER_CONNECT_ASYNC :
2723 ZEBRA_LABEL_MANAGER_CONNECT;
d62a17ae 2724
2725 if (zclient_debug)
35cbe02a 2726 zlog_debug("Connecting to Label Manager (LM)");
d62a17ae 2727
f533be73 2728 if (zclient->sock < 0) {
2729 zlog_debug("%s: invalid zclient socket", __func__);
d62a17ae 2730 return -1;
f533be73 2731 }
d62a17ae 2732
2733 /* send request */
2734 s = zclient->obuf;
2735 stream_reset(s);
f533be73 2736 zclient_create_header(s, cmd, VRF_DEFAULT);
d62a17ae 2737
2738 /* proto */
2739 stream_putc(s, zclient->redist_default);
2740 /* instance */
2741 stream_putw(s, zclient->instance);
2742
2743 /* Put length at the first point of the stream. */
2744 stream_putw_at(s, 0, stream_get_endp(s));
2745
2746 ret = writen(zclient->sock, s->data, stream_get_endp(s));
2747 if (ret < 0) {
450971aa 2748 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
d62a17ae 2749 close(zclient->sock);
2750 zclient->sock = -1;
2751 return -1;
2752 }
2753 if (ret == 0) {
450971aa 2754 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock closed");
d62a17ae 2755 close(zclient->sock);
2756 zclient->sock = -1;
2757 return -1;
2758 }
2759 if (zclient_debug)
35cbe02a 2760 zlog_debug("LM connect request sent (%d bytes)", ret);
d62a17ae 2761
f533be73 2762 if (async)
2763 return 0;
2764
d62a17ae 2765 /* read response */
f533be73 2766 if (zclient_read_sync_response(zclient, cmd)
d62a17ae 2767 != 0)
2768 return -1;
2769
d62a17ae 2770 s = zclient->ibuf;
5dffb0e9
FR
2771
2772 /* read instance and proto */
efc7191b
QY
2773 uint8_t proto;
2774 uint16_t instance;
2775
2776 STREAM_GETC(s, proto);
2777 STREAM_GETW(s, instance);
5dffb0e9
FR
2778
2779 /* sanity */
2780 if (proto != zclient->redist_default)
1c50c1c0
QY
2781 flog_err(
2782 EC_LIB_ZAPI_ENCODE,
2783 "Wrong proto (%u) in LM connect response. Should be %u",
2784 proto, zclient->redist_default);
5dffb0e9 2785 if (instance != zclient->instance)
1c50c1c0
QY
2786 flog_err(
2787 EC_LIB_ZAPI_ENCODE,
2788 "Wrong instId (%u) in LM connect response. Should be %u",
2789 instance, zclient->instance);
5dffb0e9
FR
2790
2791 /* result code */
efc7191b 2792 STREAM_GETC(s, result);
d62a17ae 2793 if (zclient_debug)
0313523d 2794 zlog_debug("LM connect-response received, result %u", result);
f2867068
HS
2795
2796 return (int)result;
2797
2798stream_failure:
2799 return -1;
2800}
2801
2802/**
2803 * Function to request a srv6-locator chunk in an Asyncronous way
2804 *
f2867068
HS
2805 * @param zclient Zclient used to connect to table manager (zebra)
2806 * @param locator_name Name of SRv6-locator
2807 * @result 0 on success, -1 otherwise
2808 */
2809int srv6_manager_get_locator_chunk(struct zclient *zclient,
2810 const char *locator_name)
2811{
2812 struct stream *s;
2813 const size_t len = strlen(locator_name);
2814
2815 if (zclient_debug)
2816 zlog_debug("Getting SRv6-Locator Chunk %s", locator_name);
2817
2818 if (zclient->sock < 0)
2819 return -1;
2820
2821 /* send request */
2822 s = zclient->obuf;
2823 stream_reset(s);
4df9d859
HS
2824 zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK,
2825 VRF_DEFAULT);
f2867068 2826
f2867068
HS
2827 /* locator_name */
2828 stream_putw(s, len);
2829 stream_put(s, locator_name, len);
2830
2831 /* Put length at the first point of the stream. */
2832 stream_putw_at(s, 0, stream_get_endp(s));
2833
2834 return zclient_send_message(zclient);
2835}
2836
2837/**
2838 * Function to release a srv6-locator chunk
2839 *
2840 * @param zclient Zclient used to connect to table manager (zebra)
2841 * @param locator_name Name of SRv6-locator
2842 * @result 0 on success, -1 otherwise
2843 */
2844int srv6_manager_release_locator_chunk(struct zclient *zclient,
2845 const char *locator_name)
2846{
2847 struct stream *s;
2848 const size_t len = strlen(locator_name);
2849
2850 if (zclient_debug)
2851 zlog_debug("Releasing SRv6-Locator Chunk %s", locator_name);
2852
2853 if (zclient->sock < 0)
2854 return -1;
2855
2856 /* send request */
2857 s = zclient->obuf;
2858 stream_reset(s);
2859 zclient_create_header(s, ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
2860 VRF_DEFAULT);
2861
f2867068
HS
2862 /* locator_name */
2863 stream_putw(s, len);
2864 stream_put(s, locator_name, len);
2865
2866 /* Put length at the first point of the stream. */
2867 stream_putw_at(s, 0, stream_get_endp(s));
2868
2869 return zclient_send_message(zclient);
2870}
2871
955bfd98
PZ
2872/*
2873 * Asynchronous label chunk request
2874 *
2875 * @param zclient Zclient used to connect to label manager (zebra)
2876 * @param keep Avoid garbage collection
2877 * @param chunk_size Amount of labels requested
0e3b6a92 2878 * @param base Base for the label chunk. if MPLS_LABEL_BASE_ANY we do not care
955bfd98
PZ
2879 * @result 0 on success, -1 otherwise
2880 */
7cfdb485
DS
2881enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient,
2882 uint8_t keep,
2883 uint32_t chunk_size,
2884 uint32_t base)
955bfd98
PZ
2885{
2886 struct stream *s;
2887
2888 if (zclient_debug)
2889 zlog_debug("Getting Label Chunk");
2890
2891 if (zclient->sock < 0)
7cfdb485 2892 return ZCLIENT_SEND_FAILURE;
955bfd98
PZ
2893
2894 s = zclient->obuf;
2895 stream_reset(s);
2896
2897 zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
5dffb0e9
FR
2898 /* proto */
2899 stream_putc(s, zclient->redist_default);
2900 /* instance */
2901 stream_putw(s, zclient->instance);
955bfd98
PZ
2902 stream_putc(s, keep);
2903 stream_putl(s, chunk_size);
0e3b6a92 2904 stream_putl(s, base);
955bfd98
PZ
2905
2906 /* Put length at the first point of the stream. */
2907 stream_putw_at(s, 0, stream_get_endp(s));
2908
2909 return zclient_send_message(zclient);
2910}
2911
fea12efb 2912/**
2913 * Function to request a label chunk in a syncronous way
2914 *
2915 * It first writes the request to zlcient output buffer and then
2916 * immediately reads the answer from the input buffer.
2917 *
2918 * @param zclient Zclient used to connect to label manager (zebra)
2919 * @param keep Avoid garbage collection
2920 * @param chunk_size Amount of labels requested
2921 * @param start To write first assigned chunk label to
2922 * @param end To write last assigned chunk label to
2923 * @result 0 on success, -1 otherwise
2924 */
0e3b6a92 2925int lm_get_label_chunk(struct zclient *zclient, uint8_t keep, uint32_t base,
d62a17ae 2926 uint32_t chunk_size, uint32_t *start, uint32_t *end)
fea12efb 2927{
d62a17ae 2928 int ret;
2929 struct stream *s;
d7c0a89a 2930 uint8_t response_keep;
d62a17ae 2931
2932 if (zclient_debug)
2933 zlog_debug("Getting Label Chunk");
2934
2935 if (zclient->sock < 0)
2936 return -1;
2937
2938 /* send request */
2939 s = zclient->obuf;
2940 stream_reset(s);
2941 zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
5dffb0e9
FR
2942 /* proto */
2943 stream_putc(s, zclient->redist_default);
2944 /* instance */
2945 stream_putw(s, zclient->instance);
d62a17ae 2946 /* keep */
2947 stream_putc(s, keep);
2948 /* chunk size */
2949 stream_putl(s, chunk_size);
0e3b6a92
EDP
2950 /* requested chunk base */
2951 stream_putl(s, base);
d62a17ae 2952 /* Put length at the first point of the stream. */
2953 stream_putw_at(s, 0, stream_get_endp(s));
2954
2955 ret = writen(zclient->sock, s->data, stream_get_endp(s));
2956 if (ret < 0) {
1c50c1c0 2957 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
d62a17ae 2958 close(zclient->sock);
2959 zclient->sock = -1;
2960 return -1;
2961 }
2962 if (ret == 0) {
1c50c1c0 2963 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock closed");
d62a17ae 2964 close(zclient->sock);
2965 zclient->sock = -1;
2966 return -1;
2967 }
2968 if (zclient_debug)
35cbe02a 2969 zlog_debug("Label chunk request (%d bytes) sent", ret);
d62a17ae 2970
2971 /* read response */
2972 if (zclient_read_sync_response(zclient, ZEBRA_GET_LABEL_CHUNK) != 0)
2973 return -1;
2974
5dffb0e9 2975 /* parse response */
d62a17ae 2976 s = zclient->ibuf;
5dffb0e9
FR
2977
2978 /* read proto and instance */
efc7191b
QY
2979 uint8_t proto;
2980 uint8_t instance;
2981
2982 STREAM_GETC(s, proto);
2983 STREAM_GETW(s, instance);
5dffb0e9
FR
2984
2985 /* sanities */
2986 if (proto != zclient->redist_default)
450971aa 2987 flog_err(EC_LIB_ZAPI_ENCODE,
1c50c1c0
QY
2988 "Wrong proto (%u) in get chunk response. Should be %u",
2989 proto, zclient->redist_default);
5dffb0e9 2990 if (instance != zclient->instance)
450971aa 2991 flog_err(EC_LIB_ZAPI_ENCODE,
1c50c1c0
QY
2992 "Wrong instId (%u) in get chunk response Should be %u",
2993 instance, zclient->instance);
5dffb0e9 2994
f004f7c3
EDP
2995 /* if we requested a specific chunk and it could not be allocated, the
2996 * response message will end here
2997 */
2998 if (!STREAM_READABLE(s)) {
2999 zlog_info("Unable to assign Label Chunk to %s instance %u",
3000 zebra_route_string(proto), instance);
3001 return -1;
3002 }
3003
d62a17ae 3004 /* keep */
efc7191b 3005 STREAM_GETC(s, response_keep);
d62a17ae 3006 /* start and end labels */
efc7191b
QY
3007 STREAM_GETL(s, *start);
3008 STREAM_GETL(s, *end);
d62a17ae 3009
3010 /* not owning this response */
3011 if (keep != response_keep) {
1c50c1c0
QY
3012 flog_err(
3013 EC_LIB_ZAPI_ENCODE,
3014 "Invalid Label chunk: %u - %u, keeps mismatch %u != %u",
3015 *start, *end, keep, response_keep);
d62a17ae 3016 }
3017 /* sanity */
70e98a7f
DS
3018 if (*start > *end || *start < MPLS_LABEL_UNRESERVED_MIN
3019 || *end > MPLS_LABEL_UNRESERVED_MAX) {
1c50c1c0
QY
3020 flog_err(EC_LIB_ZAPI_ENCODE, "Invalid Label chunk: %u - %u",
3021 *start, *end);
d62a17ae 3022 return -1;
3023 }
3024
3025 if (zclient_debug)
35cbe02a 3026 zlog_debug("Label Chunk assign: %u - %u (%u)", *start, *end,
d62a17ae 3027 response_keep);
3028
3029 return 0;
efc7191b
QY
3030
3031stream_failure:
3032 return -1;
fea12efb 3033}
3034
3035/**
3036 * Function to release a label chunk
3037 *
3038 * @param zclient Zclient used to connect to label manager (zebra)
3039 * @param start First label of chunk
3040 * @param end Last label of chunk
3041 * @result 0 on success, -1 otherwise
3042 */
d62a17ae 3043int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
3044 uint32_t end)
fea12efb 3045{
d62a17ae 3046 int ret;
3047 struct stream *s;
3048
3049 if (zclient_debug)
35cbe02a 3050 zlog_debug("Releasing Label Chunk %u - %u", start, end);
d62a17ae 3051
3052 if (zclient->sock < 0)
3053 return -1;
3054
3055 /* send request */
3056 s = zclient->obuf;
3057 stream_reset(s);
3058 zclient_create_header(s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT);
3059
5dffb0e9
FR
3060 /* proto */
3061 stream_putc(s, zclient->redist_default);
3062 /* instance */
3063 stream_putw(s, zclient->instance);
d62a17ae 3064 /* start */
3065 stream_putl(s, start);
3066 /* end */
3067 stream_putl(s, end);
3068
3069 /* Put length at the first point of the stream. */
3070 stream_putw_at(s, 0, stream_get_endp(s));
3071
3072 ret = writen(zclient->sock, s->data, stream_get_endp(s));
3073 if (ret < 0) {
450971aa 3074 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
d62a17ae 3075 close(zclient->sock);
3076 zclient->sock = -1;
3077 return -1;
3078 }
3079 if (ret == 0) {
1c50c1c0 3080 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock connection closed");
d62a17ae 3081 close(zclient->sock);
3082 zclient->sock = -1;
3083 return -1;
3084 }
3085
3086 return 0;
fea12efb 3087}
c8e264b6 3088
75fb51c1
PG
3089/**
3090 * Connect to table manager in a syncronous way
3091 *
3092 * It first writes the request to zcient output buffer and then
3093 * immediately reads the answer from the input buffer.
3094 *
3095 * @param zclient Zclient used to connect to table manager (zebra)
3096 * @result Result of response
3097 */
3098int tm_table_manager_connect(struct zclient *zclient)
3099{
3100 int ret;
3101 struct stream *s;
3102 uint8_t result;
3103
3104 if (zclient_debug)
3105 zlog_debug("Connecting to Table Manager");
3106
3107 if (zclient->sock < 0)
7cfdb485 3108 return ZCLIENT_SEND_FAILURE;
75fb51c1
PG
3109
3110 /* send request */
3111 s = zclient->obuf;
3112 stream_reset(s);
3113 zclient_create_header(s, ZEBRA_TABLE_MANAGER_CONNECT, VRF_DEFAULT);
3114
3115 /* proto */
3116 stream_putc(s, zclient->redist_default);
3117 /* instance */
3118 stream_putw(s, zclient->instance);
3119
3120 /* Put length at the first point of the stream. */
3121 stream_putw_at(s, 0, stream_get_endp(s));
3122
3123 ret = zclient_send_message(zclient);
7cfdb485 3124 if (ret == ZCLIENT_SEND_FAILURE)
75fb51c1
PG
3125 return -1;
3126
3127 if (zclient_debug)
0313523d 3128 zlog_debug("%s: Table manager connect request sent", __func__);
75fb51c1
PG
3129
3130 /* read response */
3131 if (zclient_read_sync_response(zclient, ZEBRA_TABLE_MANAGER_CONNECT)
3132 != 0)
3133 return -1;
3134
3135 /* result */
3136 s = zclient->ibuf;
3137 STREAM_GETC(s, result);
3138 if (zclient_debug)
3139 zlog_debug(
3140 "%s: Table Manager connect response received, result %u",
3141 __func__, result);
3142
3143 return (int)result;
3144stream_failure:
6a2b0d9a 3145 return -1;
75fb51c1
PG
3146}
3147
3148/**
3149 * Function to request a table chunk in a syncronous way
3150 *
3151 * It first writes the request to zclient output buffer and then
3152 * immediately reads the answer from the input buffer.
3153 *
3154 * @param zclient Zclient used to connect to table manager (zebra)
3155 * @param chunk_size Amount of table requested
3156 * @param start to write first assigned chunk table RT ID to
3157 * @param end To write last assigned chunk table RT ID to
3158 * @result 0 on success, -1 otherwise
3159 */
3160int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
3161 uint32_t *start, uint32_t *end)
3162{
3163 int ret;
3164 struct stream *s;
3165
3166 if (zclient_debug)
3167 zlog_debug("Getting Table Chunk");
3168
3169 if (zclient->sock < 0)
3170 return -1;
3171
3172 /* send request */
3173 s = zclient->obuf;
3174 stream_reset(s);
3175 zclient_create_header(s, ZEBRA_GET_TABLE_CHUNK, VRF_DEFAULT);
3176 /* chunk size */
3177 stream_putl(s, chunk_size);
3178 /* Put length at the first point of the stream. */
3179 stream_putw_at(s, 0, stream_get_endp(s));
3180
3181 ret = writen(zclient->sock, s->data, stream_get_endp(s));
3182 if (ret < 0) {
1c50c1c0
QY
3183 flog_err(EC_LIB_ZAPI_SOCKET, "%s: can't write to zclient->sock",
3184 __func__);
75fb51c1
PG
3185 close(zclient->sock);
3186 zclient->sock = -1;
3187 return -1;
3188 }
3189 if (ret == 0) {
450971aa 3190 flog_err(EC_LIB_ZAPI_SOCKET,
1c50c1c0 3191 "%s: zclient->sock connection closed", __func__);
75fb51c1
PG
3192 close(zclient->sock);
3193 zclient->sock = -1;
3194 return -1;
3195 }
3196 if (zclient_debug)
3197 zlog_debug("%s: Table chunk request (%d bytes) sent", __func__,
3198 ret);
3199
3200 /* read response */
3201 if (zclient_read_sync_response(zclient, ZEBRA_GET_TABLE_CHUNK) != 0)
3202 return -1;
3203
3204 s = zclient->ibuf;
3205 /* start and end table IDs */
3206 STREAM_GETL(s, *start);
3207 STREAM_GETL(s, *end);
3208
3209 if (zclient_debug)
3210 zlog_debug("Table Chunk assign: %u - %u ", *start, *end);
3211
75fb51c1 3212 return 0;
6a2b0d9a
RW
3213stream_failure:
3214 return -1;
75fb51c1
PG
3215}
3216
3217/**
3218 * Function to release a table chunk
3219 *
3220 * @param zclient Zclient used to connect to table manager (zebra)
3221 * @param start First label of table
3222 * @param end Last label of chunk
3223 * @result 0 on success, -1 otherwise
3224 */
3225int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
3226 uint32_t end)
3227{
3228 struct stream *s;
3229
3230 if (zclient_debug)
3231 zlog_debug("Releasing Table Chunk");
3232
3233 if (zclient->sock < 0)
3234 return -1;
3235
3236 /* send request */
3237 s = zclient->obuf;
3238 stream_reset(s);
3239 zclient_create_header(s, ZEBRA_RELEASE_TABLE_CHUNK, VRF_DEFAULT);
3240
3241 /* start */
3242 stream_putl(s, start);
3243 /* end */
3244 stream_putl(s, end);
3245
3246 /* Put length at the first point of the stream. */
3247 stream_putw_at(s, 0, stream_get_endp(s));
3248
7cfdb485
DS
3249 if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
3250 return -1;
3251
3252 return 0;
75fb51c1
PG
3253}
3254
7cfdb485
DS
3255enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient, int cmd,
3256 struct zapi_sr_policy *zp)
31f937fb
SM
3257{
3258 if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
7cfdb485 3259 return ZCLIENT_SEND_FAILURE;
31f937fb
SM
3260 return zclient_send_message(zclient);
3261}
3262
3263int zapi_sr_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp)
3264{
3265 struct zapi_srte_tunnel *zt = &zp->segment_list;
3266
3267 stream_reset(s);
3268
3269 zclient_create_header(s, cmd, VRF_DEFAULT);
3270 stream_putl(s, zp->color);
3271 stream_put_ipaddr(s, &zp->endpoint);
3272 stream_write(s, &zp->name, SRTE_POLICY_NAME_MAX_LENGTH);
3273
3274 stream_putc(s, zt->type);
3275 stream_putl(s, zt->local_label);
3276
3277 if (zt->label_num > MPLS_MAX_LABELS) {
3278 flog_err(EC_LIB_ZAPI_ENCODE,
3279 "%s: label %u: can't encode %u labels (maximum is %u)",
3280 __func__, zt->local_label, zt->label_num,
3281 MPLS_MAX_LABELS);
3282 return -1;
3283 }
3284 stream_putw(s, zt->label_num);
3285
3286 for (int i = 0; i < zt->label_num; i++)
3287 stream_putl(s, zt->labels[i]);
3288
3289 /* Put length at the first point of the stream. */
3290 stream_putw_at(s, 0, stream_get_endp(s));
3291
3292 return 0;
3293}
3294
3295int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
3296{
3297 memset(zp, 0, sizeof(*zp));
3298
3299 struct zapi_srte_tunnel *zt = &zp->segment_list;
3300
3301 STREAM_GETL(s, zp->color);
3302 STREAM_GET_IPADDR(s, &zp->endpoint);
3303 STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
3304
3305 /* segment list of active candidate path */
3306 STREAM_GETC(s, zt->type);
3307 STREAM_GETL(s, zt->local_label);
3308 STREAM_GETW(s, zt->label_num);
3309 if (zt->label_num > MPLS_MAX_LABELS) {
3310 flog_err(EC_LIB_ZAPI_ENCODE,
3311 "%s: label %u: can't decode %u labels (maximum is %u)",
3312 __func__, zt->local_label, zt->label_num,
3313 MPLS_MAX_LABELS);
3314 return -1;
3315 }
3316 for (int i = 0; i < zt->label_num; i++)
3317 STREAM_GETL(s, zt->labels[i]);
3318
3319 return 0;
3320
3321stream_failure:
3322 return -1;
3323}
3324
3325int zapi_sr_policy_notify_status_decode(struct stream *s,
3326 struct zapi_sr_policy *zp)
3327{
3328 memset(zp, 0, sizeof(*zp));
3329
3330 STREAM_GETL(s, zp->color);
3331 STREAM_GET_IPADDR(s, &zp->endpoint);
3332 STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
3333 STREAM_GETL(s, zp->status);
3334
3335 return 0;
3336
3337stream_failure:
3338 return -1;
3339}
3340
7cfdb485
DS
3341enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient,
3342 int cmd, struct zapi_labels *zl)
bad6b0e7
RW
3343{
3344 if (zapi_labels_encode(zclient->obuf, cmd, zl) < 0)
7cfdb485 3345 return ZCLIENT_SEND_FAILURE;
bad6b0e7
RW
3346 return zclient_send_message(zclient);
3347}
3348
3349int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
3350{
4945002d 3351 struct zapi_nexthop *znh;
ea6b290b 3352
bad6b0e7
RW
3353 stream_reset(s);
3354
3355 zclient_create_header(s, cmd, VRF_DEFAULT);
b3c49d0e 3356 stream_putc(s, zl->message);
bad6b0e7 3357 stream_putc(s, zl->type);
b3c49d0e
RW
3358 stream_putl(s, zl->local_label);
3359
3360 if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
3361 stream_putw(s, zl->route.prefix.family);
3362 stream_put_prefix(s, &zl->route.prefix);
3363 stream_putc(s, zl->route.type);
3364 stream_putw(s, zl->route.instance);
3365 }
3366
ea6b290b
RW
3367 if (zl->nexthop_num > MULTIPATH_NUM) {
3368 flog_err(
3369 EC_LIB_ZAPI_ENCODE,
3370 "%s: label %u: can't encode %u nexthops (maximum is %u)",
3371 __func__, zl->local_label, zl->nexthop_num,
3372 MULTIPATH_NUM);
3373 return -1;
3374 }
3375 stream_putw(s, zl->nexthop_num);
3376
3377 for (int i = 0; i < zl->nexthop_num; i++) {
3378 znh = &zl->nexthops[i];
3379
31f937fb 3380 if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
4945002d 3381 return -1;
bad6b0e7 3382 }
bad6b0e7 3383
34f86754
MS
3384 if (CHECK_FLAG(zl->message, ZAPI_LABELS_HAS_BACKUPS)) {
3385
3386 if (zl->backup_nexthop_num > MULTIPATH_NUM) {
3387 flog_err(
3388 EC_LIB_ZAPI_ENCODE,
3389 "%s: label %u: can't encode %u nexthops (maximum is %u)",
3390 __func__, zl->local_label, zl->nexthop_num,
3391 MULTIPATH_NUM);
3392 return -1;
3393 }
3394 stream_putw(s, zl->backup_nexthop_num);
3395
3396 for (int i = 0; i < zl->backup_nexthop_num; i++) {
3397 znh = &zl->backup_nexthops[i];
3398
31f937fb 3399 if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
34f86754
MS
3400 return -1;
3401 }
3402
3403 }
3404
bad6b0e7
RW
3405 /* Put length at the first point of the stream. */
3406 stream_putw_at(s, 0, stream_get_endp(s));
3407
3408 return 0;
3409}
3410
3411int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
3412{
4945002d 3413 struct zapi_nexthop *znh;
ea6b290b 3414
bad6b0e7
RW
3415 memset(zl, 0, sizeof(*zl));
3416
3417 /* Get data. */
b3c49d0e 3418 STREAM_GETC(s, zl->message);
bad6b0e7 3419 STREAM_GETC(s, zl->type);
b3c49d0e 3420 STREAM_GETL(s, zl->local_label);
bad6b0e7 3421
b3c49d0e
RW
3422 if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
3423 size_t psize;
3424
3425 STREAM_GETW(s, zl->route.prefix.family);
3426 STREAM_GETC(s, zl->route.prefix.prefixlen);
3427
3428 psize = PSIZE(zl->route.prefix.prefixlen);
3429 switch (zl->route.prefix.family) {
3430 case AF_INET:
3431 if (zl->route.prefix.prefixlen > IPV4_MAX_BITLEN) {
3432 zlog_debug(
3433 "%s: Specified prefix length %d is greater than a v4 address can support",
15569c58 3434 __func__, zl->route.prefix.prefixlen);
b3c49d0e
RW
3435 return -1;
3436 }
3437 STREAM_GET(&zl->route.prefix.u.prefix4.s_addr, s,
3438 psize);
3439 break;
3440 case AF_INET6:
3441 if (zl->route.prefix.prefixlen > IPV6_MAX_BITLEN) {
3442 zlog_debug(
3443 "%s: Specified prefix length %d is greater than a v6 address can support",
15569c58 3444 __func__, zl->route.prefix.prefixlen);
b3c49d0e
RW
3445 return -1;
3446 }
3447 STREAM_GET(&zl->route.prefix.u.prefix6, s, psize);
3448 break;
3449 default:
3450 flog_err(EC_LIB_ZAPI_ENCODE,
3451 "%s: Specified family %u is not v4 or v6",
15569c58 3452 __func__, zl->route.prefix.family);
bad6b0e7
RW
3453 return -1;
3454 }
b3c49d0e
RW
3455
3456 STREAM_GETC(s, zl->route.type);
3457 STREAM_GETW(s, zl->route.instance);
3458 }
3459
ea6b290b 3460 STREAM_GETW(s, zl->nexthop_num);
b900b3c6
QY
3461
3462 if (zl->nexthop_num > MULTIPATH_NUM) {
3463 flog_warn(
3464 EC_LIB_ZAPI_ENCODE,
3465 "%s: Prefix %pFX has %d nexthops, but we can only use the first %d",
3466 __func__, &zl->route.prefix, zl->nexthop_num,
3467 MULTIPATH_NUM);
3468 }
3469
3470 zl->nexthop_num = MIN(MULTIPATH_NUM, zl->nexthop_num);
3471
ea6b290b
RW
3472 for (int i = 0; i < zl->nexthop_num; i++) {
3473 znh = &zl->nexthops[i];
3474
31f937fb 3475 if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
4945002d 3476 return -1;
b7457b40
DS
3477
3478 if (znh->type == NEXTHOP_TYPE_BLACKHOLE) {
3479 flog_warn(
3480 EC_LIB_ZAPI_ENCODE,
3481 "%s: Prefix %pFX has a blackhole nexthop which we cannot use for a label",
3482 __func__, &zl->route.prefix);
3483 return -1;
3484 }
bad6b0e7 3485 }
bad6b0e7 3486
34f86754
MS
3487 if (CHECK_FLAG(zl->message, ZAPI_LABELS_HAS_BACKUPS)) {
3488 STREAM_GETW(s, zl->backup_nexthop_num);
3489
3490 if (zl->backup_nexthop_num > MULTIPATH_NUM) {
3491 flog_warn(
3492 EC_LIB_ZAPI_ENCODE,
3493 "%s: Prefix %pFX has %d backup nexthops, but we can only use the first %d",
3494 __func__, &zl->route.prefix,
3495 zl->backup_nexthop_num, MULTIPATH_NUM);
3496 }
3497
3498 zl->backup_nexthop_num = MIN(MULTIPATH_NUM,
3499 zl->backup_nexthop_num);
3500
3501 for (int i = 0; i < zl->backup_nexthop_num; i++) {
3502 znh = &zl->backup_nexthops[i];
3503
31f937fb 3504 if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
34f86754 3505 return -1;
b7457b40
DS
3506
3507 if (znh->type == NEXTHOP_TYPE_BLACKHOLE) {
3508 flog_warn(
3509 EC_LIB_ZAPI_ENCODE,
3510 "%s: Prefix %pFX has a backup blackhole nexthop which we cannot use for a label",
3511 __func__, &zl->route.prefix);
3512 return -1;
3513 }
34f86754
MS
3514 }
3515 }
3516
bad6b0e7
RW
3517 return 0;
3518stream_failure:
3519 return -1;
3520}
75fb51c1 3521
7cfdb485
DS
3522enum zclient_send_status zebra_send_pw(struct zclient *zclient, int command,
3523 struct zapi_pw *pw)
6833ae01 3524{
3525 struct stream *s;
3526
3527 /* Reset stream. */
3528 s = zclient->obuf;
3529 stream_reset(s);
3530
3531 zclient_create_header(s, command, VRF_DEFAULT);
3532 stream_write(s, pw->ifname, IF_NAMESIZE);
3533 stream_putl(s, pw->ifindex);
3534
3535 /* Put type */
3536 stream_putl(s, pw->type);
3537
3538 /* Put nexthop */
3539 stream_putl(s, pw->af);
3540 switch (pw->af) {
3541 case AF_INET:
3542 stream_put_in_addr(s, &pw->nexthop.ipv4);
3543 break;
3544 case AF_INET6:
d7c0a89a 3545 stream_write(s, (uint8_t *)&pw->nexthop.ipv6, 16);
6833ae01 3546 break;
3547 default:
1c50c1c0 3548 flog_err(EC_LIB_ZAPI_ENCODE, "%s: unknown af", __func__);
7cfdb485 3549 return ZCLIENT_SEND_FAILURE;
6833ae01 3550 }
3551
3552 /* Put labels */
3553 stream_putl(s, pw->local_label);
3554 stream_putl(s, pw->remote_label);
3555
3556 /* Put flags */
3557 stream_putc(s, pw->flags);
3558
3559 /* Protocol specific fields */
3560 stream_write(s, &pw->data, sizeof(union pw_protocol_fields));
3561
3562 /* Put length at the first point of the stream. */
3563 stream_putw_at(s, 0, stream_get_endp(s));
3564
3565 return zclient_send_message(zclient);
3566}
3567
3568/*
3569 * Receive PW status update from Zebra and send it to LDE process.
3570 */
efc7191b 3571int zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_status *pw)
6833ae01 3572{
3573 struct stream *s;
3574
3575 memset(pw, 0, sizeof(struct zapi_pw_status));
3576 s = zclient->ibuf;
3577
3578 /* Get data. */
3579 stream_get(pw->ifname, s, IF_NAMESIZE);
efc7191b
QY
3580 STREAM_GETL(s, pw->ifindex);
3581 STREAM_GETL(s, pw->status);
3582
3583 return 0;
3584stream_failure:
3585 return -1;
6833ae01 3586}
3587
121f9dee 3588static void zclient_capability_decode(ZAPI_CALLBACK_ARGS)
09924cff
DS
3589{
3590 struct zclient_capabilities cap;
3591 struct stream *s = zclient->ibuf;
bb6b7f79 3592 int vrf_backend;
09924cff
DS
3593 uint8_t mpls_enabled;
3594
bb6b7f79 3595 STREAM_GETL(s, vrf_backend);
7239d3d9
QY
3596
3597 if (vrf_backend < 0 || vrf_configure_backend(vrf_backend)) {
3598 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 3599 "%s: Garbage VRF backend type: %d", __func__,
7239d3d9
QY
3600 vrf_backend);
3601 goto stream_failure;
3602 }
3603
bb6b7f79 3604
09924cff
DS
3605 memset(&cap, 0, sizeof(cap));
3606 STREAM_GETC(s, mpls_enabled);
3607 cap.mpls_enabled = !!mpls_enabled;
3608 STREAM_GETL(s, cap.ecmp);
02c0866d 3609 STREAM_GETC(s, cap.role);
09924cff
DS
3610
3611 if (zclient->zebra_capabilities)
3612 (*zclient->zebra_capabilities)(&cap);
3613
3614stream_failure:
3615 return;
3616}
3617
7cfdb485
DS
3618enum zclient_send_status zclient_send_mlag_register(struct zclient *client,
3619 uint32_t bit_map)
36b5b98f
SK
3620{
3621 struct stream *s;
3622
3623 s = client->obuf;
3624 stream_reset(s);
3625
3626 zclient_create_header(s, ZEBRA_MLAG_CLIENT_REGISTER, VRF_DEFAULT);
3627 stream_putl(s, bit_map);
3628
3629 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 3630 return zclient_send_message(client);
36b5b98f
SK
3631}
3632
7cfdb485 3633enum zclient_send_status zclient_send_mlag_deregister(struct zclient *client)
36b5b98f 3634{
4df9d859
HS
3635 return zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER,
3636 VRF_DEFAULT);
36b5b98f
SK
3637}
3638
7cfdb485
DS
3639enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
3640 struct stream *client_s)
36b5b98f
SK
3641{
3642 struct stream *s;
3643
3644 s = client->obuf;
3645 stream_reset(s);
3646
3647 zclient_create_header(s, ZEBRA_MLAG_FORWARD_MSG, VRF_DEFAULT);
3648 stream_put(s, client_s->data, client_s->endp);
3649
3650 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 3651 return zclient_send_message(client);
36b5b98f
SK
3652}
3653
46c2687c
SK
3654static void zclient_mlag_process_up(ZAPI_CALLBACK_ARGS)
3655{
3656 if (zclient->mlag_process_up)
3657 (*zclient->mlag_process_up)();
3658}
3659
3660static void zclient_mlag_process_down(ZAPI_CALLBACK_ARGS)
3661{
3662 if (zclient->mlag_process_down)
3663 (*zclient->mlag_process_down)();
3664}
3665
3666static void zclient_mlag_handle_msg(ZAPI_CALLBACK_ARGS)
3667{
3668 if (zclient->mlag_handle_msg)
3669 (*zclient->mlag_handle_msg)(zclient->ibuf, length);
3670}
3671
ff491140
MS
3672/*
3673 * Send an OPAQUE message, contents opaque to zebra. The message header
3674 * is a message subtype.
3675 */
7cfdb485
DS
3676enum zclient_send_status zclient_send_opaque(struct zclient *zclient,
3677 uint32_t type, const uint8_t *data,
3678 size_t datasize)
ff491140 3679{
ff491140 3680 struct stream *s;
387831ff 3681 uint16_t flags = 0;
ff491140
MS
3682
3683 /* Check buffer size */
3684 if (STREAM_SIZE(zclient->obuf) <
3685 (ZEBRA_HEADER_SIZE + sizeof(type) + datasize))
7cfdb485 3686 return ZCLIENT_SEND_FAILURE;
ff491140
MS
3687
3688 s = zclient->obuf;
3689 stream_reset(s);
3690
3691 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
3692
387831ff 3693 /* Send sub-type and flags */
ff491140 3694 stream_putl(s, type);
387831ff 3695 stream_putw(s, flags);
ff491140
MS
3696
3697 /* Send opaque data */
3698 stream_write(s, data, datasize);
3699
3700 /* Put length into the header at the start of the stream. */
3701 stream_putw_at(s, 0, stream_get_endp(s));
3702
db71415b 3703 return zclient_send_message(zclient);
ff491140
MS
3704}
3705
387831ff
MS
3706/*
3707 * Send an OPAQUE message to a specific zclient. The contents are opaque
3708 * to zebra.
3709 */
7cfdb485
DS
3710enum zclient_send_status
3711zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
3712 uint8_t proto, uint16_t instance,
3713 uint32_t session_id, const uint8_t *data,
3714 size_t datasize)
387831ff 3715{
387831ff
MS
3716 struct stream *s;
3717 uint16_t flags = 0;
3718
3719 /* Check buffer size */
3720 if (STREAM_SIZE(zclient->obuf) <
3721 (ZEBRA_HEADER_SIZE + sizeof(struct zapi_opaque_msg) + datasize))
7cfdb485 3722 return ZCLIENT_SEND_FAILURE;
387831ff
MS
3723
3724 s = zclient->obuf;
3725 stream_reset(s);
3726
3727 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
3728
3729 /* Send sub-type and flags */
3730 SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
3731 stream_putl(s, type);
3732 stream_putw(s, flags);
3733
3734 /* Send destination client info */
3735 stream_putc(s, proto);
3736 stream_putw(s, instance);
3737 stream_putl(s, session_id);
3738
3739 /* Send opaque data */
3740 stream_write(s, data, datasize);
3741
3742 /* Put length into the header at the start of the stream. */
3743 stream_putw_at(s, 0, stream_get_endp(s));
3744
db71415b 3745 return zclient_send_message(zclient);
387831ff
MS
3746}
3747
3748/*
3749 * Decode incoming opaque message into info struct
3750 */
3751int zclient_opaque_decode(struct stream *s, struct zapi_opaque_msg *info)
3752{
3753 memset(info, 0, sizeof(*info));
3754
3755 /* Decode subtype and flags */
3756 STREAM_GETL(s, info->type);
3757 STREAM_GETW(s, info->flags);
3758
3759 /* Decode unicast client info if present */
3760 if (CHECK_FLAG(info->flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
3761 STREAM_GETC(s, info->proto);
3762 STREAM_GETW(s, info->instance);
3763 STREAM_GETL(s, info->session_id);
3764 }
3765
3766 info->len = STREAM_READABLE(s);
3767
3768 return 0;
3769
3770stream_failure:
3771
3772 return -1;
3773}
3774
ff491140
MS
3775/*
3776 * Send a registration request for opaque messages with a specified subtype.
3777 */
7cfdb485
DS
3778enum zclient_send_status zclient_register_opaque(struct zclient *zclient,
3779 uint32_t type)
ff491140 3780{
ff491140
MS
3781 struct stream *s;
3782
3783 s = zclient->obuf;
3784 stream_reset(s);
3785
3786 zclient_create_header(s, ZEBRA_OPAQUE_REGISTER, VRF_DEFAULT);
3787
3788 /* Send sub-type */
3789 stream_putl(s, type);
3790
3791 /* Add zclient info */
3792 stream_putc(s, zclient->redist_default);
3793 stream_putw(s, zclient->instance);
3794 stream_putl(s, zclient->session_id);
3795
3796 /* Put length at the first point of the stream. */
3797 stream_putw_at(s, 0, stream_get_endp(s));
3798
db71415b 3799 return zclient_send_message(zclient);
ff491140
MS
3800}
3801
3802/*
3803 * Send an un-registration request for a specified opaque subtype.
3804 */
7cfdb485
DS
3805enum zclient_send_status zclient_unregister_opaque(struct zclient *zclient,
3806 uint32_t type)
ff491140 3807{
ff491140
MS
3808 struct stream *s;
3809
3810 s = zclient->obuf;
3811 stream_reset(s);
3812
3813 zclient_create_header(s, ZEBRA_OPAQUE_UNREGISTER, VRF_DEFAULT);
3814
3815 /* Send sub-type */
3816 stream_putl(s, type);
3817
3818 /* Add zclient info */
3819 stream_putc(s, zclient->redist_default);
3820 stream_putw(s, zclient->instance);
3821 stream_putl(s, zclient->session_id);
3822
3823 /* Put length at the first point of the stream. */
3824 stream_putw_at(s, 0, stream_get_endp(s));
3825
db71415b 3826 return zclient_send_message(zclient);
ff491140
MS
3827}
3828
d2ddc141 3829/* Utility to decode opaque registration info */
387831ff 3830int zapi_opaque_reg_decode(struct stream *s, struct zapi_opaque_reg_info *info)
ff491140
MS
3831{
3832 STREAM_GETL(s, info->type);
3833 STREAM_GETC(s, info->proto);
3834 STREAM_GETW(s, info->instance);
3835 STREAM_GETL(s, info->session_id);
3836
3837 return 0;
3838
3839stream_failure:
3840
3841 return -1;
3842}
3843
581e797e
KS
3844/* Utility to decode client close notify info */
3845int zapi_client_close_notify_decode(struct stream *s,
3846 struct zapi_client_close_info *info)
3847{
3848 memset(info, 0, sizeof(*info));
3849
3850 STREAM_GETC(s, info->proto);
3851 STREAM_GETW(s, info->instance);
3852 STREAM_GETL(s, info->session_id);
3853
3854 return 0;
3855
3856stream_failure:
3857
3858 return -1;
3859}
3860
718e3744 3861/* Zebra client message read function. */
d62a17ae 3862static int zclient_read(struct thread *thread)
718e3744 3863{
d62a17ae 3864 size_t already;
3865 uint16_t length, command;
3866 uint8_t marker, version;
3867 vrf_id_t vrf_id;
3868 struct zclient *zclient;
3869
3870 /* Get socket to zebra. */
3871 zclient = THREAD_ARG(thread);
3872 zclient->t_read = NULL;
3873
3874 /* Read zebra header (if we don't have it already). */
0e2d7076
DA
3875 already = stream_get_endp(zclient->ibuf);
3876 if (already < ZEBRA_HEADER_SIZE) {
d62a17ae 3877 ssize_t nbyte;
3878 if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
3879 ZEBRA_HEADER_SIZE - already))
3880 == 0)
3881 || (nbyte == -1)) {
3882 if (zclient_debug)
3883 zlog_debug(
3884 "zclient connection closed socket [%d].",
3885 zclient->sock);
3886 return zclient_failed(zclient);
3887 }
3888 if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
d62a17ae 3889 zclient_event(ZCLIENT_READ, zclient);
3890 return 0;
3891 }
3892 already = ZEBRA_HEADER_SIZE;
634f9ea2 3893 }
d62a17ae 3894
3895 /* Reset to read from the beginning of the incoming packet. */
3896 stream_set_getp(zclient->ibuf, 0);
3897
3898 /* Fetch header values. */
3899 length = stream_getw(zclient->ibuf);
3900 marker = stream_getc(zclient->ibuf);
3901 version = stream_getc(zclient->ibuf);
a9ff90c4 3902 vrf_id = stream_getl(zclient->ibuf);
d62a17ae 3903 command = stream_getw(zclient->ibuf);
3904
3905 if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
1c50c1c0
QY
3906 flog_err(
3907 EC_LIB_ZAPI_MISSMATCH,
3908 "%s: socket %d version mismatch, marker %d, version %d",
3909 __func__, zclient->sock, marker, version);
d62a17ae 3910 return zclient_failed(zclient);
634f9ea2 3911 }
d62a17ae 3912
3913 if (length < ZEBRA_HEADER_SIZE) {
450971aa 3914 flog_err(EC_LIB_ZAPI_MISSMATCH,
1c50c1c0
QY
3915 "%s: socket %d message length %u is less than %d ",
3916 __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
d62a17ae 3917 return zclient_failed(zclient);
634f9ea2 3918 }
d62a17ae 3919
3920 /* Length check. */
3921 if (length > STREAM_SIZE(zclient->ibuf)) {
3922 struct stream *ns;
ade6974d 3923 flog_err(
450971aa 3924 EC_LIB_ZAPI_ENCODE,
ade6974d
QY
3925 "%s: message size %u exceeds buffer size %lu, expanding...",
3926 __func__, length,
3927 (unsigned long)STREAM_SIZE(zclient->ibuf));
d62a17ae 3928 ns = stream_new(length);
3929 stream_copy(ns, zclient->ibuf);
3930 stream_free(zclient->ibuf);
3931 zclient->ibuf = ns;
3932 }
3933
3934 /* Read rest of zebra packet. */
3935 if (already < length) {
3936 ssize_t nbyte;
3937 if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
3938 length - already))
3939 == 0)
3940 || (nbyte == -1)) {
3941 if (zclient_debug)
3942 zlog_debug(
3943 "zclient connection closed socket [%d].",
3944 zclient->sock);
3945 return zclient_failed(zclient);
3946 }
3947 if (nbyte != (ssize_t)(length - already)) {
3948 /* Try again later. */
3949 zclient_event(ZCLIENT_READ, zclient);
3950 return 0;
3951 }
3952 }
3953
3954 length -= ZEBRA_HEADER_SIZE;
3955
3956 if (zclient_debug)
461d106d
RW
3957 zlog_debug("zclient %p command %s VRF %u", zclient,
3958 zserv_command_string(command), vrf_id);
d62a17ae 3959
3960 switch (command) {
09924cff
DS
3961 case ZEBRA_CAPABILITIES:
3962 zclient_capability_decode(command, zclient, length, vrf_id);
3963 break;
d62a17ae 3964 case ZEBRA_ROUTER_ID_UPDATE:
3965 if (zclient->router_id_update)
3966 (*zclient->router_id_update)(command, zclient, length,
3967 vrf_id);
3968 break;
3969 case ZEBRA_VRF_ADD:
3970 zclient_vrf_add(zclient, vrf_id);
3971 break;
3972 case ZEBRA_VRF_DELETE:
3973 zclient_vrf_delete(zclient, vrf_id);
3974 break;
3975 case ZEBRA_INTERFACE_ADD:
ef7bd2a3 3976 zclient_interface_add(zclient, vrf_id);
d62a17ae 3977 break;
3978 case ZEBRA_INTERFACE_DELETE:
3c3c3252 3979 zclient_interface_delete(zclient, vrf_id);
d62a17ae 3980 break;
3981 case ZEBRA_INTERFACE_ADDRESS_ADD:
3982 if (zclient->interface_address_add)
3983 (*zclient->interface_address_add)(command, zclient,
3984 length, vrf_id);
3985 break;
3986 case ZEBRA_INTERFACE_ADDRESS_DELETE:
3987 if (zclient->interface_address_delete)
3988 (*zclient->interface_address_delete)(command, zclient,
3989 length, vrf_id);
3990 break;
3991 case ZEBRA_INTERFACE_BFD_DEST_UPDATE:
3992 if (zclient->interface_bfd_dest_update)
3993 (*zclient->interface_bfd_dest_update)(command, zclient,
3994 length, vrf_id);
3995 break;
3996 case ZEBRA_INTERFACE_NBR_ADDRESS_ADD:
3997 if (zclient->interface_nbr_address_add)
3998 (*zclient->interface_nbr_address_add)(command, zclient,
3999 length, vrf_id);
4000 break;
4001 case ZEBRA_INTERFACE_NBR_ADDRESS_DELETE:
4002 if (zclient->interface_nbr_address_delete)
4003 (*zclient->interface_nbr_address_delete)(
4004 command, zclient, length, vrf_id);
4005 break;
4006 case ZEBRA_INTERFACE_UP:
ddbf3e60 4007 zclient_interface_up(zclient, vrf_id);
d62a17ae 4008 break;
4009 case ZEBRA_INTERFACE_DOWN:
b0b69e59 4010 zclient_interface_down(zclient, vrf_id);
d62a17ae 4011 break;
4012 case ZEBRA_INTERFACE_VRF_UPDATE:
4013 if (zclient->interface_vrf_update)
4014 (*zclient->interface_vrf_update)(command, zclient,
4015 length, vrf_id);
4016 break;
4017 case ZEBRA_NEXTHOP_UPDATE:
4018 if (zclient_debug)
9165c5f5 4019 zlog_debug("zclient rcvd nexthop update");
d62a17ae 4020 if (zclient->nexthop_update)
4021 (*zclient->nexthop_update)(command, zclient, length,
4022 vrf_id);
4023 break;
d62a17ae 4024 case ZEBRA_BFD_DEST_REPLAY:
4025 if (zclient->bfd_dest_replay)
4026 (*zclient->bfd_dest_replay)(command, zclient, length,
4027 vrf_id);
4028 break;
74489921
RW
4029 case ZEBRA_REDISTRIBUTE_ROUTE_ADD:
4030 if (zclient->redistribute_route_add)
4031 (*zclient->redistribute_route_add)(command, zclient,
4032 length, vrf_id);
d62a17ae 4033 break;
74489921
RW
4034 case ZEBRA_REDISTRIBUTE_ROUTE_DEL:
4035 if (zclient->redistribute_route_del)
4036 (*zclient->redistribute_route_del)(command, zclient,
4037 length, vrf_id);
d62a17ae 4038 break;
4039 case ZEBRA_INTERFACE_LINK_PARAMS:
4040 if (zclient->interface_link_params)
4041 (*zclient->interface_link_params)(command, zclient,
edc12762 4042 length, vrf_id);
d62a17ae 4043 break;
4044 case ZEBRA_FEC_UPDATE:
4045 if (zclient_debug)
9165c5f5 4046 zlog_debug("zclient rcvd fec update");
d62a17ae 4047 if (zclient->fec_update)
4048 (*zclient->fec_update)(command, zclient, length);
4049 break;
50f74cf1 4050 case ZEBRA_LOCAL_ES_ADD:
4051 if (zclient->local_es_add)
4052 (*zclient->local_es_add)(command, zclient, length,
4053 vrf_id);
4054 break;
4055 case ZEBRA_LOCAL_ES_DEL:
4056 if (zclient->local_es_del)
4057 (*zclient->local_es_del)(command, zclient, length,
4058 vrf_id);
4059 break;
ce5160c0
AK
4060 case ZEBRA_LOCAL_ES_EVI_ADD:
4061 if (zclient->local_es_evi_add)
4062 (*zclient->local_es_evi_add)(command, zclient, length,
4063 vrf_id);
4064 break;
4065 case ZEBRA_LOCAL_ES_EVI_DEL:
4066 if (zclient->local_es_evi_del)
4067 (*zclient->local_es_evi_del)(command, zclient, length,
4068 vrf_id);
4069 break;
d62a17ae 4070 case ZEBRA_VNI_ADD:
4071 if (zclient->local_vni_add)
4072 (*zclient->local_vni_add)(command, zclient, length,
4073 vrf_id);
4074 break;
4075 case ZEBRA_VNI_DEL:
4076 if (zclient->local_vni_del)
4077 (*zclient->local_vni_del)(command, zclient, length,
4078 vrf_id);
4079 break;
b7cfce93
MK
4080 case ZEBRA_L3VNI_ADD:
4081 if (zclient->local_l3vni_add)
4082 (*zclient->local_l3vni_add)(command, zclient, length,
4083 vrf_id);
4084 break;
4085 case ZEBRA_L3VNI_DEL:
4086 if (zclient->local_l3vni_del)
4087 (*zclient->local_l3vni_del)(command, zclient, length,
4088 vrf_id);
4089 break;
d62a17ae 4090 case ZEBRA_MACIP_ADD:
4091 if (zclient->local_macip_add)
4092 (*zclient->local_macip_add)(command, zclient, length,
4093 vrf_id);
4094 break;
4095 case ZEBRA_MACIP_DEL:
4096 if (zclient->local_macip_del)
4097 (*zclient->local_macip_del)(command, zclient, length,
4098 vrf_id);
4099 break;
31310b25
MK
4100 case ZEBRA_IP_PREFIX_ROUTE_ADD:
4101 if (zclient->local_ip_prefix_add)
4102 (*zclient->local_ip_prefix_add)(command, zclient,
4103 length, vrf_id);
4104 break;
4105 case ZEBRA_IP_PREFIX_ROUTE_DEL:
4106 if (zclient->local_ip_prefix_del)
4107 (*zclient->local_ip_prefix_del)(command, zclient,
4108 length, vrf_id);
4109 break;
6833ae01 4110 case ZEBRA_PW_STATUS_UPDATE:
4111 if (zclient->pw_status_update)
4112 (*zclient->pw_status_update)(command, zclient, length,
4113 vrf_id);
4114 break;
7ea7b86e 4115 case ZEBRA_ROUTE_NOTIFY_OWNER:
28b11f81
DS
4116 if (zclient->route_notify_owner)
4117 (*zclient->route_notify_owner)(command, zclient, length,
4118 vrf_id);
7ea7b86e 4119 break;
b6c5d343
DS
4120 case ZEBRA_RULE_NOTIFY_OWNER:
4121 if (zclient->rule_notify_owner)
4122 (*zclient->rule_notify_owner)(command, zclient, length,
4123 vrf_id);
955bfd98 4124 break;
2f35a820
DS
4125 case ZEBRA_NHG_NOTIFY_OWNER:
4126 if (zclient->nhg_notify_owner)
4127 (*zclient->nhg_notify_owner)(command, zclient, length,
4128 vrf_id);
4129 break;
955bfd98
PZ
4130 case ZEBRA_GET_LABEL_CHUNK:
4131 if (zclient->label_chunk)
4132 (*zclient->label_chunk)(command, zclient, length,
0313523d 4133 vrf_id);
955bfd98 4134 break;
c16a0a62
PG
4135 case ZEBRA_IPSET_NOTIFY_OWNER:
4136 if (zclient->ipset_notify_owner)
4137 (*zclient->ipset_notify_owner)(command, zclient, length,
4138 vrf_id);
4139 break;
4140 case ZEBRA_IPSET_ENTRY_NOTIFY_OWNER:
4141 if (zclient->ipset_entry_notify_owner)
4142 (*zclient->ipset_entry_notify_owner)(command,
4143 zclient, length,
4144 vrf_id);
4145 break;
4146 case ZEBRA_IPTABLE_NOTIFY_OWNER:
4147 if (zclient->iptable_notify_owner)
4148 (*zclient->iptable_notify_owner)(command,
4149 zclient, length,
4150 vrf_id);
4ab3321f
AK
4151 break;
4152 case ZEBRA_VXLAN_SG_ADD:
4153 if (zclient->vxlan_sg_add)
4154 (*zclient->vxlan_sg_add)(command, zclient, length,
4155 vrf_id);
4156 break;
4157 case ZEBRA_VXLAN_SG_DEL:
4158 if (zclient->vxlan_sg_del)
4159 (*zclient->vxlan_sg_del)(command, zclient, length,
4160 vrf_id);
4161 break;
46c2687c
SK
4162 case ZEBRA_MLAG_PROCESS_UP:
4163 zclient_mlag_process_up(command, zclient, length, vrf_id);
4164 break;
4165 case ZEBRA_MLAG_PROCESS_DOWN:
4166 zclient_mlag_process_down(command, zclient, length, vrf_id);
4167 break;
4168 case ZEBRA_MLAG_FORWARD_MSG:
4169 zclient_mlag_handle_msg(command, zclient, length, vrf_id);
4170 break;
f2867068
HS
4171 case ZEBRA_SRV6_LOCATOR_ADD:
4172 if (zclient->srv6_locator_add)
4173 (*zclient->srv6_locator_add)(command, zclient, length,
4174 vrf_id);
4175 break;
4176 case ZEBRA_SRV6_LOCATOR_DELETE:
4177 if (zclient->srv6_locator_delete)
4178 (*zclient->srv6_locator_delete)(command, zclient,
4179 length, vrf_id);
4180 break;
4181 case ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK:
4182 if (zclient->process_srv6_locator_chunk)
4183 (*zclient->process_srv6_locator_chunk)(command, zclient,
4184 length, vrf_id);
4185 break;
9ab0b2a3
SW
4186 case ZEBRA_ERROR:
4187 zclient_handle_error(command, zclient, length, vrf_id);
ff491140
MS
4188 break;
4189 case ZEBRA_OPAQUE_MESSAGE:
4190 if (zclient->opaque_msg_handler)
4191 (*zclient->opaque_msg_handler)(command, zclient, length,
4192 vrf_id);
4193 break;
4194 case ZEBRA_OPAQUE_REGISTER:
4195 if (zclient->opaque_register_handler)
4196 (*zclient->opaque_register_handler)(command, zclient,
4197 length, vrf_id);
4198 break;
4199 case ZEBRA_OPAQUE_UNREGISTER:
4200 if (zclient->opaque_unregister_handler)
4201 (*zclient->opaque_unregister_handler)(command, zclient,
4202 length, vrf_id);
4203 break;
31f937fb
SM
4204 case ZEBRA_SR_POLICY_NOTIFY_STATUS:
4205 if (zclient->sr_policy_notify_status)
4206 (*zclient->sr_policy_notify_status)(command, zclient,
4207 length, vrf_id);
581e797e
KS
4208 break;
4209 case ZEBRA_CLIENT_CLOSE_NOTIFY:
4210 if (zclient->zebra_client_close_notify)
4211 (*zclient->zebra_client_close_notify)(command, zclient,
4212 length, vrf_id);
4213 break;
fda64ab4
PG
4214 case ZEBRA_NHRP_NEIGH_ADDED:
4215 if (zclient->neighbor_added)
4216 (*zclient->neighbor_added)(command, zclient, length,
4217 vrf_id);
4218 break;
4219 case ZEBRA_NHRP_NEIGH_REMOVED:
4220 if (zclient->neighbor_removed)
4221 (*zclient->neighbor_removed)(command, zclient, length,
4222 vrf_id);
4223 break;
4224 case ZEBRA_NHRP_NEIGH_GET:
4225 if (zclient->neighbor_get)
4226 (*zclient->neighbor_get)(command, zclient, length,
4227 vrf_id);
4228 break;
d17af8dd
PG
4229 case ZEBRA_GRE_UPDATE:
4230 if (zclient->gre_update)
4231 (*zclient->gre_update)(command, zclient,
4232 length, vrf_id);
4233 break;
d62a17ae 4234 default:
4235 break;
634f9ea2 4236 }
d62a17ae 4237
4238 if (zclient->sock < 0)
4239 /* Connection was closed during packet processing. */
4240 return -1;
4241
4242 /* Register read thread. */
4243 stream_reset(zclient->ibuf);
4244 zclient_event(ZCLIENT_READ, zclient);
4245
4246 return 0;
718e3744 4247}
4248
d62a17ae 4249void zclient_redistribute(int command, struct zclient *zclient, afi_t afi,
d7c0a89a 4250 int type, unsigned short instance, vrf_id_t vrf_id)
718e3744 4251{
718e3744 4252
d62a17ae 4253 if (instance) {
4254 if (command == ZEBRA_REDISTRIBUTE_ADD) {
4255 if (redist_check_instance(
4256 &zclient->mi_redist[afi][type], instance))
4257 return;
4258 redist_add_instance(&zclient->mi_redist[afi][type],
4259 instance);
4260 } else {
4261 if (!redist_check_instance(
4262 &zclient->mi_redist[afi][type], instance))
4263 return;
4264 redist_del_instance(&zclient->mi_redist[afi][type],
4265 instance);
4266 }
4267
4268 } else {
4269 if (command == ZEBRA_REDISTRIBUTE_ADD) {
4270 if (vrf_bitmap_check(zclient->redist[afi][type],
4271 vrf_id))
4272 return;
4273 vrf_bitmap_set(zclient->redist[afi][type], vrf_id);
4274 } else {
4275 if (!vrf_bitmap_check(zclient->redist[afi][type],
4276 vrf_id))
4277 return;
4278 vrf_bitmap_unset(zclient->redist[afi][type], vrf_id);
4279 }
4280 }
4281
4282 if (zclient->sock > 0)
4283 zebra_redistribute_send(command, zclient, afi, type, instance,
4284 vrf_id);
718e3744 4285}
4286
718e3744 4287
d62a17ae 4288void zclient_redistribute_default(int command, struct zclient *zclient,
49db7a7b 4289 afi_t afi, vrf_id_t vrf_id)
718e3744 4290{
718e3744 4291
d62a17ae 4292 if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) {
49db7a7b 4293 if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
d62a17ae 4294 return;
49db7a7b 4295 vrf_bitmap_set(zclient->default_information[afi], vrf_id);
d62a17ae 4296 } else {
49db7a7b
RW
4297 if (!vrf_bitmap_check(zclient->default_information[afi],
4298 vrf_id))
d62a17ae 4299 return;
49db7a7b 4300 vrf_bitmap_unset(zclient->default_information[afi], vrf_id);
d62a17ae 4301 }
4302
4303 if (zclient->sock > 0)
49db7a7b 4304 zebra_redistribute_default_send(command, zclient, afi, vrf_id);
718e3744 4305}
4306
d62a17ae 4307static void zclient_event(enum event event, struct zclient *zclient)
718e3744 4308{
d62a17ae 4309 switch (event) {
4310 case ZCLIENT_SCHEDULE:
4311 thread_add_event(zclient->master, zclient_connect, zclient, 0,
4312 &zclient->t_connect);
4313 break;
4314 case ZCLIENT_CONNECT:
4315 if (zclient_debug)
4316 zlog_debug(
4317 "zclient connect failures: %d schedule interval is now %d",
4318 zclient->fail, zclient->fail < 3 ? 10 : 60);
4319 thread_add_timer(zclient->master, zclient_connect, zclient,
4320 zclient->fail < 3 ? 10 : 60,
4321 &zclient->t_connect);
4322 break;
4323 case ZCLIENT_READ:
4324 zclient->t_read = NULL;
4325 thread_add_read(zclient->master, zclient_read, zclient,
4326 zclient->sock, &zclient->t_read);
4327 break;
4328 }
718e3744 4329}
b5114685 4330
7cfdb485
DS
4331enum zclient_send_status zclient_interface_set_master(struct zclient *client,
4332 struct interface *master,
4333 struct interface *slave)
e0ae31b8
DS
4334{
4335 struct stream *s;
4336
4337 s = client->obuf;
4338 stream_reset(s);
4339
a36898e7 4340 zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER, master->vrf_id);
e0ae31b8 4341
a36898e7 4342 stream_putl(s, master->vrf_id);
e0ae31b8 4343 stream_putl(s, master->ifindex);
a36898e7 4344 stream_putl(s, slave->vrf_id);
e0ae31b8
DS
4345 stream_putl(s, slave->ifindex);
4346
4347 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 4348 return zclient_send_message(client);
e0ae31b8 4349}
eb451ee5 4350
be7bbe52
S
4351/*
4352 * Send capabilities message to zebra
4353 */
7cfdb485
DS
4354enum zclient_send_status zclient_capabilities_send(uint32_t cmd,
4355 struct zclient *zclient,
4356 struct zapi_cap *api)
eb451ee5 4357{
be7bbe52
S
4358
4359 struct stream *s;
4360
4361 if (zclient == NULL)
7cfdb485 4362 return ZCLIENT_SEND_FAILURE;
be7bbe52
S
4363
4364 s = zclient->obuf;
4365 stream_reset(s);
4366 zclient_create_header(s, cmd, 0);
4367 stream_putl(s, api->cap);
4368
4369 switch (api->cap) {
4370 case ZEBRA_CLIENT_GR_CAPABILITIES:
4371 case ZEBRA_CLIENT_RIB_STALE_TIME:
4372 stream_putl(s, api->stale_removal_time);
4373 stream_putl(s, api->vrf_id);
4374 break;
4375 case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
4376 case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
4377 stream_putl(s, api->afi);
4378 stream_putl(s, api->safi);
4379 stream_putl(s, api->vrf_id);
4380 break;
4381 case ZEBRA_CLIENT_GR_DISABLE:
4382 stream_putl(s, api->vrf_id);
4383 break;
4384 }
4385
4386 /* Put length at the first point of the stream */
4387 stream_putw_at(s, 0, stream_get_endp(s));
4388
4389 return zclient_send_message(zclient);
4390}
4391
4392/*
4393 * Process capabilities message from zebra
4394 */
4395int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
4396{
4397
eb451ee5 4398 memset(api, 0, sizeof(*api));
4399
4400 STREAM_GETL(s, api->cap);
4401 switch (api->cap) {
4402 case ZEBRA_CLIENT_GR_CAPABILITIES:
4403 case ZEBRA_CLIENT_RIB_STALE_TIME:
be7bbe52
S
4404 STREAM_GETL(s, api->stale_removal_time);
4405 STREAM_GETL(s, api->vrf_id);
4406 break;
eb451ee5 4407 case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
4408 case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
be7bbe52
S
4409 STREAM_GETL(s, api->afi);
4410 STREAM_GETL(s, api->safi);
4411 STREAM_GETL(s, api->vrf_id);
4412 break;
eb451ee5 4413 case ZEBRA_CLIENT_GR_DISABLE:
be7bbe52
S
4414 STREAM_GETL(s, api->vrf_id);
4415 break;
eb451ee5 4416 }
4417stream_failure:
4418 return 0;
4419}
d68e74b4 4420
7cfdb485
DS
4421enum zclient_send_status
4422zclient_send_neigh_discovery_req(struct zclient *zclient,
4423 const struct interface *ifp,
4424 const struct prefix *p)
d68e74b4
JU
4425{
4426 struct stream *s;
4427
4428 s = zclient->obuf;
4429 stream_reset(s);
4430
4431 zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf_id);
4432 stream_putl(s, ifp->ifindex);
4433
4434 stream_putc(s, p->family);
4435 stream_putc(s, p->prefixlen);
4436 stream_put(s, &p->u.prefix, prefix_blen(p));
4437
4438 stream_putw_at(s, 0, stream_get_endp(s));
4439 return zclient_send_message(zclient);
4440}
224b3c8a
DS
4441
4442/*
4443 * Get a starting nhg point for a routing protocol
4444 */
4445uint32_t zclient_get_nhg_start(uint32_t proto)
4446{
4447 assert(proto < ZEBRA_ROUTE_MAX);
4448
54c89c93 4449 return ZEBRA_NHG_PROTO_SPACING * proto;
6c67f41f 4450}
61e6de9d
DS
4451
4452char *zclient_dump_route_flags(uint32_t flags, char *buf, size_t len)
4453{
4454 if (flags == 0) {
4455 snprintfrr(buf, len, "None ");
4456 return buf;
4457 }
4458
4459 snprintfrr(
4460 buf, len, "%s%s%s%s%s%s%s%s%s%s",
4461 CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion "
4462 : "",
4463 CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "",
4464 CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "",
4465 CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "",
4466 CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "",
4467 CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "",
4468 CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance "
4469 : "",
4470 CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "",
4471 CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "",
4472 CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED) ? "Offload Failed "
4473 : "");
4474 return buf;
4475}
bf902d4c
DS
4476
4477char *zclient_evpn_dump_macip_flags(uint8_t flags, char *buf, size_t len)
4478{
4479 if (flags == 0) {
4480 snprintfrr(buf, len, "None ");
4481 return buf;
4482 }
4483
4484 snprintfrr(
4485 buf, len, "%s%s%s%s%s%s%s",
4486 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? "Sticky MAC " : "",
4487 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? "Gateway MAC " : "",
4488 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? "Router "
4489 : "",
4490 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_OVERRIDE_FLAG) ? "Override "
4491 : "",
4492 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP) ? "SVI MAC " : "",
4493 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT) ? "Proxy "
4494 : "",
4495 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH) ? "Sync " : "");
4496
4497 return buf;
4498}
d603c077
PG
4499
4500static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add)
4501{
4502 uint8_t family;
4503
4504 STREAM_GETC(s, family);
4505 if (family != AF_INET && family != AF_INET6)
4506 return -1;
4507
4508 STREAM_GET(&add->ip.addr, s, family2addrsize(family));
4509 add->ipa_type = family;
4510 return 0;
4511 stream_failure:
4512 return -1;
4513}
4514
c4e1fd52
PG
4515int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
4516 union sockunion *out, struct interface *ifp,
4517 int ndm_state)
d603c077
PG
4518{
4519 int ret = 0;
4520
4521 zclient_create_header(s, cmd, ifp->vrf_id);
4522 stream_putc(s, sockunion_family(in));
4523 stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in));
4524 if (out && sockunion_family(out) != AF_UNSPEC) {
4525 stream_putc(s, sockunion_family(out));
4526 stream_write(s, sockunion_get_addr(out),
4527 sockunion_get_addrlen(out));
4528 } else
4529 stream_putc(s, AF_UNSPEC);
4530 stream_putl(s, ifp->ifindex);
4531 if (out)
c4e1fd52 4532 stream_putl(s, ndm_state);
d603c077
PG
4533 else
4534 stream_putl(s, ZEBRA_NEIGH_STATE_FAILED);
4535 return ret;
4536}
4537
4538int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api)
4539{
4540 int ret;
4541
4542 ret = zclient_neigh_ip_read_entry(s, &api->ip_in);
4543 if (ret < 0)
4544 return -1;
4545 zclient_neigh_ip_read_entry(s, &api->ip_out);
4546
4547 STREAM_GETL(s, api->index);
4548 STREAM_GETL(s, api->ndm_state);
4549 return 0;
4550 stream_failure:
4551 return -1;
4552}
d17af8dd
PG
4553
4554int zclient_send_zebra_gre_request(struct zclient *client,
4555 struct interface *ifp)
4556{
4557 struct stream *s;
d17af8dd
PG
4558
4559 if (!client || client->sock < 0) {
4560 zlog_err("%s : zclient not ready", __func__);
4561 return -1;
4562 }
4563 s = client->obuf;
4564 stream_reset(s);
4565 zclient_create_header(s,
4566 ZEBRA_GRE_GET,
4567 ifp->vrf_id);
4568 stream_putl(s, ifp->ifindex);
4569 stream_putw_at(s, 0, stream_get_endp(s));
4570 zclient_send_message(client);
4571 return 0;
d17af8dd 4572}