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