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