]> git.proxmox.com Git - mirror_frr.git/blame - lib/zclient.c
lib: Add missing enum's to switch statement
[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);
1038 stream_put(s, &api_nh->labels[0],
1039 api_nh->label_num * sizeof(mpls_label_t));
1040 }
1041
bd054c1a
DS
1042 if (api_nh->weight)
1043 stream_putl(s, api_nh->weight);
1044
68a02e06 1045 /* Router MAC for EVPN routes. */
5609e70f 1046 if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_EVPN))
68a02e06
MS
1047 stream_put(s, &(api_nh->rmac),
1048 sizeof(struct ethaddr));
1049
31f937fb
SM
1050 /* Color for Segment Routing TE. */
1051 if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
1052 stream_putl(s, api_nh->srte_color);
1053
018c6488 1054 /* Index of backup nexthop */
474aebd9
MS
1055 if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
1056 /* Validate backup count */
1057 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) {
1058 ret = -1;
1059 goto done;
1060 }
1061
1062 stream_putc(s, api_nh->backup_num);
1063 for (i = 0; i < api_nh->backup_num; i++)
1064 stream_putc(s, api_nh->backup_idx[i]);
1065 }
018c6488 1066
c60c1ade 1067 if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
cb7775a9
HS
1068 stream_putl(s, api_nh->seg6local_action);
1069 stream_write(s, &api_nh->seg6local_ctx,
1070 sizeof(struct seg6local_context));
1071 }
1072
c60c1ade 1073 if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6))
2aa01034
HS
1074 stream_write(s, &api_nh->seg6_segs,
1075 sizeof(struct in6_addr));
1076
68a02e06
MS
1077done:
1078 return ret;
1079}
1080
ac6a9479
HS
1081int zapi_srv6_locator_chunk_encode(struct stream *s,
1082 const struct srv6_locator_chunk *c)
1083{
ac6a9479
HS
1084 stream_putw(s, strlen(c->locator_name));
1085 stream_put(s, c->locator_name, strlen(c->locator_name));
1086 stream_putw(s, c->prefix.prefixlen);
1087 stream_put(s, &c->prefix.prefix, sizeof(c->prefix.prefix));
1088 stream_putc(s, c->block_bits_length);
1089 stream_putc(s, c->node_bits_length);
1090 stream_putc(s, c->function_bits_length);
1091 stream_putc(s, c->argument_bits_length);
d537287a 1092 stream_putc(s, c->flags);
ac6a9479
HS
1093 return 0;
1094}
1095
1096int zapi_srv6_locator_chunk_decode(struct stream *s,
1097 struct srv6_locator_chunk *c)
1098{
1099 uint16_t len = 0;
1100
05485926
HS
1101 c->prefix.family = AF_INET6;
1102
ac6a9479
HS
1103 STREAM_GETW(s, len);
1104 if (len > SRV6_LOCNAME_SIZE)
1105 goto stream_failure;
1106
1107 STREAM_GET(c->locator_name, s, len);
1108 STREAM_GETW(s, c->prefix.prefixlen);
1109 STREAM_GET(&c->prefix.prefix, s, sizeof(c->prefix.prefix));
1110 STREAM_GETC(s, c->block_bits_length);
1111 STREAM_GETC(s, c->node_bits_length);
1112 STREAM_GETC(s, c->function_bits_length);
1113 STREAM_GETC(s, c->argument_bits_length);
d537287a 1114 STREAM_GETC(s, c->flags);
ac6a9479
HS
1115 return 0;
1116
1117stream_failure:
1118 return -1;
1119}
1120
15588d7b
HS
1121int zapi_srv6_locator_encode(struct stream *s, const struct srv6_locator *l)
1122{
1123 stream_putw(s, strlen(l->name));
1124 stream_put(s, l->name, strlen(l->name));
1125 stream_putw(s, l->prefix.prefixlen);
1126 stream_put(s, &l->prefix.prefix, sizeof(l->prefix.prefix));
1127 return 0;
1128}
1129
1130int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
1131{
1132 uint16_t len = 0;
1133
1134 STREAM_GETW(s, len);
1135 if (len > SRV6_LOCNAME_SIZE)
1136 goto stream_failure;
1137
1138 STREAM_GET(l->name, s, len);
1139 STREAM_GETW(s, l->prefix.prefixlen);
1140 STREAM_GET(&l->prefix.prefix, s, sizeof(l->prefix.prefix));
1141 l->prefix.family = AF_INET6;
1142 return 0;
1143
1144stream_failure:
1145 return -1;
1146}
1147
5898ce6f 1148static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
2f35a820 1149{
21735352
SW
1150 int i;
1151
c6ce9334
SW
1152 if (cmd != ZEBRA_NHG_DEL && cmd != ZEBRA_NHG_ADD) {
1153 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1154 "%s: Specified zapi NHG command (%d) doesn't exist",
c6ce9334
SW
1155 __func__, cmd);
1156 return -1;
1157 }
2f35a820 1158
5898ce6f
MS
1159 if (api_nhg->nexthop_num >= MULTIPATH_NUM ||
1160 api_nhg->backup_nexthop_num >= MULTIPATH_NUM) {
1161 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1162 "%s: zapi NHG encode with invalid input", __func__);
5898ce6f
MS
1163 return -1;
1164 }
1165
2f35a820 1166 stream_reset(s);
c6ce9334 1167 zclient_create_header(s, cmd, VRF_DEFAULT);
2f35a820 1168
21735352 1169 stream_putw(s, api_nhg->proto);
c6ce9334 1170 stream_putl(s, api_nhg->id);
2f35a820 1171
ca2b3467
DS
1172 stream_putw(s, api_nhg->resilience.buckets);
1173 stream_putl(s, api_nhg->resilience.idle_timer);
1174 stream_putl(s, api_nhg->resilience.unbalanced_timer);
1175
c6ce9334 1176 if (cmd == ZEBRA_NHG_ADD) {
21735352 1177 /* Nexthops */
c6ce9334
SW
1178 zapi_nexthop_group_sort(api_nhg->nexthops,
1179 api_nhg->nexthop_num);
2f35a820 1180
c6ce9334 1181 stream_putw(s, api_nhg->nexthop_num);
2f35a820 1182
21735352 1183 for (i = 0; i < api_nhg->nexthop_num; i++)
c6ce9334 1184 zapi_nexthop_encode(s, &api_nhg->nexthops[i], 0, 0);
21735352
SW
1185
1186 /* Backup nexthops */
21735352
SW
1187 stream_putw(s, api_nhg->backup_nexthop_num);
1188
1189 for (i = 0; i < api_nhg->backup_nexthop_num; i++)
1190 zapi_nexthop_encode(s, &api_nhg->backup_nexthops[i], 0,
1191 0);
2f35a820
DS
1192 }
1193
1194 stream_putw_at(s, 0, stream_get_endp(s));
c6ce9334
SW
1195
1196 return 0;
2f35a820
DS
1197}
1198
7cfdb485
DS
1199enum zclient_send_status zclient_nhg_send(struct zclient *zclient, int cmd,
1200 struct zapi_nhg *api_nhg)
2f35a820 1201{
21735352
SW
1202 api_nhg->proto = zclient->redist_default;
1203
1204 if (zapi_nhg_encode(zclient->obuf, cmd, api_nhg))
c6ce9334 1205 return -1;
2f35a820 1206
c6ce9334 1207 return zclient_send_message(zclient);
2f35a820
DS
1208}
1209
d7c0a89a 1210int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
0e51b4a3
RW
1211{
1212 struct zapi_nexthop *api_nh;
d62a17ae 1213 int i;
1214 int psize;
d62a17ae 1215
d62a17ae 1216 stream_reset(s);
d62a17ae 1217 zclient_create_header(s, cmd, api->vrf_id);
1218
e4081c0e
RW
1219 if (api->type >= ZEBRA_ROUTE_MAX) {
1220 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1221 "%s: Specified route type (%u) is not a legal value",
15569c58 1222 __func__, api->type);
e4081c0e
RW
1223 return -1;
1224 }
d62a17ae 1225 stream_putc(s, api->type);
e4081c0e 1226
d62a17ae 1227 stream_putw(s, api->instance);
1228 stream_putl(s, api->flags);
31f937fb 1229 stream_putl(s, api->message);
e4081c0e
RW
1230
1231 if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
1232 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1233 "%s: Specified route SAFI (%u) is not a legal value",
15569c58 1234 __func__, api->safi);
e4081c0e
RW
1235 return -1;
1236 }
832d0f56 1237 stream_putc(s, api->safi);
d62a17ae 1238
1239 /* Put prefix information. */
0e51b4a3 1240 stream_putc(s, api->prefix.family);
bb1b9c47
RW
1241 psize = PSIZE(api->prefix.prefixlen);
1242 stream_putc(s, api->prefix.prefixlen);
c4efd0f4 1243 stream_write(s, &api->prefix.u.prefix, psize);
d62a17ae 1244
1245 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
bb1b9c47
RW
1246 psize = PSIZE(api->src_prefix.prefixlen);
1247 stream_putc(s, api->src_prefix.prefixlen);
d7c0a89a 1248 stream_write(s, (uint8_t *)&api->src_prefix.prefix, psize);
d62a17ae 1249 }
1250
27141ea9
DS
1251 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG))
1252 stream_putl(s, api->nhgid);
1253
0e51b4a3 1254 /* Nexthops. */
d62a17ae 1255 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
bb1b9c47
RW
1256 /* limit the number of nexthops if necessary */
1257 if (api->nexthop_num > MULTIPATH_NUM) {
ade6974d 1258 flog_err(
450971aa 1259 EC_LIB_ZAPI_ENCODE,
2dbe669b
DA
1260 "%s: prefix %pFX: can't encode %u nexthops (maximum is %u)",
1261 __func__, &api->prefix, api->nexthop_num,
1262 MULTIPATH_NUM);
a74e593b 1263 return -1;
bb1b9c47
RW
1264 }
1265
018c6488
MS
1266 /* We canonicalize the nexthops by sorting them; this allows
1267 * zebra to resolve the list of nexthops to a nexthop-group
1268 * more efficiently.
1269 */
3c6e0bd4
SW
1270 zapi_nexthop_group_sort(api->nexthops, api->nexthop_num);
1271
b5f79651 1272 stream_putw(s, api->nexthop_num);
d62a17ae 1273
1274 for (i = 0; i < api->nexthop_num; i++) {
bb1b9c47
RW
1275 api_nh = &api->nexthops[i];
1276
52dd3aa4 1277 /* MPLS labels for BGP-LU or Segment Routing */
68a02e06 1278 if (api_nh->label_num > MPLS_MAX_LABELS) {
2dbe669b
DA
1279 flog_err(
1280 EC_LIB_ZAPI_ENCODE,
1281 "%s: prefix %pFX: can't encode %u labels (maximum is %u)",
1282 __func__, &api->prefix,
1283 api_nh->label_num, MPLS_MAX_LABELS);
68a02e06 1284 return -1;
52dd3aa4 1285 }
a317a9b9 1286
31f937fb
SM
1287 if (zapi_nexthop_encode(s, api_nh, api->flags,
1288 api->message)
1289 != 0)
68a02e06 1290 return -1;
d62a17ae 1291 }
1292 }
1293
018c6488
MS
1294 /* Backup nexthops */
1295 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
1296 /* limit the number of nexthops if necessary */
1297 if (api->backup_nexthop_num > MULTIPATH_NUM) {
018c6488
MS
1298 flog_err(
1299 EC_LIB_ZAPI_ENCODE,
2dbe669b
DA
1300 "%s: prefix %pFX: can't encode %u backup nexthops (maximum is %u)",
1301 __func__, &api->prefix, api->backup_nexthop_num,
018c6488
MS
1302 MULTIPATH_NUM);
1303 return -1;
1304 }
1305
1306 /* Note that we do not sort the list of backup nexthops -
1307 * this list is treated as an array and indexed by each
1308 * primary nexthop that is associated with a backup.
1309 */
1310
1311 stream_putw(s, api->backup_nexthop_num);
1312
1313 for (i = 0; i < api->backup_nexthop_num; i++) {
1314 api_nh = &api->backup_nexthops[i];
1315
1316 /* MPLS labels for BGP-LU or Segment Routing */
1317 if (api_nh->label_num > MPLS_MAX_LABELS) {
2dbe669b
DA
1318 flog_err(
1319 EC_LIB_ZAPI_ENCODE,
1320 "%s: prefix %pFX: backup: can't encode %u labels (maximum is %u)",
1321 __func__, &api->prefix,
1322 api_nh->label_num, MPLS_MAX_LABELS);
018c6488
MS
1323 return -1;
1324 }
1325
31f937fb
SM
1326 if (zapi_nexthop_encode(s, api_nh, api->flags,
1327 api->message)
1328 != 0)
018c6488
MS
1329 return -1;
1330 }
1331 }
1332
0e51b4a3 1333 /* Attributes. */
d62a17ae 1334 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
1335 stream_putc(s, api->distance);
1336 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
1337 stream_putl(s, api->metric);
1338 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
1339 stream_putl(s, api->tag);
1340 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
1341 stream_putl(s, api->mtu);
ba1849ef
DS
1342 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID))
1343 stream_putl(s, api->tableid);
d62a17ae 1344
71c4870b 1345 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_OPAQUE)) {
1ae0e1b3
DS
1346 if (api->opaque.length > ZAPI_MESSAGE_OPAQUE_LENGTH) {
1347 flog_err(
1348 EC_LIB_ZAPI_ENCODE,
1349 "%s: opaque length %u is greater than allowed value",
1350 __func__, api->opaque.length);
1351 return -1;
1352 }
71c4870b
DS
1353
1354 stream_putw(s, api->opaque.length);
1355 stream_write(s, api->opaque.data, api->opaque.length);
1356 }
d62a17ae 1357 /* Put length at the first point of the stream. */
1358 stream_putw_at(s, 0, stream_get_endp(s));
1359
0e51b4a3
RW
1360 return 0;
1361}
1362
68a02e06
MS
1363/*
1364 * Decode a single zapi nexthop object
1365 */
2f35a820
DS
1366int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
1367 uint32_t api_flags, uint32_t api_message)
68a02e06 1368{
474aebd9 1369 int i, ret = -1;
68a02e06
MS
1370
1371 STREAM_GETL(s, api_nh->vrf_id);
1372 STREAM_GETC(s, api_nh->type);
1373
1374 /* Note that we're only using a single octet of flags */
1375 STREAM_GETC(s, api_nh->flags);
1376
1377 switch (api_nh->type) {
1378 case NEXTHOP_TYPE_BLACKHOLE:
1379 STREAM_GETC(s, api_nh->bh_type);
1380 break;
1381 case NEXTHOP_TYPE_IPV4:
68a02e06
MS
1382 case NEXTHOP_TYPE_IPV4_IFINDEX:
1383 STREAM_GET(&api_nh->gate.ipv4.s_addr, s,
1384 IPV4_MAX_BYTELEN);
1385 STREAM_GETL(s, api_nh->ifindex);
1386 break;
1387 case NEXTHOP_TYPE_IFINDEX:
1388 STREAM_GETL(s, api_nh->ifindex);
1389 break;
1390 case NEXTHOP_TYPE_IPV6:
68a02e06
MS
1391 case NEXTHOP_TYPE_IPV6_IFINDEX:
1392 STREAM_GET(&api_nh->gate.ipv6, s, 16);
1393 STREAM_GETL(s, api_nh->ifindex);
1394 break;
1395 }
1396
1397 /* MPLS labels for BGP-LU or Segment Routing */
1398 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)) {
1399 STREAM_GETC(s, api_nh->label_num);
1400 if (api_nh->label_num > MPLS_MAX_LABELS) {
1401 flog_err(
1402 EC_LIB_ZAPI_ENCODE,
1403 "%s: invalid number of MPLS labels (%u)",
1404 __func__, api_nh->label_num);
1405 return -1;
1406 }
1407
1408 STREAM_GET(&api_nh->labels[0], s,
1409 api_nh->label_num * sizeof(mpls_label_t));
1410 }
1411
bd054c1a
DS
1412 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
1413 STREAM_GETL(s, api_nh->weight);
1414
68a02e06 1415 /* Router MAC for EVPN routes. */
5609e70f 1416 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
68a02e06
MS
1417 STREAM_GET(&(api_nh->rmac), s,
1418 sizeof(struct ethaddr));
1419
31f937fb
SM
1420 /* Color for Segment Routing TE. */
1421 if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
1422 STREAM_GETL(s, api_nh->srte_color);
1423
018c6488 1424 /* Backup nexthop index */
474aebd9
MS
1425 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
1426 STREAM_GETC(s, api_nh->backup_num);
1427
1428 if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS)
1429 return -1;
1430
1431 for (i = 0; i < api_nh->backup_num; i++)
1432 STREAM_GETC(s, api_nh->backup_idx[i]);
1433 }
018c6488 1434
c60c1ade 1435 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
cb7775a9
HS
1436 STREAM_GETL(s, api_nh->seg6local_action);
1437 STREAM_GET(&api_nh->seg6local_ctx, s,
1438 sizeof(struct seg6local_context));
1439 }
1440
c60c1ade 1441 if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6))
2aa01034
HS
1442 STREAM_GET(&api_nh->seg6_segs, s,
1443 sizeof(struct in6_addr));
1444
68a02e06
MS
1445 /* Success */
1446 ret = 0;
1447
1448stream_failure:
1449
1450 return ret;
1451}
1452
0e51b4a3
RW
1453int zapi_route_decode(struct stream *s, struct zapi_route *api)
1454{
1455 struct zapi_nexthop *api_nh;
1456 int i;
1457
1458 memset(api, 0, sizeof(*api));
1459
1460 /* Type, flags, message. */
ec93aa12 1461 STREAM_GETC(s, api->type);
e4081c0e 1462 if (api->type >= ZEBRA_ROUTE_MAX) {
450971aa 1463 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1464 "%s: Specified route type: %d is not a legal value",
15569c58 1465 __func__, api->type);
ec93aa12
DS
1466 return -1;
1467 }
1468
1469 STREAM_GETW(s, api->instance);
1470 STREAM_GETL(s, api->flags);
31f937fb 1471 STREAM_GETL(s, api->message);
832d0f56 1472 STREAM_GETC(s, api->safi);
e4081c0e
RW
1473 if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
1474 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 1475 "%s: Specified route SAFI (%u) is not a legal value",
15569c58 1476 __func__, api->safi);
e4081c0e
RW
1477 return -1;
1478 }
0e51b4a3
RW
1479
1480 /* Prefix. */
ec93aa12
DS
1481 STREAM_GETC(s, api->prefix.family);
1482 STREAM_GETC(s, api->prefix.prefixlen);
0e51b4a3
RW
1483 switch (api->prefix.family) {
1484 case AF_INET:
936fbaef 1485 if (api->prefix.prefixlen > IPV4_MAX_BITLEN) {
ade6974d 1486 flog_err(
450971aa 1487 EC_LIB_ZAPI_ENCODE,
ade6974d 1488 "%s: V4 prefixlen is %d which should not be more than 32",
15569c58 1489 __func__, api->prefix.prefixlen);
ec93aa12
DS
1490 return -1;
1491 }
0e51b4a3
RW
1492 break;
1493 case AF_INET6:
f4d81e55 1494 if (api->prefix.prefixlen > IPV6_MAX_BITLEN) {
ade6974d 1495 flog_err(
450971aa 1496 EC_LIB_ZAPI_ENCODE,
ade6974d 1497 "%s: v6 prefixlen is %d which should not be more than 128",
15569c58 1498 __func__, api->prefix.prefixlen);
ec93aa12
DS
1499 return -1;
1500 }
0e51b4a3 1501 break;
ec93aa12 1502 default:
450971aa 1503 flog_err(EC_LIB_ZAPI_ENCODE,
15569c58
DA
1504 "%s: Specified family %d is not v4 or v6", __func__,
1505 api->prefix.family);
ec93aa12 1506 return -1;
0e51b4a3 1507 }
ec93aa12
DS
1508 STREAM_GET(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen));
1509
0e51b4a3
RW
1510 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
1511 api->src_prefix.family = AF_INET6;
ec93aa12 1512 STREAM_GETC(s, api->src_prefix.prefixlen);
f4d81e55 1513 if (api->src_prefix.prefixlen > IPV6_MAX_BITLEN) {
ade6974d 1514 flog_err(
450971aa 1515 EC_LIB_ZAPI_ENCODE,
ade6974d 1516 "%s: SRC Prefix prefixlen received: %d is too large",
15569c58 1517 __func__, api->src_prefix.prefixlen);
ec93aa12
DS
1518 return -1;
1519 }
1520 STREAM_GET(&api->src_prefix.prefix, s,
0e51b4a3
RW
1521 PSIZE(api->src_prefix.prefixlen));
1522
1523 if (api->prefix.family != AF_INET6
ec93aa12 1524 || api->src_prefix.prefixlen == 0) {
ade6974d 1525 flog_err(
450971aa 1526 EC_LIB_ZAPI_ENCODE,
ade6974d 1527 "%s: SRC prefix specified in some manner that makes no sense",
15569c58 1528 __func__);
ec93aa12
DS
1529 return -1;
1530 }
0e51b4a3
RW
1531 }
1532
27141ea9
DS
1533 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG))
1534 STREAM_GETL(s, api->nhgid);
1535
0e51b4a3
RW
1536 /* Nexthops. */
1537 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
ec93aa12 1538 STREAM_GETW(s, api->nexthop_num);
0e51b4a3 1539 if (api->nexthop_num > MULTIPATH_NUM) {
450971aa 1540 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
1541 "%s: invalid number of nexthops (%u)",
1542 __func__, api->nexthop_num);
0e51b4a3
RW
1543 return -1;
1544 }
1545
1546 for (i = 0; i < api->nexthop_num; i++) {
1547 api_nh = &api->nexthops[i];
1548
31f937fb
SM
1549 if (zapi_nexthop_decode(s, api_nh, api->flags,
1550 api->message)
1551 != 0)
68a02e06 1552 return -1;
0e51b4a3
RW
1553 }
1554 }
1555
018c6488
MS
1556 /* Backup nexthops. */
1557 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS)) {
1558 STREAM_GETW(s, api->backup_nexthop_num);
1559 if (api->backup_nexthop_num > MULTIPATH_NUM) {
1560 flog_err(EC_LIB_ZAPI_ENCODE,
1561 "%s: invalid number of backup nexthops (%u)",
1562 __func__, api->backup_nexthop_num);
1563 return -1;
1564 }
1565
1566 for (i = 0; i < api->backup_nexthop_num; i++) {
1567 api_nh = &api->backup_nexthops[i];
1568
31f937fb
SM
1569 if (zapi_nexthop_decode(s, api_nh, api->flags,
1570 api->message)
1571 != 0)
018c6488
MS
1572 return -1;
1573 }
1574 }
1575
0e51b4a3
RW
1576 /* Attributes. */
1577 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
ec93aa12 1578 STREAM_GETC(s, api->distance);
0e51b4a3 1579 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
ec93aa12 1580 STREAM_GETL(s, api->metric);
0e51b4a3 1581 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
ec93aa12 1582 STREAM_GETL(s, api->tag);
0e51b4a3 1583 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
ec93aa12 1584 STREAM_GETL(s, api->mtu);
ba1849ef
DS
1585 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID))
1586 STREAM_GETL(s, api->tableid);
0e51b4a3 1587
71c4870b
DS
1588 if (CHECK_FLAG(api->message, ZAPI_MESSAGE_OPAQUE)) {
1589 STREAM_GETW(s, api->opaque.length);
1ae0e1b3
DS
1590 if (api->opaque.length > ZAPI_MESSAGE_OPAQUE_LENGTH) {
1591 flog_err(
1592 EC_LIB_ZAPI_ENCODE,
1593 "%s: opaque length %u is greater than allowed value",
1594 __func__, api->opaque.length);
1595 return -1;
1596 }
71c4870b
DS
1597
1598 STREAM_GET(api->opaque.data, s, api->opaque.length);
1599 }
1600
0e51b4a3 1601 return 0;
6a2b0d9a
RW
1602stream_failure:
1603 return -1;
657cde12
DS
1604}
1605
0313523d
FR
1606static void zapi_encode_prefix(struct stream *s, struct prefix *p,
1607 uint8_t family)
0031a6bb
PG
1608{
1609 struct prefix any;
1610
1611 if (!p) {
1612 memset(&any, 0, sizeof(any));
1613 any.family = family;
1614 p = &any;
1615 }
1616
1617 stream_putc(s, p->family);
1618 stream_putc(s, p->prefixlen);
1619 stream_put(s, &p->u.prefix, prefix_blen(p));
1620}
1621
0313523d 1622int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule)
0031a6bb
PG
1623{
1624 stream_reset(s);
1625 zclient_create_header(s, cmd, zrule->vrf_id);
1626
1627 /*
1628 * We are sending one item at a time at the moment
1629 */
1630 stream_putl(s, 1);
1631
1632 stream_putl(s, zrule->seq);
1633 stream_putl(s, zrule->priority);
1634 stream_putl(s, zrule->unique);
1635
1636 zapi_encode_prefix(s, &(zrule->filter.src_ip),
1637 zrule->filter.src_ip.family);
0313523d 1638 stream_putw(s, zrule->filter.src_port); /* src port */
0031a6bb
PG
1639 zapi_encode_prefix(s, &(zrule->filter.dst_ip),
1640 zrule->filter.src_ip.family);
0313523d
FR
1641 stream_putw(s, zrule->filter.dst_port); /* dst port */
1642 stream_putw(s, zrule->filter.fwmark); /* fwmark */
0031a6bb
PG
1643
1644 stream_putl(s, zrule->action.table);
58a1d249 1645 stream_put(s, zrule->ifname, INTERFACE_NAMSIZ);
0031a6bb
PG
1646
1647 /* Put length at the first point of the stream. */
1648 stream_putw_at(s, 0, stream_get_endp(s));
1649
1650 return 0;
1651}
1652
dfacea4a
SY
1653int zapi_tc_qdisc_encode(uint8_t cmd, struct stream *s, struct tc_qdisc *qdisc)
1654{
1655 stream_reset(s);
1656 zclient_create_header(s, cmd, VRF_DEFAULT);
1657
1658
1659 stream_putl(s, 1);
1660
1661 stream_putl(s, qdisc->ifindex);
1662 stream_putl(s, qdisc->kind);
1663
1664 stream_putw_at(s, 0, stream_get_endp(s));
1665
1666 return 0;
1667}
1668
1669int zapi_tc_class_encode(uint8_t cmd, struct stream *s, struct tc_class *class)
1670{
1671 stream_reset(s);
1672 zclient_create_header(s, cmd, VRF_DEFAULT);
1673
1674 stream_putl(s, 1);
1675
1676 stream_putl(s, class->ifindex);
1677 stream_putl(s, class->handle);
1678 stream_putl(s, class->kind);
1679
1680 switch (class->kind) {
1681 case TC_QDISC_HTB:
1682 stream_putq(s, class->u.htb.rate);
1683 stream_putq(s, class->u.htb.ceil);
1684 break;
bde30e78
DS
1685 case TC_QDISC_UNSPEC:
1686 case TC_QDISC_NOQUEUE:
dfacea4a
SY
1687 /* not implemented */
1688 break;
1689 }
1690 stream_putw_at(s, 0, stream_get_endp(s));
1691
1692 return 0;
1693}
1694
1695int zapi_tc_filter_encode(uint8_t cmd, struct stream *s,
1696 struct tc_filter *filter)
1697{
1698 stream_reset(s);
1699 zclient_create_header(s, cmd, VRF_DEFAULT);
1700
1701 stream_putl(s, 1);
1702
1703 stream_putl(s, filter->ifindex);
1704 stream_putl(s, filter->handle);
1705 stream_putl(s, filter->priority);
1706 stream_putl(s, filter->protocol);
1707 stream_putl(s, filter->kind);
1708
1709 switch (filter->kind) {
1710 case TC_FILTER_FLOWER:
1711 stream_putl(s, filter->u.flower.filter_bm);
1712 if (filter->u.flower.filter_bm & TC_FLOWER_IP_PROTOCOL)
1713 stream_putc(s, filter->u.flower.ip_proto);
1714 if (filter->u.flower.filter_bm & TC_FLOWER_SRC_IP)
1715 zapi_encode_prefix(s, &filter->u.flower.src_ip,
1716 filter->u.flower.src_ip.family);
1717 if (filter->u.flower.filter_bm & TC_FLOWER_SRC_PORT) {
1718 stream_putw(s, filter->u.flower.src_port_min);
1719 stream_putw(s, filter->u.flower.src_port_max);
1720 }
1721 if (filter->u.flower.filter_bm & TC_FLOWER_DST_IP)
1722 zapi_encode_prefix(s, &filter->u.flower.dst_ip,
1723 filter->u.flower.dst_ip.family);
1724 if (filter->u.flower.filter_bm & TC_FLOWER_DST_PORT) {
1725 stream_putw(s, filter->u.flower.dst_port_min);
1726 stream_putw(s, filter->u.flower.dst_port_max);
1727 }
1728 if (filter->u.flower.filter_bm & TC_FLOWER_DSFIELD) {
1729 stream_putc(s, filter->u.flower.dsfield);
1730 stream_putc(s, filter->u.flower.dsfield_mask);
1731 }
1732 stream_putl(s, filter->u.flower.classid);
1733 break;
bde30e78
DS
1734 case TC_FILTER_UNSPEC:
1735 case TC_FILTER_BPF:
1736 case TC_FILTER_FLOW:
1737 case TC_FILTER_U32:
dfacea4a
SY
1738 /* not implemented */
1739 break;
1740 }
1741
1742 stream_putw_at(s, 0, stream_get_endp(s));
1743
1744 return 0;
1745}
1746
2f35a820
DS
1747bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id,
1748 enum zapi_nhg_notify_owner *note)
1749{
2c7819b9 1750 uint32_t read_id;
2f35a820 1751
2f35a820 1752 STREAM_GET(note, s, sizeof(*note));
2c7819b9 1753 STREAM_GETL(s, read_id);
2f35a820
DS
1754
1755 *id = read_id;
1756
1757 return true;
1758
1759stream_failure:
1760 return false;
1761}
1762
7ea7b86e 1763bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
28610f7e 1764 uint32_t *tableid,
77b38a4a
S
1765 enum zapi_route_notify_owner *note,
1766 afi_t *afi, safi_t *safi)
7ea7b86e 1767{
7a1eb44b 1768 uint32_t t;
77b38a4a
S
1769 afi_t afi_val;
1770 safi_t safi_val;
7a1eb44b 1771
7ea7b86e
DS
1772 STREAM_GET(note, s, sizeof(*note));
1773
1774 STREAM_GETC(s, p->family);
1775 STREAM_GETC(s, p->prefixlen);
996c9314 1776 STREAM_GET(&p->u.prefix, s, prefix_blen(p));
7a1eb44b 1777 STREAM_GETL(s, t);
77b38a4a
S
1778 STREAM_GETC(s, afi_val);
1779 STREAM_GETC(s, safi_val);
7a1eb44b
DS
1780
1781 *tableid = t;
7ea7b86e 1782
77b38a4a
S
1783 if (afi)
1784 *afi = afi_val;
1785 if (safi)
1786 *safi = safi_val;
1787
7ea7b86e
DS
1788 return true;
1789
1790stream_failure:
1791 return false;
1792}
1793
b6c5d343 1794bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
58a1d249 1795 uint32_t *priority, uint32_t *unique, char *ifname,
b6c5d343
DS
1796 enum zapi_rule_notify_owner *note)
1797{
1798 uint32_t prio, seq, uni;
b6c5d343
DS
1799
1800 STREAM_GET(note, s, sizeof(*note));
1801
1802 STREAM_GETL(s, seq);
1803 STREAM_GETL(s, prio);
1804 STREAM_GETL(s, uni);
58a1d249 1805 STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
b6c5d343
DS
1806
1807 if (zclient_debug)
58a1d249 1808 zlog_debug("%s: %u %u %u %s", __func__, seq, prio, uni, ifname);
b6c5d343
DS
1809 *seqno = seq;
1810 *priority = prio;
1811 *unique = uni;
b6c5d343
DS
1812
1813 return true;
1814
1815stream_failure:
1816 return false;
1817}
1818
0313523d
FR
1819bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique,
1820 enum zapi_ipset_notify_owner *note)
425bdd6b
PG
1821{
1822 uint32_t uni;
ef524230 1823 uint16_t notew;
425bdd6b 1824
ef524230 1825 STREAM_GETW(s, notew);
425bdd6b
PG
1826
1827 STREAM_GETL(s, uni);
1828
1829 if (zclient_debug)
15569c58 1830 zlog_debug("%s: %u", __func__, uni);
425bdd6b 1831 *unique = uni;
ef524230 1832 *note = (enum zapi_ipset_notify_owner)notew;
425bdd6b
PG
1833 return true;
1834
1835stream_failure:
1836 return false;
1837}
1838
0313523d
FR
1839bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
1840 char *ipset_name,
1841 enum zapi_ipset_entry_notify_owner *note)
425bdd6b
PG
1842{
1843 uint32_t uni;
ef524230 1844 uint16_t notew;
425bdd6b 1845
ef524230 1846 STREAM_GETW(s, notew);
425bdd6b
PG
1847
1848 STREAM_GETL(s, uni);
1849
0313523d 1850 STREAM_GET(ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
425bdd6b
PG
1851
1852 if (zclient_debug)
15569c58 1853 zlog_debug("%s: %u", __func__, uni);
425bdd6b 1854 *unique = uni;
ef524230 1855 *note = (enum zapi_ipset_entry_notify_owner)notew;
425bdd6b
PG
1856
1857 return true;
1858
1859stream_failure:
1860 return false;
1861}
1862
c16a0a62
PG
1863bool zapi_iptable_notify_decode(struct stream *s,
1864 uint32_t *unique,
1865 enum zapi_iptable_notify_owner *note)
1866{
1867 uint32_t uni;
ef524230 1868 uint16_t notew;
c16a0a62 1869
ef524230 1870 STREAM_GETW(s, notew);
c16a0a62
PG
1871
1872 STREAM_GETL(s, uni);
1873
1874 if (zclient_debug)
15569c58 1875 zlog_debug("%s: %u", __func__, uni);
c16a0a62 1876 *unique = uni;
ef524230 1877 *note = (enum zapi_iptable_notify_owner)notew;
c16a0a62
PG
1878
1879 return true;
1880
1881stream_failure:
1882 return false;
1883}
1884
e4a1ec74 1885struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
4a749e2c
DS
1886{
1887 struct nexthop *n = nexthop_new();
1888
1889 n->type = znh->type;
4a7371e9 1890 n->vrf_id = znh->vrf_id;
4a749e2c
DS
1891 n->ifindex = znh->ifindex;
1892 n->gate = znh->gate;
31f937fb 1893 n->srte_color = znh->srte_color;
4a749e2c
DS
1894
1895 /*
960035b2 1896 * This function currently handles labels
4a749e2c 1897 */
960035b2
PZ
1898 if (znh->label_num) {
1899 nexthop_add_labels(n, ZEBRA_LSP_NONE, znh->label_num,
0313523d 1900 znh->labels);
960035b2 1901 }
4a749e2c 1902
0a8881b4
MS
1903 if (CHECK_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
1904 SET_FLAG(n->flags, NEXTHOP_FLAG_HAS_BACKUP);
474aebd9
MS
1905 n->backup_num = znh->backup_num;
1906 memcpy(n->backup_idx, znh->backup_idx, n->backup_num);
0a8881b4
MS
1907 }
1908
eab0f8f0
HS
1909 if (znh->seg6local_action != ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
1910 nexthop_add_srv6_seg6local(n, znh->seg6local_action,
1911 &znh->seg6local_ctx);
cb7775a9 1912
eab0f8f0
HS
1913 if (!sid_zero(&znh->seg6_segs))
1914 nexthop_add_srv6_seg6(n, &znh->seg6_segs);
2aa01034 1915
4a749e2c
DS
1916 return n;
1917}
1918
68a02e06
MS
1919/*
1920 * Convert nexthop to zapi nexthop
1921 */
1922int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
1923 const struct nexthop *nh)
1924{
1925 int i;
1926
1927 memset(znh, 0, sizeof(*znh));
1928
1929 znh->type = nh->type;
1930 znh->vrf_id = nh->vrf_id;
1df3b1dc 1931 znh->weight = nh->weight;
68a02e06
MS
1932 znh->ifindex = nh->ifindex;
1933 znh->gate = nh->gate;
1934
e90284d7
SW
1935 if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK))
1936 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
1937
5609e70f
XL
1938 if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_EVPN))
1939 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_EVPN);
1940
68a02e06 1941 if (nh->nh_label && (nh->nh_label->num_labels > 0)) {
018c6488
MS
1942
1943 /* Validate */
1944 if (nh->nh_label->num_labels > MPLS_MAX_LABELS)
1945 return -1;
1946
68a02e06
MS
1947 for (i = 0; i < nh->nh_label->num_labels; i++)
1948 znh->labels[i] = nh->nh_label->label[i];
1949
1950 znh->label_num = i;
1951 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_LABEL);
1952 }
1953
0a8881b4 1954 if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
474aebd9
MS
1955 if (nh->backup_num > NEXTHOP_MAX_BACKUPS)
1956 return -1;
1957
0a8881b4 1958 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
474aebd9
MS
1959 znh->backup_num = nh->backup_num;
1960 memcpy(znh->backup_idx, nh->backup_idx, znh->backup_num);
0a8881b4
MS
1961 }
1962
eab0f8f0
HS
1963 if (nh->nh_srv6) {
1964 if (nh->nh_srv6->seg6local_action !=
1965 ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) {
c60c1ade 1966 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
eab0f8f0
HS
1967 znh->seg6local_action = nh->nh_srv6->seg6local_action;
1968 memcpy(&znh->seg6local_ctx,
1969 &nh->nh_srv6->seg6local_ctx,
1970 sizeof(struct seg6local_context));
1971 }
cb7775a9 1972
c60c1ade
HS
1973 if (!sid_zero(&nh->nh_srv6->seg6_segs)) {
1974 SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
eab0f8f0
HS
1975 memcpy(&znh->seg6_segs, &nh->nh_srv6->seg6_segs,
1976 sizeof(struct in6_addr));
c60c1ade 1977 }
eab0f8f0 1978 }
2aa01034 1979
68a02e06
MS
1980 return 0;
1981}
1982
0a8881b4
MS
1983/*
1984 * Wrapper that converts backup nexthop
1985 */
1986int zapi_backup_nexthop_from_nexthop(struct zapi_nexthop *znh,
1987 const struct nexthop *nh)
1988{
1989 int ret;
1990
1991 /* Ensure that zapi flags are correct: backups don't have backups */
1992 ret = zapi_nexthop_from_nexthop(znh, nh);
1993 if (ret == 0)
1994 UNSET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
1995
1996 return ret;
1997}
1998
ae076fc2
MS
1999/*
2000 * Format some info about a zapi nexthop, for debug or logging.
2001 */
2002const char *zapi_nexthop2str(const struct zapi_nexthop *znh, char *buf,
2003 int bufsize)
2004{
2005 char tmp[INET6_ADDRSTRLEN];
2006
2007 switch (znh->type) {
2008 case NEXTHOP_TYPE_IFINDEX:
2009 snprintf(buf, bufsize, "if %u", znh->ifindex);
2010 break;
2011 case NEXTHOP_TYPE_IPV4:
2012 case NEXTHOP_TYPE_IPV4_IFINDEX:
2013 inet_ntop(AF_INET, &znh->gate.ipv4, tmp, sizeof(tmp));
2014 snprintf(buf, bufsize, "%s if %u", tmp, znh->ifindex);
2015 break;
2016 case NEXTHOP_TYPE_IPV6:
2017 case NEXTHOP_TYPE_IPV6_IFINDEX:
2018 inet_ntop(AF_INET6, &znh->gate.ipv6, tmp, sizeof(tmp));
2019 snprintf(buf, bufsize, "%s if %u", tmp, znh->ifindex);
2020 break;
2021 case NEXTHOP_TYPE_BLACKHOLE:
2022 snprintf(buf, bufsize, "blackhole");
2023 break;
2024 default:
2025 snprintf(buf, bufsize, "unknown");
2026 break;
2027 }
2028
2029 return buf;
2030}
2031
68a02e06
MS
2032/*
2033 * Decode the nexthop-tracking update message
2034 */
06e4e901
DS
2035bool zapi_nexthop_update_decode(struct stream *s, struct prefix *match,
2036 struct zapi_route *nhr)
4a749e2c
DS
2037{
2038 uint32_t i;
2039
2040 memset(nhr, 0, sizeof(*nhr));
2041
31f937fb 2042 STREAM_GETL(s, nhr->message);
027db469 2043 STREAM_GETW(s, nhr->safi);
06e4e901
DS
2044 STREAM_GETW(s, match->family);
2045 STREAM_GETC(s, match->prefixlen);
2046 /*
2047 * What we got told to match against
2048 */
2049 switch (match->family) {
2050 case AF_INET:
2051 STREAM_GET(&match->u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
2052 break;
2053 case AF_INET6:
2054 STREAM_GET(&match->u.prefix6, s, IPV6_MAX_BYTELEN);
2055 break;
2056 }
2057 /*
2058 * What we matched against
2059 */
4a749e2c
DS
2060 STREAM_GETW(s, nhr->prefix.family);
2061 STREAM_GETC(s, nhr->prefix.prefixlen);
996c9314 2062 switch (nhr->prefix.family) {
4a749e2c
DS
2063 case AF_INET:
2064 STREAM_GET(&nhr->prefix.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
2065 break;
2066 case AF_INET6:
2067 STREAM_GET(&nhr->prefix.u.prefix6, s, IPV6_MAX_BYTELEN);
2068 break;
2069 default:
2070 break;
2071 }
31f937fb
SM
2072 if (CHECK_FLAG(nhr->message, ZAPI_MESSAGE_SRTE))
2073 STREAM_GETL(s, nhr->srte_color);
4a749e2c 2074
05dd5aaf
DS
2075 STREAM_GETC(s, nhr->type);
2076 STREAM_GETW(s, nhr->instance);
4a749e2c
DS
2077 STREAM_GETC(s, nhr->distance);
2078 STREAM_GETL(s, nhr->metric);
2079 STREAM_GETC(s, nhr->nexthop_num);
2080
996c9314 2081 for (i = 0; i < nhr->nexthop_num; i++) {
31f937fb 2082 if (zapi_nexthop_decode(s, &(nhr->nexthops[i]), 0, 0) != 0)
2fec17cd 2083 return false;
4a749e2c
DS
2084 }
2085
2086 return true;
2087stream_failure:
2088 return false;
2089}
2090
9ab0b2a3
SW
2091bool zapi_error_decode(struct stream *s, enum zebra_error_types *error)
2092{
2093 memset(error, 0, sizeof(*error));
2094
2095 STREAM_GET(error, s, sizeof(*error));
2096
2097 if (zclient_debug)
2098 zlog_debug("%s: type: %s", __func__,
2099 zebra_error_type2str(*error));
2100
2101 return true;
2102stream_failure:
2103 return false;
2104}
2105
d62a17ae 2106/*
0a589359 2107 * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
2108 * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
d62a17ae 2109 * then set/unset redist[type] in the client handle (a struct zserv) for the
0a589359 2110 * sending client
2111 */
7cfdb485
DS
2112enum zclient_send_status
2113zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi,
2114 int type, unsigned short instance, vrf_id_t vrf_id)
718e3744 2115{
d62a17ae 2116 struct stream *s;
2117
2118 s = zclient->obuf;
2119 stream_reset(s);
2120
2121 zclient_create_header(s, command, vrf_id);
2122 stream_putc(s, afi);
2123 stream_putc(s, type);
2124 stream_putw(s, instance);
2125
2126 stream_putw_at(s, 0, stream_get_endp(s));
2127
2128 return zclient_send_message(zclient);
718e3744 2129}
2130
7cfdb485
DS
2131enum zclient_send_status
2132zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi,
2133 vrf_id_t vrf_id)
49db7a7b
RW
2134{
2135 struct stream *s;
2136
2137 s = zclient->obuf;
2138 stream_reset(s);
2139
2140 zclient_create_header(s, command, vrf_id);
2141 stream_putc(s, afi);
2142
2143 stream_putw_at(s, 0, stream_get_endp(s));
2144
2145 return zclient_send_message(zclient);
2146}
2147
77b38a4a
S
2148/* Send route notify request to zebra */
2149int zebra_route_notify_send(int command, struct zclient *zclient, bool set)
2150{
2151 struct stream *s;
2152
2153 s = zclient->obuf;
2154 stream_reset(s);
2155
2156 zclient_create_header(s, command, 0);
2157 stream_putc(s, !!set);
2158
2159 stream_putw_at(s, 0, stream_get_endp(s));
2160
2161 return zclient_send_message(zclient);
2162}
2163
d9178828 2164/* Get prefix in ZServ format; family should be filled in on prefix */
efc7191b 2165static int zclient_stream_get_prefix(struct stream *s, struct prefix *p)
d9178828 2166{
d62a17ae 2167 size_t plen = prefix_blen(p);
d7c0a89a 2168 uint8_t c;
d62a17ae 2169 p->prefixlen = 0;
2170
2171 if (plen == 0)
efc7191b 2172 return -1;
d62a17ae 2173
efc7191b 2174 STREAM_GET(&p->u.prefix, s, plen);
ec93aa12 2175 STREAM_GETC(s, c);
d62a17ae 2176 p->prefixlen = MIN(plen * 8, c);
ec93aa12 2177
efc7191b 2178 return 0;
ec93aa12 2179stream_failure:
efc7191b 2180 return -1;
d9178828
PJ
2181}
2182
18a6dce6 2183/* Router-id update from zebra daemon. */
efc7191b 2184int zebra_router_id_update_read(struct stream *s, struct prefix *rid)
18a6dce6 2185{
d62a17ae 2186 /* Fetch interface address. */
ec93aa12 2187 STREAM_GETC(s, rid->family);
d62a17ae 2188
efc7191b 2189 return zclient_stream_get_prefix(s, rid);
ec93aa12
DS
2190
2191stream_failure:
efc7191b 2192 return -1;
18a6dce6 2193}
2194
718e3744 2195/* Interface addition from zebra daemon. */
d62a17ae 2196/*
0a589359 2197 * The format of the message sent with type ZEBRA_INTERFACE_ADD or
2198 * ZEBRA_INTERFACE_DELETE from zebra to the client is:
2199 * 0 1 2 3
2200 * 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 2201 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2202 * | ifname |
2203 * | |
2204 * | |
2205 * | |
2206 * | |
2207 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2208 * | ifindex |
2209 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2210 * | status |
0a589359 2211 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2212 * | if_flags |
c77d4546 2213 * | |
0a589359 2214 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2215 * | metric |
2216 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2d7f0d76
DS
2217 * | speed |
2218 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2219 * | ifmtu |
2220 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2221 * | ifmtu6 |
2222 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2223 * | bandwidth |
2224 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53e60e5c
QY
2225 * | parent ifindex |
2226 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2227 * | Link Layer Type |
0a589359 2228 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2229 * | Harware Address Length |
0a589359 2230 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
03bad95a 2231 * | Hardware Address if HW length different from 0 |
16f1b9ee 2232 * | ... max INTERFACE_HWADDR_MAX |
0a589359 2233 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee 2234 * | Link_params? | Whether a link-params follows: 1 or 0.
0a589359 2235 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16f1b9ee
OD
2236 * | Link_params 0 or 1 INTERFACE_LINK_PARAMS_SIZE sized |
2237 * | .... (struct if_link_params). |
0a589359 2238 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2239 */
2240
a243d1db 2241static int zclient_vrf_add(ZAPI_CALLBACK_ARGS)
1892f15e 2242{
d62a17ae 2243 struct vrf *vrf;
f17a9d0a 2244 char vrfname_tmp[VRF_NAMSIZ + 1] = {};
d62a17ae 2245 struct vrf_data data;
1892f15e 2246
efc7191b 2247 STREAM_GET(&data, zclient->ibuf, sizeof(struct vrf_data));
d62a17ae 2248 /* Read interface name. */
efc7191b 2249 STREAM_GET(vrfname_tmp, zclient->ibuf, VRF_NAMSIZ);
1892f15e 2250
f17a9d0a
QY
2251 if (strlen(vrfname_tmp) == 0)
2252 goto stream_failure;
2253
cff0de12 2254 /* Lookup/create vrf by name, then vrf_id. */
d62a17ae 2255 vrf = vrf_get(vrf_id, vrfname_tmp);
f17a9d0a 2256
cff0de12
QY
2257 /* If there's already a VRF with this name, don't create vrf */
2258 if (!vrf)
f17a9d0a
QY
2259 return 0;
2260
4691b65a
PG
2261 vrf->data.l.table_id = data.l.table_id;
2262 memcpy(vrf->data.l.netns_name, data.l.netns_name, NS_NAMSIZ);
d62a17ae 2263 vrf_enable(vrf);
efc7191b
QY
2264
2265 return 0;
2266stream_failure:
2267 return -1;
1892f15e
DS
2268}
2269
a243d1db 2270static int zclient_vrf_delete(ZAPI_CALLBACK_ARGS)
1892f15e 2271{
d62a17ae 2272 struct vrf *vrf;
1892f15e 2273
d62a17ae 2274 /* Lookup vrf by vrf_id. */
2275 vrf = vrf_lookup_by_id(vrf_id);
1892f15e 2276
d62a17ae 2277 /*
2278 * If a routing protocol doesn't know about a
2279 * vrf that is about to be deleted. There is
2280 * no point in attempting to delete it.
2281 */
2282 if (!vrf)
a243d1db 2283 return 0;
beef1990 2284
d62a17ae 2285 vrf_delete(vrf);
a243d1db 2286 return 0;
1892f15e
DS
2287}
2288
a243d1db 2289static int zclient_interface_add(ZAPI_CALLBACK_ARGS)
718e3744 2290{
d62a17ae 2291 struct interface *ifp;
b98edbcc 2292 char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
ef7bd2a3 2293 struct stream *s = zclient->ibuf;
f60a1188 2294 struct vrf *vrf;
718e3744 2295
d62a17ae 2296 /* Read interface name. */
efc7191b 2297 STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
718e3744 2298
d62a17ae 2299 /* Lookup/create interface by name. */
f60a1188
IR
2300 vrf = vrf_lookup_by_id(vrf_id);
2301 if (!vrf) {
229d0d4e
QY
2302 zlog_debug(
2303 "Rx'd interface add from Zebra, but VRF %u does not exist",
2304 vrf_id);
2305 return -1;
2306 }
2307
f60a1188 2308 ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name);
a41c4e1b 2309
d62a17ae 2310 zebra_interface_if_set_value(s, ifp);
718e3744 2311
ef7bd2a3 2312 if_new_via_zapi(ifp);
efc7191b
QY
2313
2314 return 0;
2315stream_failure:
2316 return -1;
718e3744 2317}
2318
d62a17ae 2319/*
0a589359 2320 * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN)
2321 * from zebra server. The format of this message is the same as
ef7bd2a3
DS
2322 * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE,
2323 * except that no sockaddr_dl is sent at the tail of the message.
0a589359 2324 */
d62a17ae 2325struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t vrf_id)
718e3744 2326{
d62a17ae 2327 struct interface *ifp;
f17a9d0a 2328 char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
d62a17ae 2329
2330 /* Read interface name. */
efc7191b 2331 STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
d62a17ae 2332
2333 /* Lookup this by interface index. */
a36898e7 2334 ifp = if_lookup_by_name(ifname_tmp, vrf_id);
d62a17ae 2335 if (ifp == NULL) {
450971aa 2336 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
2337 "INTERFACE_STATE: Cannot find IF %s in VRF %d",
2338 ifname_tmp, vrf_id);
d62a17ae 2339 return NULL;
2340 }
2341
2342 zebra_interface_if_set_value(s, ifp);
2343
2344 return ifp;
efc7191b
QY
2345stream_failure:
2346 return NULL;
718e3744 2347}
2348
a243d1db 2349static int zclient_interface_delete(ZAPI_CALLBACK_ARGS)
3c3c3252
DS
2350{
2351 struct interface *ifp;
2352 struct stream *s = zclient->ibuf;
2353
2354 ifp = zebra_interface_state_read(s, vrf_id);
2355
2356 if (ifp == NULL)
a243d1db 2357 return 0;
3c3c3252
DS
2358
2359 if_destroy_via_zapi(ifp);
a243d1db 2360 return 0;
3c3c3252
DS
2361}
2362
a243d1db 2363static int zclient_interface_up(ZAPI_CALLBACK_ARGS)
ddbf3e60
DS
2364{
2365 struct interface *ifp;
2366 struct stream *s = zclient->ibuf;
2367
2368 ifp = zebra_interface_state_read(s, vrf_id);
2369
2370 if (!ifp)
a243d1db 2371 return 0;
ddbf3e60
DS
2372
2373 if_up_via_zapi(ifp);
a243d1db 2374 return 0;
ddbf3e60
DS
2375}
2376
a243d1db 2377static int zclient_interface_down(ZAPI_CALLBACK_ARGS)
b0b69e59
DS
2378{
2379 struct interface *ifp;
2380 struct stream *s = zclient->ibuf;
2381
2382 ifp = zebra_interface_state_read(s, vrf_id);
2383
2384 if (!ifp)
a243d1db 2385 return 0;
b0b69e59
DS
2386
2387 if_down_via_zapi(ifp);
a243d1db 2388 return 0;
b0b69e59
DS
2389}
2390
a243d1db 2391static int zclient_handle_error(ZAPI_CALLBACK_ARGS)
9ab0b2a3
SW
2392{
2393 enum zebra_error_types error;
2394 struct stream *s = zclient->ibuf;
2395
2396 zapi_error_decode(s, &error);
2397
2398 if (zclient->handle_error)
2399 (*zclient->handle_error)(error);
a243d1db 2400 return 0;
9ab0b2a3
SW
2401}
2402
fe0a1296 2403static int link_params_set_value(struct stream *s, struct interface *ifp)
16f1b9ee 2404{
fe0a1296
LS
2405 uint8_t link_params_enabled;
2406 struct if_link_params *iflp;
2407 uint32_t bwclassnum;
2408
2409 iflp = if_link_params_get(ifp);
16f1b9ee 2410
d62a17ae 2411 if (iflp == NULL)
fe0a1296 2412 iflp = if_link_params_init(ifp);
d62a17ae 2413
fe0a1296
LS
2414 STREAM_GETC(s, link_params_enabled);
2415 if (!link_params_enabled) {
2416 if_link_params_free(ifp);
2417 return 0;
2418 }
efc7191b
QY
2419
2420 STREAM_GETL(s, iflp->lp_status);
2421 STREAM_GETL(s, iflp->te_metric);
2422 STREAM_GETF(s, iflp->max_bw);
2423 STREAM_GETF(s, iflp->max_rsv_bw);
2424 STREAM_GETL(s, bwclassnum);
d62a17ae 2425 {
2426 unsigned int i;
2427 for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++)
efc7191b 2428 STREAM_GETF(s, iflp->unrsv_bw[i]);
d62a17ae 2429 if (i < bwclassnum)
1c50c1c0
QY
2430 flog_err(
2431 EC_LIB_ZAPI_MISSMATCH,
3efd0893 2432 "%s: received %d > %d (MAX_CLASS_TYPE) bw entries - outdated library?",
1c50c1c0 2433 __func__, bwclassnum, MAX_CLASS_TYPE);
d62a17ae 2434 }
efc7191b
QY
2435 STREAM_GETL(s, iflp->admin_grp);
2436 STREAM_GETL(s, iflp->rmt_as);
d62a17ae 2437 iflp->rmt_ip.s_addr = stream_get_ipv4(s);
2438
efc7191b
QY
2439 STREAM_GETL(s, iflp->av_delay);
2440 STREAM_GETL(s, iflp->min_delay);
2441 STREAM_GETL(s, iflp->max_delay);
2442 STREAM_GETL(s, iflp->delay_var);
2443
2444 STREAM_GETF(s, iflp->pkt_loss);
2445 STREAM_GETF(s, iflp->res_bw);
2446 STREAM_GETF(s, iflp->ava_bw);
2447 STREAM_GETF(s, iflp->use_bw);
d62a17ae 2448
efc7191b
QY
2449 return 0;
2450stream_failure:
2451 return -1;
16f1b9ee
OD
2452}
2453
edc12762 2454struct interface *zebra_interface_link_params_read(struct stream *s,
0b4124c1
KS
2455 vrf_id_t vrf_id,
2456 bool *changed)
16f1b9ee 2457{
d62a17ae 2458 struct if_link_params *iflp;
fe0a1296 2459 struct if_link_params iflp_prev;
d62a17ae 2460 ifindex_t ifindex;
fe0a1296 2461 bool iflp_prev_set;
c28e5b2a 2462
efc7191b 2463 STREAM_GETL(s, ifindex);
16f1b9ee 2464
a36898e7 2465 struct interface *ifp = if_lookup_by_index(ifindex, vrf_id);
16f1b9ee 2466
d62a17ae 2467 if (ifp == NULL) {
450971aa 2468 flog_err(EC_LIB_ZAPI_ENCODE,
1c50c1c0
QY
2469 "%s: unknown ifindex %u, shouldn't happen", __func__,
2470 ifindex);
d62a17ae 2471 return NULL;
2472 }
16f1b9ee 2473
f6657a6e 2474 if (if_link_params_get(ifp)) {
fe0a1296
LS
2475 iflp_prev_set = true;
2476 memcpy(&iflp_prev, ifp->link_params, sizeof(iflp_prev));
2477 } else
2478 iflp_prev_set = false;
0b4124c1 2479
fe0a1296
LS
2480 /* read the link_params from stream
2481 * Free ifp->link_params if the stream has no params
2482 * to means that link-params are not enabled on links.
2483 */
2484 if (link_params_set_value(s, ifp) != 0)
efc7191b 2485 goto stream_failure;
16f1b9ee 2486
fe0a1296
LS
2487 if (changed == NULL)
2488 return ifp;
0b4124c1 2489
f6657a6e
LS
2490 iflp = if_link_params_get(ifp);
2491
fe0a1296
LS
2492 if (iflp_prev_set && iflp) {
2493 if (memcmp(&iflp_prev, iflp, sizeof(iflp_prev)))
2494 *changed = true;
2495 else
2496 *changed = false;
2497 } else if (!iflp_prev_set && !iflp)
2498 *changed = false;
2499 else
2500 *changed = true;
0b4124c1 2501
d62a17ae 2502 return ifp;
efc7191b
QY
2503
2504stream_failure:
2505 return NULL;
16f1b9ee
OD
2506}
2507
41ce5384
QY
2508static void zebra_interface_if_set_value(struct stream *s,
2509 struct interface *ifp)
16f1b9ee 2510{
d7c0a89a 2511 uint8_t link_params_status = 0;
41ce5384 2512 ifindex_t old_ifindex, new_ifindex;
efc7191b 2513
e7ff0253 2514 old_ifindex = ifp->oldifindex;
d62a17ae 2515 /* Read interface's index. */
41ce5384
QY
2516 STREAM_GETL(s, new_ifindex);
2517 if_set_index(ifp, new_ifindex);
2518 STREAM_GETC(s, ifp->status);
d62a17ae 2519
2520 /* Read interface's value. */
41ce5384
QY
2521 STREAM_GETQ(s, ifp->flags);
2522 STREAM_GETC(s, ifp->ptm_enable);
2523 STREAM_GETC(s, ifp->ptm_status);
2524 STREAM_GETL(s, ifp->metric);
2525 STREAM_GETL(s, ifp->speed);
2526 STREAM_GETL(s, ifp->mtu);
2527 STREAM_GETL(s, ifp->mtu6);
2528 STREAM_GETL(s, ifp->bandwidth);
2529 STREAM_GETL(s, ifp->link_ifindex);
2530 STREAM_GETL(s, ifp->ll_type);
2531 STREAM_GETL(s, ifp->hw_addr_len);
2532 if (ifp->hw_addr_len)
2533 STREAM_GET(ifp->hw_addr, s,
2534 MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
d62a17ae 2535
2536 /* Read Traffic Engineering status */
41ce5384 2537 link_params_status = stream_getc(s);
d62a17ae 2538 /* Then, Traffic Engineering parameters if any */
fe0a1296
LS
2539 if (link_params_status)
2540 link_params_set_value(s, ifp);
98cbbaea
DS
2541
2542 nexthop_group_interface_state_change(ifp, old_ifindex);
efc7191b 2543
41ce5384 2544 return;
efc7191b 2545stream_failure:
41ce5384
QY
2546 zlog_err("Could not parse interface values; aborting");
2547 assert(!"Failed to parse interface values");
16f1b9ee
OD
2548}
2549
d62a17ae 2550size_t zebra_interface_link_params_write(struct stream *s,
2551 struct interface *ifp)
16f1b9ee 2552{
d62a17ae 2553 size_t w;
2554 struct if_link_params *iflp;
2555 int i;
16f1b9ee 2556
fe0a1296 2557 if (s == NULL || ifp == NULL)
d62a17ae 2558 return 0;
16f1b9ee 2559
d62a17ae 2560 iflp = ifp->link_params;
2561 w = 0;
16f1b9ee 2562
fe0a1296
LS
2563 /* encode if link_params is enabled */
2564 if (iflp) {
2565 w += stream_putc(s, true);
2566 } else {
2567 w += stream_putc(s, false);
2568 return w;
2569 }
2570
d62a17ae 2571 w += stream_putl(s, iflp->lp_status);
16f1b9ee 2572
d62a17ae 2573 w += stream_putl(s, iflp->te_metric);
2574 w += stream_putf(s, iflp->max_bw);
2575 w += stream_putf(s, iflp->max_rsv_bw);
16f1b9ee 2576
d62a17ae 2577 w += stream_putl(s, MAX_CLASS_TYPE);
2578 for (i = 0; i < MAX_CLASS_TYPE; i++)
2579 w += stream_putf(s, iflp->unrsv_bw[i]);
16f1b9ee 2580
d62a17ae 2581 w += stream_putl(s, iflp->admin_grp);
2582 w += stream_putl(s, iflp->rmt_as);
2583 w += stream_put_in_addr(s, &iflp->rmt_ip);
16f1b9ee 2584
d62a17ae 2585 w += stream_putl(s, iflp->av_delay);
2586 w += stream_putl(s, iflp->min_delay);
2587 w += stream_putl(s, iflp->max_delay);
2588 w += stream_putl(s, iflp->delay_var);
16f1b9ee 2589
d62a17ae 2590 w += stream_putf(s, iflp->pkt_loss);
2591 w += stream_putf(s, iflp->res_bw);
2592 w += stream_putf(s, iflp->ava_bw);
2593 w += stream_putf(s, iflp->use_bw);
16f1b9ee 2594
d62a17ae 2595 return w;
16f1b9ee
OD
2596}
2597
2598/*
03bad95a 2599 * format of message for address addition is:
0a589359 2600 * 0
2601 * 0 1 2 3 4 5 6 7
2602 * +-+-+-+-+-+-+-+-+
2603 * | type | ZEBRA_INTERFACE_ADDRESS_ADD or
2604 * +-+-+-+-+-+-+-+-+ ZEBRA_INTERFACE_ADDRES_DELETE
2605 * | |
2606 * + +
2607 * | ifindex |
2608 * + +
2609 * | |
2610 * + +
2611 * | |
2612 * +-+-+-+-+-+-+-+-+
2613 * | ifc_flags | flags for connected address
2614 * +-+-+-+-+-+-+-+-+
2615 * | addr_family |
2616 * +-+-+-+-+-+-+-+-+
2617 * | addr... |
2618 * : :
2619 * | |
2620 * +-+-+-+-+-+-+-+-+
2621 * | addr_len | len of addr. E.g., addr_len = 4 for ipv4 addrs.
2622 * +-+-+-+-+-+-+-+-+
2623 * | daddr.. |
2624 * : :
2625 * | |
2626 * +-+-+-+-+-+-+-+-+
0a589359 2627 */
2628
d62a17ae 2629static int memconstant(const void *s, int c, size_t n)
3fb9cd6e 2630{
d7c0a89a 2631 const uint8_t *p = s;
3fb9cd6e 2632
d62a17ae 2633 while (n-- > 0)
2634 if (*p++ != c)
2635 return 0;
2636 return 1;
3fb9cd6e 2637}
2638
d5a5c8f0 2639
d62a17ae 2640struct connected *zebra_interface_address_read(int type, struct stream *s,
2641 vrf_id_t vrf_id)
718e3744 2642{
d62a17ae 2643 ifindex_t ifindex;
2644 struct interface *ifp;
2645 struct connected *ifc;
2646 struct prefix p, d, *dp;
2647 int plen;
d7c0a89a 2648 uint8_t ifc_flags;
d62a17ae 2649
2650 memset(&p, 0, sizeof(p));
2651 memset(&d, 0, sizeof(d));
2652
2653 /* Get interface index. */
efc7191b 2654 STREAM_GETL(s, ifindex);
d62a17ae 2655
2656 /* Lookup index. */
2657 ifp = if_lookup_by_index(ifindex, vrf_id);
2658 if (ifp == NULL) {
450971aa 2659 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
2660 "INTERFACE_ADDRESS_%s: Cannot find IF %u in VRF %d",
2661 (type == ZEBRA_INTERFACE_ADDRESS_ADD) ? "ADD" : "DEL",
2662 ifindex, vrf_id);
d62a17ae 2663 return NULL;
2664 }
2665
2666 /* Fetch flag. */
efc7191b 2667 STREAM_GETC(s, ifc_flags);
d62a17ae 2668
2669 /* Fetch interface address. */
efc7191b 2670 STREAM_GETC(s, d.family);
e4f5680d 2671 p.family = d.family;
d62a17ae 2672 plen = prefix_blen(&d);
2673
efc7191b
QY
2674 if (zclient_stream_get_prefix(s, &p) != 0)
2675 goto stream_failure;
d62a17ae 2676
2677 /* Fetch destination address. */
efc7191b 2678 STREAM_GET(&d.u.prefix, s, plen);
d62a17ae 2679
2680 /* N.B. NULL destination pointers are encoded as all zeroes */
2681 dp = memconstant(&d.u.prefix, 0, plen) ? NULL : &d;
2682
2683 if (type == ZEBRA_INTERFACE_ADDRESS_ADD) {
2684 ifc = connected_lookup_prefix_exact(ifp, &p);
2685 if (!ifc) {
2686 /* N.B. NULL destination pointers are encoded as all
2687 * zeroes */
2688 ifc = connected_add_by_prefix(ifp, &p, dp);
2689 }
2690 if (ifc) {
2691 ifc->flags = ifc_flags;
2692 if (ifc->destination)
2693 ifc->destination->prefixlen =
2694 ifc->address->prefixlen;
2695 else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
2696 /* carp interfaces on OpenBSD with 0.0.0.0/0 as
2697 * "peer" */
ade6974d 2698 flog_err(
450971aa 2699 EC_LIB_ZAPI_ENCODE,
a0ee6f32 2700 "interface %s address %pFX with peer flag set, but no peer address!",
2dbe669b 2701 ifp->name, ifc->address);
d62a17ae 2702 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
2703 }
2704 }
2705 } else {
2706 assert(type == ZEBRA_INTERFACE_ADDRESS_DELETE);
2707 ifc = connected_delete_by_prefix(ifp, &p);
2708 }
2709
2710 return ifc;
efc7191b
QY
2711
2712stream_failure:
2713 return NULL;
718e3744 2714}
0a589359 2715
a80beece
DS
2716/*
2717 * format of message for neighbor connected address is:
2718 * 0
2719 * 0 1 2 3 4 5 6 7
2720 * +-+-+-+-+-+-+-+-+
2721 * | type | ZEBRA_INTERFACE_NBR_ADDRESS_ADD or
2722 * +-+-+-+-+-+-+-+-+ ZEBRA_INTERFACE_NBR_ADDRES_DELETE
2723 * | |
2724 * + +
2725 * | ifindex |
2726 * + +
2727 * | |
2728 * + +
2729 * | |
2730 * +-+-+-+-+-+-+-+-+
2731 * | addr_family |
2732 * +-+-+-+-+-+-+-+-+
2733 * | addr... |
2734 * : :
2735 * | |
2736 * +-+-+-+-+-+-+-+-+
2737 * | addr_len | len of addr.
2738 * +-+-+-+-+-+-+-+-+
2739 */
2740struct nbr_connected *
d62a17ae 2741zebra_interface_nbr_address_read(int type, struct stream *s, vrf_id_t vrf_id)
a80beece 2742{
d62a17ae 2743 unsigned int ifindex;
2744 struct interface *ifp;
2745 struct prefix p;
2746 struct nbr_connected *ifc;
2747
2748 /* Get interface index. */
efc7191b 2749 STREAM_GETL(s, ifindex);
d62a17ae 2750
2751 /* Lookup index. */
2752 ifp = if_lookup_by_index(ifindex, vrf_id);
2753 if (ifp == NULL) {
450971aa 2754 flog_err(EC_LIB_ZAPI_ENCODE,
decbd929
DS
2755 "INTERFACE_NBR_%s: Cannot find IF %u in VRF %d",
2756 (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) ? "ADD"
ade6974d
QY
2757 : "DELETE",
2758 ifindex, vrf_id);
d62a17ae 2759 return NULL;
2760 }
2761
efc7191b
QY
2762 STREAM_GETC(s, p.family);
2763 STREAM_GET(&p.u.prefix, s, prefix_blen(&p));
2764 STREAM_GETC(s, p.prefixlen);
d62a17ae 2765
2766 if (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) {
2767 /* Currently only supporting P2P links, so any new RA source
2768 address is
2769 considered as the replacement of the previously learnt
2770 Link-Local address. */
2771 if (!(ifc = listnode_head(ifp->nbr_connected))) {
2772 ifc = nbr_connected_new();
2773 ifc->address = prefix_new();
2774 ifc->ifp = ifp;
2775 listnode_add(ifp->nbr_connected, ifc);
2776 }
2777
2778 prefix_copy(ifc->address, &p);
2779 } else {
2780 assert(type == ZEBRA_INTERFACE_NBR_ADDRESS_DELETE);
2781
2782 ifc = nbr_connected_check(ifp, &p);
2783 if (ifc)
2784 listnode_delete(ifp->nbr_connected, ifc);
2785 }
2786
2787 return ifc;
efc7191b
QY
2788
2789stream_failure:
2790 return NULL;
a80beece 2791}
6b0655a2 2792
d62a17ae 2793struct interface *zebra_interface_vrf_update_read(struct stream *s,
2794 vrf_id_t vrf_id,
2795 vrf_id_t *new_vrf_id)
c8e264b6 2796{
f17a9d0a 2797 char ifname[INTERFACE_NAMSIZ + 1] = {};
d62a17ae 2798 struct interface *ifp;
a9ff90c4 2799 vrf_id_t new_id;
d62a17ae 2800
91d227b7 2801 /* Read interface name. */
efc7191b 2802 STREAM_GET(ifname, s, INTERFACE_NAMSIZ);
d62a17ae 2803
2804 /* Lookup interface. */
a36898e7 2805 ifp = if_lookup_by_name(ifname, vrf_id);
d62a17ae 2806 if (ifp == NULL) {
450971aa 2807 flog_err(EC_LIB_ZAPI_ENCODE,
91d227b7
RW
2808 "INTERFACE_VRF_UPDATE: Cannot find IF %s in VRF %d",
2809 ifname, vrf_id);
d62a17ae 2810 return NULL;
2811 }
2812
2813 /* Fetch new VRF Id. */
efc7191b 2814 STREAM_GETL(s, new_id);
d62a17ae 2815
2816 *new_vrf_id = new_id;
2817 return ifp;
efc7191b
QY
2818
2819stream_failure:
2820 return NULL;
c8e264b6 2821}
5c7ef8dc 2822
2823/* filter unwanted messages until the expected one arrives */
d62a17ae 2824static int zclient_read_sync_response(struct zclient *zclient,
d7c0a89a 2825 uint16_t expected_cmd)
5c7ef8dc 2826{
d62a17ae 2827 struct stream *s;
d7c0a89a
QY
2828 uint16_t size = -1;
2829 uint8_t marker;
2830 uint8_t version;
d62a17ae 2831 vrf_id_t vrf_id;
d7c0a89a 2832 uint16_t cmd;
d62a17ae 2833 fd_set readfds;
2834 int ret;
2835
2836 ret = 0;
2837 cmd = expected_cmd + 1;
2838 while (ret == 0 && cmd != expected_cmd) {
2839 s = zclient->ibuf;
2840 stream_reset(s);
2841
2842 /* wait until response arrives */
2843 FD_ZERO(&readfds);
2844 FD_SET(zclient->sock, &readfds);
2845 select(zclient->sock + 1, &readfds, NULL, NULL, NULL);
2846 if (!FD_ISSET(zclient->sock, &readfds))
2847 continue;
2848 /* read response */
2849 ret = zclient_read_header(s, zclient->sock, &size, &marker,
2850 &version, &vrf_id, &cmd);
2851 if (zclient_debug)
2852 zlog_debug("%s: Response (%d bytes) received", __func__,
2853 size);
2854 }
2855 if (ret != 0) {
1c50c1c0
QY
2856 flog_err(EC_LIB_ZAPI_ENCODE, "%s: Invalid Sync Message Reply",
2857 __func__);
d62a17ae 2858 return -1;
2859 }
2860
2861 return 0;
5c7ef8dc 2862}
fea12efb 2863/**
03bad95a 2864 * Connect to label manager in a synchronous way
fea12efb 2865 *
03bad95a 2866 * It first writes the request to zclient output buffer and then
fea12efb 2867 * immediately reads the answer from the input buffer.
2868 *
2869 * @param zclient Zclient used to connect to label manager (zebra)
f533be73 2870 * @param async Synchronous (0) or asynchronous (1) operation
fea12efb 2871 * @result Result of response
2872 */
f533be73 2873int lm_label_manager_connect(struct zclient *zclient, int async)
fea12efb 2874{
d62a17ae 2875 int ret;
2876 struct stream *s;
d7c0a89a 2877 uint8_t result;
f533be73 2878 uint16_t cmd = async ? ZEBRA_LABEL_MANAGER_CONNECT_ASYNC :
2879 ZEBRA_LABEL_MANAGER_CONNECT;
d62a17ae 2880
2881 if (zclient_debug)
35cbe02a 2882 zlog_debug("Connecting to Label Manager (LM)");
d62a17ae 2883
f533be73 2884 if (zclient->sock < 0) {
2885 zlog_debug("%s: invalid zclient socket", __func__);
d62a17ae 2886 return -1;
f533be73 2887 }
d62a17ae 2888
2889 /* send request */
2890 s = zclient->obuf;
2891 stream_reset(s);
f533be73 2892 zclient_create_header(s, cmd, VRF_DEFAULT);
d62a17ae 2893
2894 /* proto */
2895 stream_putc(s, zclient->redist_default);
2896 /* instance */
2897 stream_putw(s, zclient->instance);
2898
2899 /* Put length at the first point of the stream. */
2900 stream_putw_at(s, 0, stream_get_endp(s));
2901
2902 ret = writen(zclient->sock, s->data, stream_get_endp(s));
2903 if (ret < 0) {
450971aa 2904 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
d62a17ae 2905 close(zclient->sock);
2906 zclient->sock = -1;
2907 return -1;
2908 }
2909 if (ret == 0) {
450971aa 2910 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock closed");
d62a17ae 2911 close(zclient->sock);
2912 zclient->sock = -1;
2913 return -1;
2914 }
2915 if (zclient_debug)
35cbe02a 2916 zlog_debug("LM connect request sent (%d bytes)", ret);
d62a17ae 2917
f533be73 2918 if (async)
2919 return 0;
2920
d62a17ae 2921 /* read response */
f533be73 2922 if (zclient_read_sync_response(zclient, cmd)
d62a17ae 2923 != 0)
2924 return -1;
2925
d62a17ae 2926 s = zclient->ibuf;
5dffb0e9
FR
2927
2928 /* read instance and proto */
efc7191b
QY
2929 uint8_t proto;
2930 uint16_t instance;
2931
2932 STREAM_GETC(s, proto);
2933 STREAM_GETW(s, instance);
5dffb0e9
FR
2934
2935 /* sanity */
2936 if (proto != zclient->redist_default)
1c50c1c0
QY
2937 flog_err(
2938 EC_LIB_ZAPI_ENCODE,
2939 "Wrong proto (%u) in LM connect response. Should be %u",
2940 proto, zclient->redist_default);
5dffb0e9 2941 if (instance != zclient->instance)
1c50c1c0
QY
2942 flog_err(
2943 EC_LIB_ZAPI_ENCODE,
2944 "Wrong instId (%u) in LM connect response. Should be %u",
2945 instance, zclient->instance);
5dffb0e9
FR
2946
2947 /* result code */
efc7191b 2948 STREAM_GETC(s, result);
d62a17ae 2949 if (zclient_debug)
0313523d 2950 zlog_debug("LM connect-response received, result %u", result);
f2867068
HS
2951
2952 return (int)result;
2953
2954stream_failure:
2955 return -1;
2956}
2957
2958/**
03bad95a 2959 * Function to request a srv6-locator chunk in an asynchronous way
f2867068 2960 *
f2867068
HS
2961 * @param zclient Zclient used to connect to table manager (zebra)
2962 * @param locator_name Name of SRv6-locator
2963 * @result 0 on success, -1 otherwise
2964 */
2965int srv6_manager_get_locator_chunk(struct zclient *zclient,
2966 const char *locator_name)
2967{
2968 struct stream *s;
2969 const size_t len = strlen(locator_name);
2970
2971 if (zclient_debug)
2972 zlog_debug("Getting SRv6-Locator Chunk %s", locator_name);
2973
2974 if (zclient->sock < 0)
2975 return -1;
2976
2977 /* send request */
2978 s = zclient->obuf;
2979 stream_reset(s);
4df9d859
HS
2980 zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK,
2981 VRF_DEFAULT);
f2867068 2982
f2867068
HS
2983 /* locator_name */
2984 stream_putw(s, len);
2985 stream_put(s, locator_name, len);
2986
2987 /* Put length at the first point of the stream. */
2988 stream_putw_at(s, 0, stream_get_endp(s));
2989
2990 return zclient_send_message(zclient);
2991}
2992
2993/**
2994 * Function to release a srv6-locator chunk
2995 *
2996 * @param zclient Zclient used to connect to table manager (zebra)
2997 * @param locator_name Name of SRv6-locator
2998 * @result 0 on success, -1 otherwise
2999 */
3000int srv6_manager_release_locator_chunk(struct zclient *zclient,
3001 const char *locator_name)
3002{
3003 struct stream *s;
3004 const size_t len = strlen(locator_name);
3005
3006 if (zclient_debug)
3007 zlog_debug("Releasing SRv6-Locator Chunk %s", locator_name);
3008
3009 if (zclient->sock < 0)
3010 return -1;
3011
3012 /* send request */
3013 s = zclient->obuf;
3014 stream_reset(s);
3015 zclient_create_header(s, ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
3016 VRF_DEFAULT);
3017
f2867068
HS
3018 /* locator_name */
3019 stream_putw(s, len);
3020 stream_put(s, locator_name, len);
3021
3022 /* Put length at the first point of the stream. */
3023 stream_putw_at(s, 0, stream_get_endp(s));
3024
3025 return zclient_send_message(zclient);
3026}
3027
955bfd98
PZ
3028/*
3029 * Asynchronous label chunk request
3030 *
3031 * @param zclient Zclient used to connect to label manager (zebra)
3032 * @param keep Avoid garbage collection
3033 * @param chunk_size Amount of labels requested
0e3b6a92 3034 * @param base Base for the label chunk. if MPLS_LABEL_BASE_ANY we do not care
955bfd98
PZ
3035 * @result 0 on success, -1 otherwise
3036 */
7cfdb485
DS
3037enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient,
3038 uint8_t keep,
3039 uint32_t chunk_size,
3040 uint32_t base)
955bfd98
PZ
3041{
3042 struct stream *s;
3043
3044 if (zclient_debug)
3045 zlog_debug("Getting Label Chunk");
3046
3047 if (zclient->sock < 0)
7cfdb485 3048 return ZCLIENT_SEND_FAILURE;
955bfd98
PZ
3049
3050 s = zclient->obuf;
3051 stream_reset(s);
3052
3053 zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
5dffb0e9
FR
3054 /* proto */
3055 stream_putc(s, zclient->redist_default);
3056 /* instance */
3057 stream_putw(s, zclient->instance);
955bfd98
PZ
3058 stream_putc(s, keep);
3059 stream_putl(s, chunk_size);
0e3b6a92 3060 stream_putl(s, base);
955bfd98
PZ
3061
3062 /* Put length at the first point of the stream. */
3063 stream_putw_at(s, 0, stream_get_endp(s));
3064
3065 return zclient_send_message(zclient);
3066}
3067
fea12efb 3068/**
03bad95a 3069 * Function to request a label chunk in a synchronous way
fea12efb 3070 *
03bad95a 3071 * It first writes the request to zclient output buffer and then
fea12efb 3072 * immediately reads the answer from the input buffer.
3073 *
3074 * @param zclient Zclient used to connect to label manager (zebra)
3075 * @param keep Avoid garbage collection
3076 * @param chunk_size Amount of labels requested
3077 * @param start To write first assigned chunk label to
3078 * @param end To write last assigned chunk label to
3079 * @result 0 on success, -1 otherwise
3080 */
0e3b6a92 3081int lm_get_label_chunk(struct zclient *zclient, uint8_t keep, uint32_t base,
d62a17ae 3082 uint32_t chunk_size, uint32_t *start, uint32_t *end)
fea12efb 3083{
d62a17ae 3084 int ret;
3085 struct stream *s;
d7c0a89a 3086 uint8_t response_keep;
d62a17ae 3087
3088 if (zclient_debug)
3089 zlog_debug("Getting Label Chunk");
3090
3091 if (zclient->sock < 0)
3092 return -1;
3093
3094 /* send request */
3095 s = zclient->obuf;
3096 stream_reset(s);
3097 zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT);
5dffb0e9
FR
3098 /* proto */
3099 stream_putc(s, zclient->redist_default);
3100 /* instance */
3101 stream_putw(s, zclient->instance);
d62a17ae 3102 /* keep */
3103 stream_putc(s, keep);
3104 /* chunk size */
3105 stream_putl(s, chunk_size);
0e3b6a92
EDP
3106 /* requested chunk base */
3107 stream_putl(s, base);
d62a17ae 3108 /* Put length at the first point of the stream. */
3109 stream_putw_at(s, 0, stream_get_endp(s));
3110
3111 ret = writen(zclient->sock, s->data, stream_get_endp(s));
3112 if (ret < 0) {
1c50c1c0 3113 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
d62a17ae 3114 close(zclient->sock);
3115 zclient->sock = -1;
3116 return -1;
3117 }
3118 if (ret == 0) {
1c50c1c0 3119 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock closed");
d62a17ae 3120 close(zclient->sock);
3121 zclient->sock = -1;
3122 return -1;
3123 }
3124 if (zclient_debug)
35cbe02a 3125 zlog_debug("Label chunk request (%d bytes) sent", ret);
d62a17ae 3126
3127 /* read response */
3128 if (zclient_read_sync_response(zclient, ZEBRA_GET_LABEL_CHUNK) != 0)
3129 return -1;
3130
5dffb0e9 3131 /* parse response */
d62a17ae 3132 s = zclient->ibuf;
5dffb0e9
FR
3133
3134 /* read proto and instance */
efc7191b
QY
3135 uint8_t proto;
3136 uint8_t instance;
3137
3138 STREAM_GETC(s, proto);
3139 STREAM_GETW(s, instance);
5dffb0e9
FR
3140
3141 /* sanities */
3142 if (proto != zclient->redist_default)
450971aa 3143 flog_err(EC_LIB_ZAPI_ENCODE,
1c50c1c0
QY
3144 "Wrong proto (%u) in get chunk response. Should be %u",
3145 proto, zclient->redist_default);
5dffb0e9 3146 if (instance != zclient->instance)
450971aa 3147 flog_err(EC_LIB_ZAPI_ENCODE,
1c50c1c0
QY
3148 "Wrong instId (%u) in get chunk response Should be %u",
3149 instance, zclient->instance);
5dffb0e9 3150
f004f7c3
EDP
3151 /* if we requested a specific chunk and it could not be allocated, the
3152 * response message will end here
3153 */
3154 if (!STREAM_READABLE(s)) {
3155 zlog_info("Unable to assign Label Chunk to %s instance %u",
3156 zebra_route_string(proto), instance);
3157 return -1;
3158 }
3159
d62a17ae 3160 /* keep */
efc7191b 3161 STREAM_GETC(s, response_keep);
d62a17ae 3162 /* start and end labels */
efc7191b
QY
3163 STREAM_GETL(s, *start);
3164 STREAM_GETL(s, *end);
d62a17ae 3165
3166 /* not owning this response */
3167 if (keep != response_keep) {
1c50c1c0
QY
3168 flog_err(
3169 EC_LIB_ZAPI_ENCODE,
3170 "Invalid Label chunk: %u - %u, keeps mismatch %u != %u",
3171 *start, *end, keep, response_keep);
d62a17ae 3172 }
3173 /* sanity */
70e98a7f
DS
3174 if (*start > *end || *start < MPLS_LABEL_UNRESERVED_MIN
3175 || *end > MPLS_LABEL_UNRESERVED_MAX) {
1c50c1c0
QY
3176 flog_err(EC_LIB_ZAPI_ENCODE, "Invalid Label chunk: %u - %u",
3177 *start, *end);
d62a17ae 3178 return -1;
3179 }
3180
3181 if (zclient_debug)
35cbe02a 3182 zlog_debug("Label Chunk assign: %u - %u (%u)", *start, *end,
d62a17ae 3183 response_keep);
3184
3185 return 0;
efc7191b
QY
3186
3187stream_failure:
3188 return -1;
fea12efb 3189}
3190
3191/**
3192 * Function to release a label chunk
3193 *
3194 * @param zclient Zclient used to connect to label manager (zebra)
3195 * @param start First label of chunk
3196 * @param end Last label of chunk
3197 * @result 0 on success, -1 otherwise
3198 */
d62a17ae 3199int lm_release_label_chunk(struct zclient *zclient, uint32_t start,
3200 uint32_t end)
fea12efb 3201{
d62a17ae 3202 int ret;
3203 struct stream *s;
3204
3205 if (zclient_debug)
35cbe02a 3206 zlog_debug("Releasing Label Chunk %u - %u", start, end);
d62a17ae 3207
3208 if (zclient->sock < 0)
3209 return -1;
3210
3211 /* send request */
3212 s = zclient->obuf;
3213 stream_reset(s);
3214 zclient_create_header(s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT);
3215
5dffb0e9
FR
3216 /* proto */
3217 stream_putc(s, zclient->redist_default);
3218 /* instance */
3219 stream_putw(s, zclient->instance);
d62a17ae 3220 /* start */
3221 stream_putl(s, start);
3222 /* end */
3223 stream_putl(s, end);
3224
3225 /* Put length at the first point of the stream. */
3226 stream_putw_at(s, 0, stream_get_endp(s));
3227
3228 ret = writen(zclient->sock, s->data, stream_get_endp(s));
3229 if (ret < 0) {
450971aa 3230 flog_err(EC_LIB_ZAPI_SOCKET, "Can't write to zclient sock");
d62a17ae 3231 close(zclient->sock);
3232 zclient->sock = -1;
3233 return -1;
3234 }
3235 if (ret == 0) {
1c50c1c0 3236 flog_err(EC_LIB_ZAPI_SOCKET, "Zclient sock connection closed");
d62a17ae 3237 close(zclient->sock);
3238 zclient->sock = -1;
3239 return -1;
3240 }
3241
3242 return 0;
fea12efb 3243}
c8e264b6 3244
75fb51c1 3245/**
03bad95a 3246 * Connect to table manager in a synchronous way
75fb51c1 3247 *
03bad95a 3248 * It first writes the request to zclient output buffer and then
75fb51c1
PG
3249 * immediately reads the answer from the input buffer.
3250 *
3251 * @param zclient Zclient used to connect to table manager (zebra)
3252 * @result Result of response
3253 */
3254int tm_table_manager_connect(struct zclient *zclient)
3255{
3256 int ret;
3257 struct stream *s;
3258 uint8_t result;
3259
3260 if (zclient_debug)
3261 zlog_debug("Connecting to Table Manager");
3262
3263 if (zclient->sock < 0)
7cfdb485 3264 return ZCLIENT_SEND_FAILURE;
75fb51c1
PG
3265
3266 /* send request */
3267 s = zclient->obuf;
3268 stream_reset(s);
3269 zclient_create_header(s, ZEBRA_TABLE_MANAGER_CONNECT, VRF_DEFAULT);
3270
3271 /* proto */
3272 stream_putc(s, zclient->redist_default);
3273 /* instance */
3274 stream_putw(s, zclient->instance);
3275
3276 /* Put length at the first point of the stream. */
3277 stream_putw_at(s, 0, stream_get_endp(s));
3278
3279 ret = zclient_send_message(zclient);
7cfdb485 3280 if (ret == ZCLIENT_SEND_FAILURE)
75fb51c1
PG
3281 return -1;
3282
3283 if (zclient_debug)
0313523d 3284 zlog_debug("%s: Table manager connect request sent", __func__);
75fb51c1
PG
3285
3286 /* read response */
3287 if (zclient_read_sync_response(zclient, ZEBRA_TABLE_MANAGER_CONNECT)
3288 != 0)
3289 return -1;
3290
3291 /* result */
3292 s = zclient->ibuf;
3293 STREAM_GETC(s, result);
3294 if (zclient_debug)
3295 zlog_debug(
3296 "%s: Table Manager connect response received, result %u",
3297 __func__, result);
3298
3299 return (int)result;
3300stream_failure:
6a2b0d9a 3301 return -1;
75fb51c1
PG
3302}
3303
3304/**
03bad95a 3305 * Function to request a table chunk in a synchronous way
75fb51c1
PG
3306 *
3307 * It first writes the request to zclient output buffer and then
3308 * immediately reads the answer from the input buffer.
3309 *
3310 * @param zclient Zclient used to connect to table manager (zebra)
3311 * @param chunk_size Amount of table requested
3312 * @param start to write first assigned chunk table RT ID to
3313 * @param end To write last assigned chunk table RT ID to
3314 * @result 0 on success, -1 otherwise
3315 */
3316int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
3317 uint32_t *start, uint32_t *end)
3318{
3319 int ret;
3320 struct stream *s;
3321
3322 if (zclient_debug)
3323 zlog_debug("Getting Table Chunk");
3324
3325 if (zclient->sock < 0)
3326 return -1;
3327
3328 /* send request */
3329 s = zclient->obuf;
3330 stream_reset(s);
3331 zclient_create_header(s, ZEBRA_GET_TABLE_CHUNK, VRF_DEFAULT);
3332 /* chunk size */
3333 stream_putl(s, chunk_size);
3334 /* Put length at the first point of the stream. */
3335 stream_putw_at(s, 0, stream_get_endp(s));
3336
3337 ret = writen(zclient->sock, s->data, stream_get_endp(s));
3338 if (ret < 0) {
1c50c1c0
QY
3339 flog_err(EC_LIB_ZAPI_SOCKET, "%s: can't write to zclient->sock",
3340 __func__);
75fb51c1
PG
3341 close(zclient->sock);
3342 zclient->sock = -1;
3343 return -1;
3344 }
3345 if (ret == 0) {
450971aa 3346 flog_err(EC_LIB_ZAPI_SOCKET,
1c50c1c0 3347 "%s: zclient->sock connection closed", __func__);
75fb51c1
PG
3348 close(zclient->sock);
3349 zclient->sock = -1;
3350 return -1;
3351 }
3352 if (zclient_debug)
3353 zlog_debug("%s: Table chunk request (%d bytes) sent", __func__,
3354 ret);
3355
3356 /* read response */
3357 if (zclient_read_sync_response(zclient, ZEBRA_GET_TABLE_CHUNK) != 0)
3358 return -1;
3359
3360 s = zclient->ibuf;
3361 /* start and end table IDs */
3362 STREAM_GETL(s, *start);
3363 STREAM_GETL(s, *end);
3364
3365 if (zclient_debug)
3366 zlog_debug("Table Chunk assign: %u - %u ", *start, *end);
3367
75fb51c1 3368 return 0;
6a2b0d9a
RW
3369stream_failure:
3370 return -1;
75fb51c1
PG
3371}
3372
3373/**
3374 * Function to release a table chunk
3375 *
3376 * @param zclient Zclient used to connect to table manager (zebra)
3377 * @param start First label of table
3378 * @param end Last label of chunk
3379 * @result 0 on success, -1 otherwise
3380 */
3381int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
3382 uint32_t end)
3383{
3384 struct stream *s;
3385
3386 if (zclient_debug)
3387 zlog_debug("Releasing Table Chunk");
3388
3389 if (zclient->sock < 0)
3390 return -1;
3391
3392 /* send request */
3393 s = zclient->obuf;
3394 stream_reset(s);
3395 zclient_create_header(s, ZEBRA_RELEASE_TABLE_CHUNK, VRF_DEFAULT);
3396
3397 /* start */
3398 stream_putl(s, start);
3399 /* end */
3400 stream_putl(s, end);
3401
3402 /* Put length at the first point of the stream. */
3403 stream_putw_at(s, 0, stream_get_endp(s));
3404
7cfdb485
DS
3405 if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
3406 return -1;
3407
3408 return 0;
75fb51c1
PG
3409}
3410
7cfdb485
DS
3411enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient, int cmd,
3412 struct zapi_sr_policy *zp)
31f937fb
SM
3413{
3414 if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
7cfdb485 3415 return ZCLIENT_SEND_FAILURE;
31f937fb
SM
3416 return zclient_send_message(zclient);
3417}
3418
3419int zapi_sr_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp)
3420{
3421 struct zapi_srte_tunnel *zt = &zp->segment_list;
3422
3423 stream_reset(s);
3424
3425 zclient_create_header(s, cmd, VRF_DEFAULT);
3426 stream_putl(s, zp->color);
3427 stream_put_ipaddr(s, &zp->endpoint);
3428 stream_write(s, &zp->name, SRTE_POLICY_NAME_MAX_LENGTH);
3429
3430 stream_putc(s, zt->type);
3431 stream_putl(s, zt->local_label);
3432
3433 if (zt->label_num > MPLS_MAX_LABELS) {
3434 flog_err(EC_LIB_ZAPI_ENCODE,
3435 "%s: label %u: can't encode %u labels (maximum is %u)",
3436 __func__, zt->local_label, zt->label_num,
3437 MPLS_MAX_LABELS);
3438 return -1;
3439 }
3440 stream_putw(s, zt->label_num);
3441
3442 for (int i = 0; i < zt->label_num; i++)
3443 stream_putl(s, zt->labels[i]);
3444
3445 /* Put length at the first point of the stream. */
3446 stream_putw_at(s, 0, stream_get_endp(s));
3447
3448 return 0;
3449}
3450
3451int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
3452{
3453 memset(zp, 0, sizeof(*zp));
3454
3455 struct zapi_srte_tunnel *zt = &zp->segment_list;
3456
3457 STREAM_GETL(s, zp->color);
3458 STREAM_GET_IPADDR(s, &zp->endpoint);
3459 STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
3460
3461 /* segment list of active candidate path */
3462 STREAM_GETC(s, zt->type);
3463 STREAM_GETL(s, zt->local_label);
3464 STREAM_GETW(s, zt->label_num);
3465 if (zt->label_num > MPLS_MAX_LABELS) {
3466 flog_err(EC_LIB_ZAPI_ENCODE,
3467 "%s: label %u: can't decode %u labels (maximum is %u)",
3468 __func__, zt->local_label, zt->label_num,
3469 MPLS_MAX_LABELS);
3470 return -1;
3471 }
3472 for (int i = 0; i < zt->label_num; i++)
3473 STREAM_GETL(s, zt->labels[i]);
3474
3475 return 0;
3476
3477stream_failure:
3478 return -1;
3479}
3480
3481int zapi_sr_policy_notify_status_decode(struct stream *s,
3482 struct zapi_sr_policy *zp)
3483{
3484 memset(zp, 0, sizeof(*zp));
3485
3486 STREAM_GETL(s, zp->color);
3487 STREAM_GET_IPADDR(s, &zp->endpoint);
3488 STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
3489 STREAM_GETL(s, zp->status);
3490
3491 return 0;
3492
3493stream_failure:
3494 return -1;
3495}
3496
7cfdb485
DS
3497enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient,
3498 int cmd, struct zapi_labels *zl)
bad6b0e7
RW
3499{
3500 if (zapi_labels_encode(zclient->obuf, cmd, zl) < 0)
7cfdb485 3501 return ZCLIENT_SEND_FAILURE;
bad6b0e7
RW
3502 return zclient_send_message(zclient);
3503}
3504
3505int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
3506{
4945002d 3507 struct zapi_nexthop *znh;
ea6b290b 3508
bad6b0e7
RW
3509 stream_reset(s);
3510
3511 zclient_create_header(s, cmd, VRF_DEFAULT);
b3c49d0e 3512 stream_putc(s, zl->message);
bad6b0e7 3513 stream_putc(s, zl->type);
b3c49d0e
RW
3514 stream_putl(s, zl->local_label);
3515
3516 if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
3517 stream_putw(s, zl->route.prefix.family);
3518 stream_put_prefix(s, &zl->route.prefix);
3519 stream_putc(s, zl->route.type);
3520 stream_putw(s, zl->route.instance);
3521 }
3522
ea6b290b
RW
3523 if (zl->nexthop_num > MULTIPATH_NUM) {
3524 flog_err(
3525 EC_LIB_ZAPI_ENCODE,
3526 "%s: label %u: can't encode %u nexthops (maximum is %u)",
3527 __func__, zl->local_label, zl->nexthop_num,
3528 MULTIPATH_NUM);
3529 return -1;
3530 }
3531 stream_putw(s, zl->nexthop_num);
3532
3533 for (int i = 0; i < zl->nexthop_num; i++) {
3534 znh = &zl->nexthops[i];
3535
31f937fb 3536 if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
4945002d 3537 return -1;
bad6b0e7 3538 }
bad6b0e7 3539
34f86754
MS
3540 if (CHECK_FLAG(zl->message, ZAPI_LABELS_HAS_BACKUPS)) {
3541
3542 if (zl->backup_nexthop_num > MULTIPATH_NUM) {
3543 flog_err(
3544 EC_LIB_ZAPI_ENCODE,
3545 "%s: label %u: can't encode %u nexthops (maximum is %u)",
3546 __func__, zl->local_label, zl->nexthop_num,
3547 MULTIPATH_NUM);
3548 return -1;
3549 }
3550 stream_putw(s, zl->backup_nexthop_num);
3551
3552 for (int i = 0; i < zl->backup_nexthop_num; i++) {
3553 znh = &zl->backup_nexthops[i];
3554
31f937fb 3555 if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
34f86754
MS
3556 return -1;
3557 }
3558
3559 }
3560
bad6b0e7
RW
3561 /* Put length at the first point of the stream. */
3562 stream_putw_at(s, 0, stream_get_endp(s));
3563
3564 return 0;
3565}
3566
3567int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
3568{
4945002d 3569 struct zapi_nexthop *znh;
ea6b290b 3570
bad6b0e7
RW
3571 memset(zl, 0, sizeof(*zl));
3572
3573 /* Get data. */
b3c49d0e 3574 STREAM_GETC(s, zl->message);
bad6b0e7 3575 STREAM_GETC(s, zl->type);
b3c49d0e 3576 STREAM_GETL(s, zl->local_label);
bad6b0e7 3577
b3c49d0e
RW
3578 if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
3579 size_t psize;
3580
3581 STREAM_GETW(s, zl->route.prefix.family);
3582 STREAM_GETC(s, zl->route.prefix.prefixlen);
3583
3584 psize = PSIZE(zl->route.prefix.prefixlen);
3585 switch (zl->route.prefix.family) {
3586 case AF_INET:
3587 if (zl->route.prefix.prefixlen > IPV4_MAX_BITLEN) {
3588 zlog_debug(
3589 "%s: Specified prefix length %d is greater than a v4 address can support",
15569c58 3590 __func__, zl->route.prefix.prefixlen);
b3c49d0e
RW
3591 return -1;
3592 }
3593 STREAM_GET(&zl->route.prefix.u.prefix4.s_addr, s,
3594 psize);
3595 break;
3596 case AF_INET6:
3597 if (zl->route.prefix.prefixlen > IPV6_MAX_BITLEN) {
3598 zlog_debug(
3599 "%s: Specified prefix length %d is greater than a v6 address can support",
15569c58 3600 __func__, zl->route.prefix.prefixlen);
b3c49d0e
RW
3601 return -1;
3602 }
3603 STREAM_GET(&zl->route.prefix.u.prefix6, s, psize);
3604 break;
3605 default:
3606 flog_err(EC_LIB_ZAPI_ENCODE,
3607 "%s: Specified family %u is not v4 or v6",
15569c58 3608 __func__, zl->route.prefix.family);
bad6b0e7
RW
3609 return -1;
3610 }
b3c49d0e
RW
3611
3612 STREAM_GETC(s, zl->route.type);
3613 STREAM_GETW(s, zl->route.instance);
3614 }
3615
ea6b290b 3616 STREAM_GETW(s, zl->nexthop_num);
b900b3c6
QY
3617
3618 if (zl->nexthop_num > MULTIPATH_NUM) {
3619 flog_warn(
3620 EC_LIB_ZAPI_ENCODE,
3621 "%s: Prefix %pFX has %d nexthops, but we can only use the first %d",
3622 __func__, &zl->route.prefix, zl->nexthop_num,
3623 MULTIPATH_NUM);
3624 }
3625
3626 zl->nexthop_num = MIN(MULTIPATH_NUM, zl->nexthop_num);
3627
ea6b290b
RW
3628 for (int i = 0; i < zl->nexthop_num; i++) {
3629 znh = &zl->nexthops[i];
3630
31f937fb 3631 if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
4945002d 3632 return -1;
b7457b40
DS
3633
3634 if (znh->type == NEXTHOP_TYPE_BLACKHOLE) {
3635 flog_warn(
3636 EC_LIB_ZAPI_ENCODE,
3637 "%s: Prefix %pFX has a blackhole nexthop which we cannot use for a label",
3638 __func__, &zl->route.prefix);
3639 return -1;
3640 }
bad6b0e7 3641 }
bad6b0e7 3642
34f86754
MS
3643 if (CHECK_FLAG(zl->message, ZAPI_LABELS_HAS_BACKUPS)) {
3644 STREAM_GETW(s, zl->backup_nexthop_num);
3645
3646 if (zl->backup_nexthop_num > MULTIPATH_NUM) {
3647 flog_warn(
3648 EC_LIB_ZAPI_ENCODE,
3649 "%s: Prefix %pFX has %d backup nexthops, but we can only use the first %d",
3650 __func__, &zl->route.prefix,
3651 zl->backup_nexthop_num, MULTIPATH_NUM);
3652 }
3653
3654 zl->backup_nexthop_num = MIN(MULTIPATH_NUM,
3655 zl->backup_nexthop_num);
3656
3657 for (int i = 0; i < zl->backup_nexthop_num; i++) {
3658 znh = &zl->backup_nexthops[i];
3659
31f937fb 3660 if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
34f86754 3661 return -1;
b7457b40
DS
3662
3663 if (znh->type == NEXTHOP_TYPE_BLACKHOLE) {
3664 flog_warn(
3665 EC_LIB_ZAPI_ENCODE,
3666 "%s: Prefix %pFX has a backup blackhole nexthop which we cannot use for a label",
3667 __func__, &zl->route.prefix);
3668 return -1;
3669 }
34f86754
MS
3670 }
3671 }
3672
bad6b0e7
RW
3673 return 0;
3674stream_failure:
3675 return -1;
3676}
75fb51c1 3677
7cfdb485
DS
3678enum zclient_send_status zebra_send_pw(struct zclient *zclient, int command,
3679 struct zapi_pw *pw)
6833ae01 3680{
3681 struct stream *s;
3682
3683 /* Reset stream. */
3684 s = zclient->obuf;
3685 stream_reset(s);
3686
3687 zclient_create_header(s, command, VRF_DEFAULT);
3682bd90 3688 stream_write(s, pw->ifname, INTERFACE_NAMSIZ);
6833ae01 3689 stream_putl(s, pw->ifindex);
3690
3691 /* Put type */
3692 stream_putl(s, pw->type);
3693
3694 /* Put nexthop */
3695 stream_putl(s, pw->af);
3696 switch (pw->af) {
3697 case AF_INET:
3698 stream_put_in_addr(s, &pw->nexthop.ipv4);
3699 break;
3700 case AF_INET6:
d7c0a89a 3701 stream_write(s, (uint8_t *)&pw->nexthop.ipv6, 16);
6833ae01 3702 break;
3703 default:
1c50c1c0 3704 flog_err(EC_LIB_ZAPI_ENCODE, "%s: unknown af", __func__);
7cfdb485 3705 return ZCLIENT_SEND_FAILURE;
6833ae01 3706 }
3707
3708 /* Put labels */
3709 stream_putl(s, pw->local_label);
3710 stream_putl(s, pw->remote_label);
3711
3712 /* Put flags */
3713 stream_putc(s, pw->flags);
3714
3715 /* Protocol specific fields */
3716 stream_write(s, &pw->data, sizeof(union pw_protocol_fields));
3717
3718 /* Put length at the first point of the stream. */
3719 stream_putw_at(s, 0, stream_get_endp(s));
3720
3721 return zclient_send_message(zclient);
3722}
3723
3724/*
3725 * Receive PW status update from Zebra and send it to LDE process.
3726 */
efc7191b 3727int zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_status *pw)
6833ae01 3728{
3729 struct stream *s;
3730
3731 memset(pw, 0, sizeof(struct zapi_pw_status));
3732 s = zclient->ibuf;
3733
3734 /* Get data. */
3682bd90 3735 stream_get(pw->ifname, s, INTERFACE_NAMSIZ);
efc7191b
QY
3736 STREAM_GETL(s, pw->ifindex);
3737 STREAM_GETL(s, pw->status);
3738
3739 return 0;
3740stream_failure:
3741 return -1;
6833ae01 3742}
3743
a243d1db 3744static int zclient_capability_decode(ZAPI_CALLBACK_ARGS)
09924cff
DS
3745{
3746 struct zclient_capabilities cap;
3747 struct stream *s = zclient->ibuf;
bb6b7f79 3748 int vrf_backend;
09924cff
DS
3749 uint8_t mpls_enabled;
3750
bb6b7f79 3751 STREAM_GETL(s, vrf_backend);
7239d3d9
QY
3752
3753 if (vrf_backend < 0 || vrf_configure_backend(vrf_backend)) {
3754 flog_err(EC_LIB_ZAPI_ENCODE,
1d5453d6 3755 "%s: Garbage VRF backend type: %d", __func__,
7239d3d9
QY
3756 vrf_backend);
3757 goto stream_failure;
3758 }
3759
bb6b7f79 3760
09924cff
DS
3761 memset(&cap, 0, sizeof(cap));
3762 STREAM_GETC(s, mpls_enabled);
3763 cap.mpls_enabled = !!mpls_enabled;
3764 STREAM_GETL(s, cap.ecmp);
02c0866d 3765 STREAM_GETC(s, cap.role);
09924cff
DS
3766
3767 if (zclient->zebra_capabilities)
3768 (*zclient->zebra_capabilities)(&cap);
3769
3770stream_failure:
a243d1db 3771 return 0;
09924cff
DS
3772}
3773
7cfdb485
DS
3774enum zclient_send_status zclient_send_mlag_register(struct zclient *client,
3775 uint32_t bit_map)
36b5b98f
SK
3776{
3777 struct stream *s;
3778
3779 s = client->obuf;
3780 stream_reset(s);
3781
3782 zclient_create_header(s, ZEBRA_MLAG_CLIENT_REGISTER, VRF_DEFAULT);
3783 stream_putl(s, bit_map);
3784
3785 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 3786 return zclient_send_message(client);
36b5b98f
SK
3787}
3788
7cfdb485 3789enum zclient_send_status zclient_send_mlag_deregister(struct zclient *client)
36b5b98f 3790{
4df9d859
HS
3791 return zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER,
3792 VRF_DEFAULT);
36b5b98f
SK
3793}
3794
7cfdb485
DS
3795enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
3796 struct stream *client_s)
36b5b98f
SK
3797{
3798 struct stream *s;
3799
3800 s = client->obuf;
3801 stream_reset(s);
3802
3803 zclient_create_header(s, ZEBRA_MLAG_FORWARD_MSG, VRF_DEFAULT);
3804 stream_put(s, client_s->data, client_s->endp);
3805
3806 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 3807 return zclient_send_message(client);
36b5b98f
SK
3808}
3809
ff491140
MS
3810/*
3811 * Send an OPAQUE message, contents opaque to zebra. The message header
3812 * is a message subtype.
3813 */
7cfdb485
DS
3814enum zclient_send_status zclient_send_opaque(struct zclient *zclient,
3815 uint32_t type, const uint8_t *data,
3816 size_t datasize)
ff491140 3817{
ff491140 3818 struct stream *s;
387831ff 3819 uint16_t flags = 0;
ff491140
MS
3820
3821 /* Check buffer size */
3822 if (STREAM_SIZE(zclient->obuf) <
3823 (ZEBRA_HEADER_SIZE + sizeof(type) + datasize))
7cfdb485 3824 return ZCLIENT_SEND_FAILURE;
ff491140
MS
3825
3826 s = zclient->obuf;
3827 stream_reset(s);
3828
3829 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
3830
387831ff 3831 /* Send sub-type and flags */
ff491140 3832 stream_putl(s, type);
387831ff 3833 stream_putw(s, flags);
ff491140
MS
3834
3835 /* Send opaque data */
3836 stream_write(s, data, datasize);
3837
3838 /* Put length into the header at the start of the stream. */
3839 stream_putw_at(s, 0, stream_get_endp(s));
3840
db71415b 3841 return zclient_send_message(zclient);
ff491140
MS
3842}
3843
387831ff
MS
3844/*
3845 * Send an OPAQUE message to a specific zclient. The contents are opaque
3846 * to zebra.
3847 */
7cfdb485
DS
3848enum zclient_send_status
3849zclient_send_opaque_unicast(struct zclient *zclient, uint32_t type,
3850 uint8_t proto, uint16_t instance,
3851 uint32_t session_id, const uint8_t *data,
3852 size_t datasize)
387831ff 3853{
387831ff
MS
3854 struct stream *s;
3855 uint16_t flags = 0;
3856
3857 /* Check buffer size */
3858 if (STREAM_SIZE(zclient->obuf) <
3859 (ZEBRA_HEADER_SIZE + sizeof(struct zapi_opaque_msg) + datasize))
7cfdb485 3860 return ZCLIENT_SEND_FAILURE;
387831ff
MS
3861
3862 s = zclient->obuf;
3863 stream_reset(s);
3864
3865 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
3866
3867 /* Send sub-type and flags */
3868 SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
3869 stream_putl(s, type);
3870 stream_putw(s, flags);
3871
3872 /* Send destination client info */
3873 stream_putc(s, proto);
3874 stream_putw(s, instance);
3875 stream_putl(s, session_id);
3876
3877 /* Send opaque data */
3878 stream_write(s, data, datasize);
3879
3880 /* Put length into the header at the start of the stream. */
3881 stream_putw_at(s, 0, stream_get_endp(s));
3882
db71415b 3883 return zclient_send_message(zclient);
387831ff
MS
3884}
3885
3886/*
3887 * Decode incoming opaque message into info struct
3888 */
3889int zclient_opaque_decode(struct stream *s, struct zapi_opaque_msg *info)
3890{
3891 memset(info, 0, sizeof(*info));
3892
3893 /* Decode subtype and flags */
3894 STREAM_GETL(s, info->type);
3895 STREAM_GETW(s, info->flags);
3896
3897 /* Decode unicast client info if present */
3898 if (CHECK_FLAG(info->flags, ZAPI_OPAQUE_FLAG_UNICAST)) {
3899 STREAM_GETC(s, info->proto);
3900 STREAM_GETW(s, info->instance);
3901 STREAM_GETL(s, info->session_id);
3902 }
3903
3904 info->len = STREAM_READABLE(s);
3905
3906 return 0;
3907
3908stream_failure:
3909
3910 return -1;
3911}
3912
ff491140
MS
3913/*
3914 * Send a registration request for opaque messages with a specified subtype.
3915 */
7cfdb485
DS
3916enum zclient_send_status zclient_register_opaque(struct zclient *zclient,
3917 uint32_t type)
ff491140 3918{
ff491140
MS
3919 struct stream *s;
3920
3921 s = zclient->obuf;
3922 stream_reset(s);
3923
3924 zclient_create_header(s, ZEBRA_OPAQUE_REGISTER, VRF_DEFAULT);
3925
3926 /* Send sub-type */
3927 stream_putl(s, type);
3928
3929 /* Add zclient info */
3930 stream_putc(s, zclient->redist_default);
3931 stream_putw(s, zclient->instance);
3932 stream_putl(s, zclient->session_id);
3933
3934 /* Put length at the first point of the stream. */
3935 stream_putw_at(s, 0, stream_get_endp(s));
3936
db71415b 3937 return zclient_send_message(zclient);
ff491140
MS
3938}
3939
3940/*
3941 * Send an un-registration request for a specified opaque subtype.
3942 */
7cfdb485
DS
3943enum zclient_send_status zclient_unregister_opaque(struct zclient *zclient,
3944 uint32_t type)
ff491140 3945{
ff491140
MS
3946 struct stream *s;
3947
3948 s = zclient->obuf;
3949 stream_reset(s);
3950
3951 zclient_create_header(s, ZEBRA_OPAQUE_UNREGISTER, VRF_DEFAULT);
3952
3953 /* Send sub-type */
3954 stream_putl(s, type);
3955
3956 /* Add zclient info */
3957 stream_putc(s, zclient->redist_default);
3958 stream_putw(s, zclient->instance);
3959 stream_putl(s, zclient->session_id);
3960
3961 /* Put length at the first point of the stream. */
3962 stream_putw_at(s, 0, stream_get_endp(s));
3963
db71415b 3964 return zclient_send_message(zclient);
ff491140
MS
3965}
3966
d2ddc141 3967/* Utility to decode opaque registration info */
387831ff 3968int zapi_opaque_reg_decode(struct stream *s, struct zapi_opaque_reg_info *info)
ff491140
MS
3969{
3970 STREAM_GETL(s, info->type);
3971 STREAM_GETC(s, info->proto);
3972 STREAM_GETW(s, info->instance);
3973 STREAM_GETL(s, info->session_id);
3974
3975 return 0;
3976
3977stream_failure:
3978
3979 return -1;
3980}
3981
581e797e
KS
3982/* Utility to decode client close notify info */
3983int zapi_client_close_notify_decode(struct stream *s,
3984 struct zapi_client_close_info *info)
3985{
3986 memset(info, 0, sizeof(*info));
3987
3988 STREAM_GETC(s, info->proto);
3989 STREAM_GETW(s, info->instance);
3990 STREAM_GETL(s, info->session_id);
3991
3992 return 0;
3993
3994stream_failure:
3995
3996 return -1;
3997}
3998
a243d1db
DL
3999static zclient_handler *const lib_handlers[] = {
4000 /* fundamentals */
4001 [ZEBRA_CAPABILITIES] = zclient_capability_decode,
4002 [ZEBRA_ERROR] = zclient_handle_error,
4003
4004 /* VRF & interface code is shared in lib */
4005 [ZEBRA_VRF_ADD] = zclient_vrf_add,
4006 [ZEBRA_VRF_DELETE] = zclient_vrf_delete,
4007 [ZEBRA_INTERFACE_ADD] = zclient_interface_add,
4008 [ZEBRA_INTERFACE_DELETE] = zclient_interface_delete,
4009 [ZEBRA_INTERFACE_UP] = zclient_interface_up,
4010 [ZEBRA_INTERFACE_DOWN] = zclient_interface_down,
4011
4012 /* BFD */
3e51a84a 4013 [ZEBRA_BFD_DEST_REPLAY] = zclient_bfd_session_replay,
a243d1db
DL
4014 [ZEBRA_INTERFACE_BFD_DEST_UPDATE] = zclient_bfd_session_update,
4015};
4016
718e3744 4017/* Zebra client message read function. */
cc9f21da 4018static void zclient_read(struct thread *thread)
718e3744 4019{
d62a17ae 4020 size_t already;
4021 uint16_t length, command;
4022 uint8_t marker, version;
4023 vrf_id_t vrf_id;
4024 struct zclient *zclient;
4025
4026 /* Get socket to zebra. */
4027 zclient = THREAD_ARG(thread);
4028 zclient->t_read = NULL;
4029
4030 /* Read zebra header (if we don't have it already). */
0e2d7076
DA
4031 already = stream_get_endp(zclient->ibuf);
4032 if (already < ZEBRA_HEADER_SIZE) {
d62a17ae 4033 ssize_t nbyte;
4034 if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
4035 ZEBRA_HEADER_SIZE - already))
4036 == 0)
4037 || (nbyte == -1)) {
4038 if (zclient_debug)
4039 zlog_debug(
4040 "zclient connection closed socket [%d].",
4041 zclient->sock);
cc9f21da
DS
4042 zclient_failed(zclient);
4043 return;
d62a17ae 4044 }
4045 if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
d62a17ae 4046 zclient_event(ZCLIENT_READ, zclient);
cc9f21da 4047 return;
d62a17ae 4048 }
4049 already = ZEBRA_HEADER_SIZE;
634f9ea2 4050 }
d62a17ae 4051
4052 /* Reset to read from the beginning of the incoming packet. */
4053 stream_set_getp(zclient->ibuf, 0);
4054
4055 /* Fetch header values. */
4056 length = stream_getw(zclient->ibuf);
4057 marker = stream_getc(zclient->ibuf);
4058 version = stream_getc(zclient->ibuf);
a9ff90c4 4059 vrf_id = stream_getl(zclient->ibuf);
d62a17ae 4060 command = stream_getw(zclient->ibuf);
4061
4062 if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
1c50c1c0
QY
4063 flog_err(
4064 EC_LIB_ZAPI_MISSMATCH,
4065 "%s: socket %d version mismatch, marker %d, version %d",
4066 __func__, zclient->sock, marker, version);
cc9f21da
DS
4067 zclient_failed(zclient);
4068 return;
634f9ea2 4069 }
d62a17ae 4070
4071 if (length < ZEBRA_HEADER_SIZE) {
450971aa 4072 flog_err(EC_LIB_ZAPI_MISSMATCH,
1c50c1c0
QY
4073 "%s: socket %d message length %u is less than %d ",
4074 __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
cc9f21da
DS
4075 zclient_failed(zclient);
4076 return;
634f9ea2 4077 }
d62a17ae 4078
4079 /* Length check. */
4080 if (length > STREAM_SIZE(zclient->ibuf)) {
4081 struct stream *ns;
ade6974d 4082 flog_err(
450971aa 4083 EC_LIB_ZAPI_ENCODE,
ade6974d
QY
4084 "%s: message size %u exceeds buffer size %lu, expanding...",
4085 __func__, length,
4086 (unsigned long)STREAM_SIZE(zclient->ibuf));
d62a17ae 4087 ns = stream_new(length);
4088 stream_copy(ns, zclient->ibuf);
4089 stream_free(zclient->ibuf);
4090 zclient->ibuf = ns;
4091 }
4092
4093 /* Read rest of zebra packet. */
4094 if (already < length) {
4095 ssize_t nbyte;
4096 if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
4097 length - already))
4098 == 0)
4099 || (nbyte == -1)) {
4100 if (zclient_debug)
4101 zlog_debug(
4102 "zclient connection closed socket [%d].",
4103 zclient->sock);
cc9f21da
DS
4104 zclient_failed(zclient);
4105 return;
d62a17ae 4106 }
4107 if (nbyte != (ssize_t)(length - already)) {
4108 /* Try again later. */
4109 zclient_event(ZCLIENT_READ, zclient);
cc9f21da 4110 return;
d62a17ae 4111 }
4112 }
4113
4114 length -= ZEBRA_HEADER_SIZE;
4115
4116 if (zclient_debug)
461d106d
RW
4117 zlog_debug("zclient %p command %s VRF %u", zclient,
4118 zserv_command_string(command), vrf_id);
d62a17ae 4119
a243d1db
DL
4120 if (command < array_size(lib_handlers) && lib_handlers[command])
4121 lib_handlers[command](command, zclient, length, vrf_id);
4122 if (command < zclient->n_handlers && zclient->handlers[command])
4123 zclient->handlers[command](command, zclient, length, vrf_id);
d62a17ae 4124
4125 if (zclient->sock < 0)
4126 /* Connection was closed during packet processing. */
cc9f21da 4127 return;
d62a17ae 4128
4129 /* Register read thread. */
4130 stream_reset(zclient->ibuf);
4131 zclient_event(ZCLIENT_READ, zclient);
718e3744 4132}
4133
d62a17ae 4134void zclient_redistribute(int command, struct zclient *zclient, afi_t afi,
d7c0a89a 4135 int type, unsigned short instance, vrf_id_t vrf_id)
718e3744 4136{
718e3744 4137
d62a17ae 4138 if (instance) {
4139 if (command == ZEBRA_REDISTRIBUTE_ADD) {
4140 if (redist_check_instance(
4141 &zclient->mi_redist[afi][type], instance))
4142 return;
4143 redist_add_instance(&zclient->mi_redist[afi][type],
4144 instance);
4145 } else {
4146 if (!redist_check_instance(
4147 &zclient->mi_redist[afi][type], instance))
4148 return;
4149 redist_del_instance(&zclient->mi_redist[afi][type],
4150 instance);
4151 }
4152
4153 } else {
4154 if (command == ZEBRA_REDISTRIBUTE_ADD) {
4155 if (vrf_bitmap_check(zclient->redist[afi][type],
4156 vrf_id))
4157 return;
4158 vrf_bitmap_set(zclient->redist[afi][type], vrf_id);
4159 } else {
4160 if (!vrf_bitmap_check(zclient->redist[afi][type],
4161 vrf_id))
4162 return;
4163 vrf_bitmap_unset(zclient->redist[afi][type], vrf_id);
4164 }
4165 }
4166
4167 if (zclient->sock > 0)
4168 zebra_redistribute_send(command, zclient, afi, type, instance,
4169 vrf_id);
718e3744 4170}
4171
718e3744 4172
d62a17ae 4173void zclient_redistribute_default(int command, struct zclient *zclient,
49db7a7b 4174 afi_t afi, vrf_id_t vrf_id)
718e3744 4175{
718e3744 4176
d62a17ae 4177 if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) {
49db7a7b 4178 if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
d62a17ae 4179 return;
49db7a7b 4180 vrf_bitmap_set(zclient->default_information[afi], vrf_id);
d62a17ae 4181 } else {
49db7a7b
RW
4182 if (!vrf_bitmap_check(zclient->default_information[afi],
4183 vrf_id))
d62a17ae 4184 return;
49db7a7b 4185 vrf_bitmap_unset(zclient->default_information[afi], vrf_id);
d62a17ae 4186 }
4187
4188 if (zclient->sock > 0)
49db7a7b 4189 zebra_redistribute_default_send(command, zclient, afi, vrf_id);
718e3744 4190}
4191
91f2045d 4192static void zclient_event(enum zclient_event event, struct zclient *zclient)
718e3744 4193{
d62a17ae 4194 switch (event) {
4195 case ZCLIENT_SCHEDULE:
4196 thread_add_event(zclient->master, zclient_connect, zclient, 0,
4197 &zclient->t_connect);
4198 break;
4199 case ZCLIENT_CONNECT:
4200 if (zclient_debug)
4201 zlog_debug(
4202 "zclient connect failures: %d schedule interval is now %d",
4203 zclient->fail, zclient->fail < 3 ? 10 : 60);
4204 thread_add_timer(zclient->master, zclient_connect, zclient,
4205 zclient->fail < 3 ? 10 : 60,
4206 &zclient->t_connect);
4207 break;
4208 case ZCLIENT_READ:
4209 zclient->t_read = NULL;
4210 thread_add_read(zclient->master, zclient_read, zclient,
4211 zclient->sock, &zclient->t_read);
4212 break;
4213 }
718e3744 4214}
b5114685 4215
7cfdb485
DS
4216enum zclient_send_status zclient_interface_set_master(struct zclient *client,
4217 struct interface *master,
4218 struct interface *slave)
e0ae31b8
DS
4219{
4220 struct stream *s;
4221
4222 s = client->obuf;
4223 stream_reset(s);
4224
096f7609
IR
4225 zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER,
4226 master->vrf->vrf_id);
e0ae31b8 4227
096f7609 4228 stream_putl(s, master->vrf->vrf_id);
e0ae31b8 4229 stream_putl(s, master->ifindex);
096f7609 4230 stream_putl(s, slave->vrf->vrf_id);
e0ae31b8
DS
4231 stream_putl(s, slave->ifindex);
4232
4233 stream_putw_at(s, 0, stream_get_endp(s));
db71415b 4234 return zclient_send_message(client);
e0ae31b8 4235}
eb451ee5 4236
be7bbe52
S
4237/*
4238 * Send capabilities message to zebra
4239 */
7cfdb485
DS
4240enum zclient_send_status zclient_capabilities_send(uint32_t cmd,
4241 struct zclient *zclient,
4242 struct zapi_cap *api)
eb451ee5 4243{
be7bbe52
S
4244
4245 struct stream *s;
4246
4247 if (zclient == NULL)
7cfdb485 4248 return ZCLIENT_SEND_FAILURE;
be7bbe52
S
4249
4250 s = zclient->obuf;
4251 stream_reset(s);
4252 zclient_create_header(s, cmd, 0);
4253 stream_putl(s, api->cap);
4254
4255 switch (api->cap) {
4256 case ZEBRA_CLIENT_GR_CAPABILITIES:
4257 case ZEBRA_CLIENT_RIB_STALE_TIME:
4258 stream_putl(s, api->stale_removal_time);
4259 stream_putl(s, api->vrf_id);
4260 break;
4261 case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
4262 case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
4263 stream_putl(s, api->afi);
4264 stream_putl(s, api->safi);
4265 stream_putl(s, api->vrf_id);
4266 break;
4267 case ZEBRA_CLIENT_GR_DISABLE:
4268 stream_putl(s, api->vrf_id);
4269 break;
4270 }
4271
4272 /* Put length at the first point of the stream */
4273 stream_putw_at(s, 0, stream_get_endp(s));
4274
4275 return zclient_send_message(zclient);
4276}
4277
4278/*
4279 * Process capabilities message from zebra
4280 */
4281int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
4282{
4283
eb451ee5 4284 memset(api, 0, sizeof(*api));
4285
4286 STREAM_GETL(s, api->cap);
4287 switch (api->cap) {
4288 case ZEBRA_CLIENT_GR_CAPABILITIES:
4289 case ZEBRA_CLIENT_RIB_STALE_TIME:
be7bbe52
S
4290 STREAM_GETL(s, api->stale_removal_time);
4291 STREAM_GETL(s, api->vrf_id);
4292 break;
eb451ee5 4293 case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
4294 case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
be7bbe52
S
4295 STREAM_GETL(s, api->afi);
4296 STREAM_GETL(s, api->safi);
4297 STREAM_GETL(s, api->vrf_id);
4298 break;
eb451ee5 4299 case ZEBRA_CLIENT_GR_DISABLE:
be7bbe52
S
4300 STREAM_GETL(s, api->vrf_id);
4301 break;
eb451ee5 4302 }
4303stream_failure:
4304 return 0;
4305}
d68e74b4 4306
7cfdb485
DS
4307enum zclient_send_status
4308zclient_send_neigh_discovery_req(struct zclient *zclient,
4309 const struct interface *ifp,
4310 const struct prefix *p)
d68e74b4
JU
4311{
4312 struct stream *s;
4313
4314 s = zclient->obuf;
4315 stream_reset(s);
4316
096f7609 4317 zclient_create_header(s, ZEBRA_NEIGH_DISCOVER, ifp->vrf->vrf_id);
d68e74b4
JU
4318 stream_putl(s, ifp->ifindex);
4319
4320 stream_putc(s, p->family);
4321 stream_putc(s, p->prefixlen);
4322 stream_put(s, &p->u.prefix, prefix_blen(p));
4323
4324 stream_putw_at(s, 0, stream_get_endp(s));
4325 return zclient_send_message(zclient);
4326}
224b3c8a
DS
4327
4328/*
4329 * Get a starting nhg point for a routing protocol
4330 */
4331uint32_t zclient_get_nhg_start(uint32_t proto)
4332{
4333 assert(proto < ZEBRA_ROUTE_MAX);
4334
54c89c93 4335 return ZEBRA_NHG_PROTO_SPACING * proto;
6c67f41f 4336}
61e6de9d
DS
4337
4338char *zclient_dump_route_flags(uint32_t flags, char *buf, size_t len)
4339{
4340 if (flags == 0) {
4341 snprintfrr(buf, len, "None ");
4342 return buf;
4343 }
4344
4345 snprintfrr(
4346 buf, len, "%s%s%s%s%s%s%s%s%s%s",
4347 CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion "
4348 : "",
4349 CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "",
4350 CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "",
4351 CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "",
4352 CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "",
4353 CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "",
4354 CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance "
4355 : "",
4356 CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "",
4357 CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "",
4358 CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED) ? "Offload Failed "
4359 : "");
4360 return buf;
4361}
bf902d4c
DS
4362
4363char *zclient_evpn_dump_macip_flags(uint8_t flags, char *buf, size_t len)
4364{
4365 if (flags == 0) {
4366 snprintfrr(buf, len, "None ");
4367 return buf;
4368 }
4369
4370 snprintfrr(
4371 buf, len, "%s%s%s%s%s%s%s",
4372 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? "Sticky MAC " : "",
4373 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? "Gateway MAC " : "",
4374 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG) ? "Router "
4375 : "",
4376 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_OVERRIDE_FLAG) ? "Override "
4377 : "",
4378 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP) ? "SVI MAC " : "",
4379 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT) ? "Proxy "
4380 : "",
4381 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH) ? "Sync " : "");
4382
4383 return buf;
4384}
d603c077
PG
4385
4386static int zclient_neigh_ip_read_entry(struct stream *s, struct ipaddr *add)
4387{
4388 uint8_t family;
4389
4390 STREAM_GETC(s, family);
4391 if (family != AF_INET && family != AF_INET6)
4392 return -1;
4393
4394 STREAM_GET(&add->ip.addr, s, family2addrsize(family));
4395 add->ipa_type = family;
4396 return 0;
4397 stream_failure:
4398 return -1;
4399}
4400
c4e1fd52
PG
4401int zclient_neigh_ip_encode(struct stream *s, uint16_t cmd, union sockunion *in,
4402 union sockunion *out, struct interface *ifp,
4403 int ndm_state)
d603c077
PG
4404{
4405 int ret = 0;
4406
096f7609 4407 zclient_create_header(s, cmd, ifp->vrf->vrf_id);
d603c077
PG
4408 stream_putc(s, sockunion_family(in));
4409 stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in));
4410 if (out && sockunion_family(out) != AF_UNSPEC) {
4411 stream_putc(s, sockunion_family(out));
4412 stream_write(s, sockunion_get_addr(out),
4413 sockunion_get_addrlen(out));
4414 } else
4415 stream_putc(s, AF_UNSPEC);
4416 stream_putl(s, ifp->ifindex);
4417 if (out)
c4e1fd52 4418 stream_putl(s, ndm_state);
d603c077
PG
4419 else
4420 stream_putl(s, ZEBRA_NEIGH_STATE_FAILED);
4421 return ret;
4422}
4423
4424int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api)
4425{
4426 int ret;
4427
4428 ret = zclient_neigh_ip_read_entry(s, &api->ip_in);
4429 if (ret < 0)
4430 return -1;
4431 zclient_neigh_ip_read_entry(s, &api->ip_out);
4432
4433 STREAM_GETL(s, api->index);
4434 STREAM_GETL(s, api->ndm_state);
4435 return 0;
4436 stream_failure:
4437 return -1;
4438}
d17af8dd
PG
4439
4440int zclient_send_zebra_gre_request(struct zclient *client,
4441 struct interface *ifp)
4442{
4443 struct stream *s;
d17af8dd
PG
4444
4445 if (!client || client->sock < 0) {
4446 zlog_err("%s : zclient not ready", __func__);
4447 return -1;
4448 }
4449 s = client->obuf;
4450 stream_reset(s);
096f7609 4451 zclient_create_header(s, ZEBRA_GRE_GET, ifp->vrf->vrf_id);
d17af8dd
PG
4452 stream_putl(s, ifp->ifindex);
4453 stream_putw_at(s, 0, stream_get_endp(s));
4454 zclient_send_message(client);
4455 return 0;
d17af8dd 4456}