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