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