]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zserv.c
pimd: Fix igmp(*,G) not influencing S,G mroutes
[mirror_frr.git] / zebra / zserv.c
CommitLineData
718e3744 1/* Zebra daemon server routine.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "command.h"
26#include "if.h"
27#include "thread.h"
28#include "stream.h"
29#include "memory.h"
4a1ab8e4 30#include "zebra_memory.h"
718e3744 31#include "table.h"
32#include "rib.h"
33#include "network.h"
34#include "sockunion.h"
35#include "log.h"
36#include "zclient.h"
edd7c245 37#include "privs.h"
719e9741 38#include "network.h"
39#include "buffer.h"
fb018d25 40#include "nexthop.h"
78104b9b 41#include "vrf.h"
718e3744 42
43#include "zebra/zserv.h"
7c551956
DS
44#include "zebra/zebra_ns.h"
45#include "zebra/zebra_vrf.h"
18a6dce6 46#include "zebra/router-id.h"
718e3744 47#include "zebra/redistribute.h"
48#include "zebra/debug.h"
49#include "zebra/ipforward.h"
fb018d25 50#include "zebra/zebra_rnh.h"
5c610faf 51#include "zebra/rt_netlink.h"
88177fe3
DS
52#include "zebra/interface.h"
53#include "zebra/zebra_ptm.h"
4a04e5f7 54#include "zebra/rtadv.h"
ce549947 55#include "zebra/zebra_mpls.h"
518acd6f 56#include "zebra/zebra_fpm.h"
6b0655a2 57
718e3744 58/* Event list of zebra. */
59enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
60
b9df2d25 61static void zebra_event (enum event event, int sock, struct zserv *client);
ccf3557b 62
edd7c245 63extern struct zebra_privs_t zserv_privs;
6b0655a2 64
719e9741 65static void zebra_client_close (struct zserv *client);
ccf3557b 66
719e9741 67static int
68zserv_delayed_close(struct thread *thread)
ccf3557b 69{
719e9741 70 struct zserv *client = THREAD_ARG(thread);
ccf3557b 71
719e9741 72 client->t_suicide = NULL;
73 zebra_client_close(client);
ccf3557b 74 return 0;
75}
76
719e9741 77static int
78zserv_flush_data(struct thread *thread)
ccf3557b 79{
719e9741 80 struct zserv *client = THREAD_ARG(thread);
ccf3557b 81
719e9741 82 client->t_write = NULL;
83 if (client->t_suicide)
ccf3557b 84 {
719e9741 85 zebra_client_close(client);
86 return -1;
ccf3557b 87 }
719e9741 88 switch (buffer_flush_available(client->wb, client->sock))
ccf3557b 89 {
719e9741 90 case BUFFER_ERROR:
91 zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, "
92 "closing", __func__, client->sock);
93 zebra_client_close(client);
94 break;
95 case BUFFER_PENDING:
96 client->t_write = thread_add_write(zebrad.master, zserv_flush_data,
97 client, client->sock);
98 break;
99 case BUFFER_EMPTY:
100 break;
ccf3557b 101 }
04b02fda 102
2176b7c3 103 client->last_write_time = quagga_monotime();
719e9741 104 return 0;
105}
ccf3557b 106
fb018d25 107int
719e9741 108zebra_server_send_message(struct zserv *client)
109{
110 if (client->t_suicide)
111 return -1;
04b02fda
DS
112
113 stream_set_getp(client->obuf, 0);
80ab3edf 114 client->last_write_cmd = stream_getw_from(client->obuf, 6);
719e9741 115 switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf),
116 stream_get_endp(client->obuf)))
117 {
118 case BUFFER_ERROR:
119 zlog_warn("%s: buffer_write failed to zserv client fd %d, closing",
120 __func__, client->sock);
121 /* Schedule a delayed close since many of the functions that call this
122 one do not check the return code. They do not allow for the
123 possibility that an I/O error may have caused the client to be
124 deleted. */
125 client->t_suicide = thread_add_event(zebrad.master, zserv_delayed_close,
126 client, 0);
127 return -1;
719e9741 128 case BUFFER_EMPTY:
129 THREAD_OFF(client->t_write);
130 break;
131 case BUFFER_PENDING:
132 THREAD_WRITE_ON(zebrad.master, client->t_write,
133 zserv_flush_data, client, client->sock);
134 break;
135 }
04b02fda 136
2176b7c3 137 client->last_write_time = quagga_monotime();
ccf3557b 138 return 0;
139}
140
fb018d25 141void
7076bb2f 142zserv_create_header (struct stream *s, uint16_t cmd, vrf_id_t vrf_id)
c1b9800a 143{
144 /* length placeholder, caller can update */
145 stream_putw (s, ZEBRA_HEADER_SIZE);
146 stream_putc (s, ZEBRA_HEADER_MARKER);
147 stream_putc (s, ZSERV_VERSION);
7076bb2f 148 stream_putw (s, vrf_id);
c1b9800a 149 stream_putw (s, cmd);
150}
151
51d4ef83
JB
152static void
153zserv_encode_interface (struct stream *s, struct interface *ifp)
154{
155 /* Interface information. */
156 stream_put (s, ifp->name, INTERFACE_NAMSIZ);
157 stream_putl (s, ifp->ifindex);
158 stream_putc (s, ifp->status);
159 stream_putq (s, ifp->flags);
244c1cdc
DS
160 stream_putc (s, ifp->ptm_enable);
161 stream_putc (s, ifp->ptm_status);
51d4ef83
JB
162 stream_putl (s, ifp->metric);
163 stream_putl (s, ifp->mtu);
164 stream_putl (s, ifp->mtu6);
165 stream_putl (s, ifp->bandwidth);
8ccc7e80 166 stream_putl (s, ifp->ll_type);
51d4ef83
JB
167 stream_putl (s, ifp->hw_addr_len);
168 if (ifp->hw_addr_len)
169 stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
51d4ef83 170
16f1b9ee
OD
171 /* Then, Traffic Engineering parameters if any */
172 if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params))
173 {
174 stream_putc (s, 1);
175 zebra_interface_link_params_write (s, ifp);
176 }
177 else
178 stream_putc (s, 0);
179
51d4ef83
JB
180 /* Write packet size. */
181 stream_putw_at (s, 0, stream_get_endp (s));
182}
183
12f6fb97 184static void
9e1bf607 185zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf)
12f6fb97
DS
186{
187 /* Interface information. */
661512bf 188 stream_put (s, zvrf_name (zvrf), VRF_NAMSIZ);
12f6fb97
DS
189
190 /* Write packet size. */
191 stream_putw_at (s, 0, stream_get_endp (s));
192}
193
718e3744 194/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
b9df2d25 195/*
196 * This function is called in the following situations:
197 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
198 * from the client.
199 * - at startup, when zebra figures out the available interfaces
200 * - when an interface is added (where support for
201 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
202 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
203 * received)
204 */
718e3744 205int
206zsend_interface_add (struct zserv *client, struct interface *ifp)
207{
208 struct stream *s;
209
718e3744 210 s = client->obuf;
211 stream_reset (s);
212
7076bb2f 213 zserv_create_header (s, ZEBRA_INTERFACE_ADD, ifp->vrf_id);
51d4ef83 214 zserv_encode_interface (s, ifp);
718e3744 215
04b02fda 216 client->ifadd_cnt++;
719e9741 217 return zebra_server_send_message(client);
718e3744 218}
219
220/* Interface deletion from zebra daemon. */
221int
222zsend_interface_delete (struct zserv *client, struct interface *ifp)
223{
224 struct stream *s;
225
718e3744 226 s = client->obuf;
227 stream_reset (s);
718e3744 228
7076bb2f 229 zserv_create_header (s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id);
51d4ef83 230 zserv_encode_interface (s, ifp);
718e3744 231
04b02fda 232 client->ifdel_cnt++;
719e9741 233 return zebra_server_send_message (client);
718e3744 234}
235
12f6fb97 236int
9e1bf607 237zsend_vrf_add (struct zserv *client, struct zebra_vrf *zvrf)
12f6fb97
DS
238{
239 struct stream *s;
240
241 s = client->obuf;
242 stream_reset (s);
243
661512bf 244 zserv_create_header (s, ZEBRA_VRF_ADD, zvrf_id (zvrf));
9e1bf607 245 zserv_encode_vrf (s, zvrf);
12f6fb97
DS
246
247 client->vrfadd_cnt++;
248 return zebra_server_send_message(client);
249}
250
251/* VRF deletion from zebra daemon. */
252int
9e1bf607 253zsend_vrf_delete (struct zserv *client, struct zebra_vrf *zvrf)
12f6fb97
DS
254{
255 struct stream *s;
256
257 s = client->obuf;
258 stream_reset (s);
259
661512bf 260 zserv_create_header (s, ZEBRA_VRF_DELETE, zvrf_id (zvrf));
9e1bf607 261 zserv_encode_vrf (s, zvrf);
12f6fb97
DS
262
263 client->vrfdel_cnt++;
264 return zebra_server_send_message (client);
265}
266
16f1b9ee
OD
267int
268zsend_interface_link_params (struct zserv *client, struct interface *ifp)
269{
270 struct stream *s;
271
272 /* Check this client need interface information. */
273 if (! client->ifinfo)
274 return 0;
275
276 if (!ifp->link_params)
277 return 0;
278 s = client->obuf;
279 stream_reset (s);
280
281 zserv_create_header (s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id);
282
283 /* Add Interface Index */
284 stream_putl (s, ifp->ifindex);
285
286 /* Then TE Link Parameters */
287 if (zebra_interface_link_params_write (s, ifp) == 0)
288 return 0;
289
290 /* Write packet size. */
291 stream_putw_at (s, 0, stream_get_endp (s));
292
293 return zebra_server_send_message (client);
294}
295
b9df2d25 296/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
297 * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
298 *
299 * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
300 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
301 * from the client, after the ZEBRA_INTERFACE_ADD has been
302 * sent from zebra to the client
303 * - redistribute new address info to all clients in the following situations
304 * - at startup, when zebra figures out the available interfaces
305 * - when an interface is added (where support for
306 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
307 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
308 * received)
309 * - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
310 * and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
311 * - when an RTM_NEWADDR message is received from the kernel,
312 *
313 * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:
314 *
315 * zsend_interface_address(DELETE)
316 * ^
317 * |
318 * zebra_interface_address_delete_update
319 * ^ ^ ^
6eb8827d 320 * | | if_delete_update
321 * | |
b9df2d25 322 * ip_address_uninstall connected_delete_ipv4
323 * [ipv6_addresss_uninstall] [connected_delete_ipv6]
324 * ^ ^
325 * | |
326 * | RTM_NEWADDR on routing/netlink socket
327 * |
328 * vty commands:
329 * "no ip address A.B.C.D/M [label LINE]"
330 * "no ip address A.B.C.D/M secondary"
331 * ["no ipv6 address X:X::X:X/M"]
332 *
333 */
718e3744 334int
b9df2d25 335zsend_interface_address (int cmd, struct zserv *client,
336 struct interface *ifp, struct connected *ifc)
718e3744 337{
338 int blen;
339 struct stream *s;
340 struct prefix *p;
341
718e3744 342 s = client->obuf;
343 stream_reset (s);
c1b9800a 344
7076bb2f 345 zserv_create_header (s, cmd, ifp->vrf_id);
718e3744 346 stream_putl (s, ifp->ifindex);
347
348 /* Interface address flag. */
349 stream_putc (s, ifc->flags);
350
351 /* Prefix information. */
352 p = ifc->address;
353 stream_putc (s, p->family);
354 blen = prefix_blen (p);
355 stream_put (s, &p->u.prefix, blen);
b9df2d25 356
357 /*
358 * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE
359 * but zebra_interface_address_delete_read() in the gnu version
360 * expects to find it
361 */
718e3744 362 stream_putc (s, p->prefixlen);
363
364 /* Destination. */
365 p = ifc->destination;
366 if (p)
367 stream_put (s, &p->u.prefix, blen);
368 else
369 stream_put (s, NULL, blen);
370
371 /* Write packet size. */
372 stream_putw_at (s, 0, stream_get_endp (s));
373
04b02fda 374 client->connected_rt_add_cnt++;
719e9741 375 return zebra_server_send_message(client);
718e3744 376}
377
a80beece
DS
378static int
379zsend_interface_nbr_address (int cmd, struct zserv *client,
380 struct interface *ifp, struct nbr_connected *ifc)
381{
382 int blen;
383 struct stream *s;
384 struct prefix *p;
385
a80beece
DS
386 s = client->obuf;
387 stream_reset (s);
388
7076bb2f 389 zserv_create_header (s, cmd, ifp->vrf_id);
a80beece
DS
390 stream_putl (s, ifp->ifindex);
391
392 /* Prefix information. */
393 p = ifc->address;
394 stream_putc (s, p->family);
395 blen = prefix_blen (p);
396 stream_put (s, &p->u.prefix, blen);
397
398 /*
399 * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE
400 * but zebra_interface_address_delete_read() in the gnu version
401 * expects to find it
402 */
403 stream_putc (s, p->prefixlen);
404
405 /* Write packet size. */
406 stream_putw_at (s, 0, stream_get_endp (s));
407
408 return zebra_server_send_message(client);
409}
410
411/* Interface address addition. */
412static void
413zebra_interface_nbr_address_add_update (struct interface *ifp,
414 struct nbr_connected *ifc)
415{
416 struct listnode *node, *nnode;
417 struct zserv *client;
418 struct prefix *p;
419
420 if (IS_ZEBRA_DEBUG_EVENT)
421 {
422 char buf[INET6_ADDRSTRLEN];
423
424 p = ifc->address;
425 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_ADD %s/%d on %s",
426 inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN),
427 p->prefixlen, ifc->ifp->name);
428 }
429
430 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
4fe51714 431 zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD, client, ifp, ifc);
a80beece
DS
432}
433
434/* Interface address deletion. */
435static void
436zebra_interface_nbr_address_delete_update (struct interface *ifp,
437 struct nbr_connected *ifc)
438{
439 struct listnode *node, *nnode;
440 struct zserv *client;
441 struct prefix *p;
442
443 if (IS_ZEBRA_DEBUG_EVENT)
444 {
445 char buf[INET6_ADDRSTRLEN];
446
447 p = ifc->address;
448 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_NBR_ADDRESS_DELETE %s/%d on %s",
449 inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN),
450 p->prefixlen, ifc->ifp->name);
451 }
452
453 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
4fe51714 454 zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, client, ifp, ifc);
a80beece
DS
455}
456
c8e264b6 457/* Send addresses on interface to client */
458int
459zsend_interface_addresses (struct zserv *client, struct interface *ifp)
460{
461 struct listnode *cnode, *cnnode;
462 struct connected *c;
463 struct nbr_connected *nc;
464
465 /* Send interface addresses. */
466 for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
467 {
468 if (!CHECK_FLAG (c->conf, ZEBRA_IFC_REAL))
469 continue;
470
471 if (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client,
472 ifp, c) < 0)
473 return -1;
474 }
475
476 /* Send interface neighbors. */
477 for (ALL_LIST_ELEMENTS (ifp->nbr_connected, cnode, cnnode, nc))
478 {
479 if (zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
480 client, ifp, nc) < 0)
481 return -1;
482 }
483
484 return 0;
485}
486
487/* Notify client about interface moving from one VRF to another.
488 * Whether client is interested in old and new VRF is checked by caller.
489 */
490int
491zsend_interface_vrf_update (struct zserv *client, struct interface *ifp,
492 vrf_id_t vrf_id)
493{
494 struct stream *s;
495
496 s = client->obuf;
497 stream_reset (s);
498
499 zserv_create_header (s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
500
501 /* Fill in the ifIndex of the interface and its new VRF (id) */
502 stream_putl (s, ifp->ifindex);
503 stream_putw (s, vrf_id);
504
505 /* Write packet size. */
506 stream_putw_at (s, 0, stream_get_endp (s));
507
508 client->if_vrfchg_cnt++;
509 return zebra_server_send_message(client);
510}
511
1d20ccf3 512/* Add new nbr connected IPv6 address */
a80beece 513void
1d20ccf3 514nbr_connected_add_ipv6 (struct interface *ifp, struct in6_addr *address)
a80beece
DS
515{
516 struct nbr_connected *ifc;
517 struct prefix p;
518
519 p.family = AF_INET6;
520 IPV6_ADDR_COPY (&p.u.prefix, address);
1d20ccf3 521 p.prefixlen = IPV6_MAX_PREFIXLEN;
a80beece
DS
522
523 if (!(ifc = listnode_head(ifp->nbr_connected)))
524 {
525 /* new addition */
526 ifc = nbr_connected_new ();
527 ifc->address = prefix_new();
528 ifc->ifp = ifp;
529 listnode_add (ifp->nbr_connected, ifc);
530 }
531
532 prefix_copy(ifc->address, &p);
533
534 zebra_interface_nbr_address_add_update (ifp, ifc);
5c610faf
DS
535
536 if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 1);
a80beece
DS
537}
538
539void
1d20ccf3 540nbr_connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address)
a80beece
DS
541{
542 struct nbr_connected *ifc;
543 struct prefix p;
544
545 p.family = AF_INET6;
546 IPV6_ADDR_COPY (&p.u.prefix, address);
1d20ccf3 547 p.prefixlen = IPV6_MAX_PREFIXLEN;
a80beece
DS
548
549 ifc = nbr_connected_check(ifp, &p);
550 if (!ifc)
551 return;
552
553 listnode_delete (ifp->nbr_connected, ifc);
554
555 zebra_interface_nbr_address_delete_update (ifp, ifc);
556
5c610faf
DS
557 if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 0);
558
a80beece
DS
559 nbr_connected_free (ifc);
560}
561
b9df2d25 562/*
563 * The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or
564 * ZEBRA_INTERFACE_DOWN.
565 *
566 * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
567 * the clients in one of 2 situations:
568 * - an if_up is detected e.g., as a result of an RTM_IFINFO message
569 * - a vty command modifying the bandwidth of an interface is received.
570 * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
571 */
718e3744 572int
b9df2d25 573zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
718e3744 574{
575 struct stream *s;
576
718e3744 577 s = client->obuf;
578 stream_reset (s);
579
7076bb2f 580 zserv_create_header (s, cmd, ifp->vrf_id);
51d4ef83 581 zserv_encode_interface (s, ifp);
718e3744 582
04b02fda
DS
583 if (cmd == ZEBRA_INTERFACE_UP)
584 client->ifup_cnt++;
585 else
586 client->ifdown_cnt++;
587
719e9741 588 return zebra_server_send_message(client);
718e3744 589}
590
b9df2d25 591/*
5048fe14 592 * This is the new function to announce and withdraw redistributed routes, used
593 * by Zebra. This is the old zsend_route_multipath() function. That function
594 * was duplicating code to send a lot of information that was essentially thrown
595 * away or ignored by the receiver. This is the leaner function that is not a
596 * duplicate of the zapi_ipv4_route_add/del.
b9df2d25 597 *
5048fe14 598 * The primary difference is that this function merely sends a single NH instead of
599 * all the nexthops.
b9df2d25 600 */
718e3744 601int
9c6060d4 602zsend_redistribute_route (int add, struct zserv *client, struct prefix *p,
5048fe14 603 struct rib *rib)
718e3744 604{
9c6060d4
RW
605 afi_t afi;
606 int cmd;
718e3744 607 int psize;
608 struct stream *s;
609 struct nexthop *nexthop;
1dcb5172 610 unsigned long nhnummark = 0, messmark = 0;
b9df2d25 611 int nhnum = 0;
1dcb5172 612 u_char zapi_flags = 0;
5048fe14 613 struct nexthop dummy_nh;
614
9c6060d4
RW
615 afi = family2afi (p->family);
616 if (add)
617 {
618 switch (afi)
619 {
620 case AFI_IP:
621 cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD;
622 client->redist_v4_add_cnt++;
623 break;
624 case AFI_IP6:
625 cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD;
626 client->redist_v6_add_cnt++;
627 break;
628 default:
629 return -1;
630 }
631 }
632 else
633 {
634 switch (afi)
635 {
636 case AFI_IP:
637 cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL;
638 client->redist_v4_del_cnt++;
639 break;
640 case AFI_IP6:
641 cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL;
642 client->redist_v6_del_cnt++;
643 break;
644 default:
645 return -1;
646 }
647 }
7076bb2f 648
718e3744 649 s = client->obuf;
650 stream_reset (s);
5048fe14 651 memset(&dummy_nh, 0, sizeof(struct nexthop));
652
7076bb2f
FL
653 zserv_create_header (s, cmd, rib->vrf_id);
654
c1b9800a 655 /* Put type and nexthop. */
718e3744 656 stream_putc (s, rib->type);
7c8ff89e 657 stream_putw (s, rib->instance);
0fc452dc 658 stream_putl (s, rib->flags);
5048fe14 659
1dcb5172 660 /* marker for message flags field */
661 messmark = stream_get_endp (s);
662 stream_putc (s, 0);
718e3744 663
664 /* Prefix. */
665 psize = PSIZE (p->prefixlen);
666 stream_putc (s, p->prefixlen);
b9df2d25 667 stream_write (s, (u_char *) & p->u.prefix, psize);
668
718e3744 669 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
670 {
5048fe14 671 /* We don't send any nexthops when there's a multipath */
eac6e3f0 672 if (rib->nexthop_active_num > 1 && client->proto != ZEBRA_ROUTE_LDP)
5048fe14 673 {
674 SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
675 SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
676
677 stream_putc(s, 1);
678 if (p->family == AF_INET)
679 {
680 stream_put_in_addr (s, &dummy_nh.gate.ipv4);
681 }
682 else if (p->family == AF_INET6)
683 {
684 stream_write (s, (u_char *) &dummy_nh.gate.ipv6, 16);
685 }
686 else
687 {
688 /* We don't handle anything else now, abort */
689 zlog_err("%s: Unable to redistribute route of unknown family, %d\n",
690 __func__, p->family);
691 return -1;
692 }
693 stream_putc (s, 1);
694 stream_putl (s, 0); /* dummy ifindex */
695 break;
696 }
697
446bb95e 698 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
b9df2d25 699 {
1dcb5172 700 SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
701 SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
1dcb5172 702 if (nhnummark == 0)
703 {
704 nhnummark = stream_get_endp (s);
705 stream_putc (s, 1); /* placeholder */
706 }
b9df2d25 707 nhnum++;
708
709 switch(nexthop->type)
710 {
711 case NEXTHOP_TYPE_IPV4:
712 case NEXTHOP_TYPE_IPV4_IFINDEX:
713 stream_put_in_addr (s, &nexthop->gate.ipv4);
714 break;
b9df2d25 715 case NEXTHOP_TYPE_IPV6:
716 case NEXTHOP_TYPE_IPV6_IFINDEX:
5048fe14 717 /* Only BGP supports IPv4 prefix with IPv6 NH, so kill this */
718 if (p->family == AF_INET)
719 stream_put_in_addr(s, &dummy_nh.gate.ipv4);
720 else
721 stream_write (s, (u_char *) &nexthop->gate.ipv6, 16);
b9df2d25 722 break;
b9df2d25 723 default:
5048fe14 724 if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD
725 || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL)
b9df2d25 726 {
727 struct in_addr empty;
44983cf8 728 memset (&empty, 0, sizeof (struct in_addr));
b9df2d25 729 stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN);
730 }
731 else
732 {
733 struct in6_addr empty;
734 memset (&empty, 0, sizeof (struct in6_addr));
735 stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN);
736 }
737 }
738
739 /* Interface index. */
740 stream_putc (s, 1);
741 stream_putl (s, nexthop->ifindex);
742
eac6e3f0
RW
743 /* ldpd needs all nexthops */
744 if (client->proto != ZEBRA_ROUTE_LDP)
b9df2d25 745 break;
746 }
718e3744 747 }
748
7fe041ac 749 /* Distance */
fbf5d033 750 SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE);
751 stream_putc (s, rib->distance);
7fe041ac 752
718e3744 753 /* Metric */
1dcb5172 754 SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC);
755 stream_putl (s, rib->metric);
0d9551dc 756
7fe041ac 757 /* Tag */
0d9551dc
DS
758 if (rib->tag)
759 {
760 SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG);
dc9ffce8 761 stream_putl(s, rib->tag);
0d9551dc 762 }
5048fe14 763
7fe041ac 764 /* MTU */
c50ca33a
TT
765 SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU);
766 stream_putl (s, rib->mtu);
5048fe14 767
1dcb5172 768 /* write real message flags value */
769 stream_putc_at (s, messmark, zapi_flags);
5048fe14 770
b9df2d25 771 /* Write next-hop number */
772 if (nhnummark)
c1eaa442 773 stream_putc_at (s, nhnummark, nhnum);
5048fe14 774
718e3744 775 /* Write packet size. */
776 stream_putw_at (s, 0, stream_get_endp (s));
777
719e9741 778 return zebra_server_send_message(client);
718e3744 779}
780
10fbd59a
DS
781static int
782zsend_write_nexthop (struct stream *s, struct nexthop *nexthop)
783{
784 stream_putc (s, nexthop->type);
785 switch (nexthop->type)
786 {
787 case NEXTHOP_TYPE_IPV4:
788 stream_put_in_addr (s, &nexthop->gate.ipv4);
789 break;
790 case NEXTHOP_TYPE_IPV4_IFINDEX:
791 stream_put_in_addr (s, &nexthop->gate.ipv4);
792 stream_putl (s, nexthop->ifindex);
793 break;
794 case NEXTHOP_TYPE_IPV6:
795 stream_put (s, &nexthop->gate.ipv6, 16);
796 break;
797 case NEXTHOP_TYPE_IPV6_IFINDEX:
798 stream_put (s, &nexthop->gate.ipv6, 16);
799 stream_putl (s, nexthop->ifindex);
800 break;
801 case NEXTHOP_TYPE_IFINDEX:
802 stream_putl (s, nexthop->ifindex);
803 break;
804 default:
805 /* do nothing */
806 break;
807 }
808 return 1;
809}
810
fb018d25
DS
811/* Nexthop register */
812static int
078430f6 813zserv_rnh_register (struct zserv *client, int sock, u_short length,
d651649e 814 rnh_type_t type, struct zebra_vrf *zvrf)
fb018d25
DS
815{
816 struct rnh *rnh;
817 struct stream *s;
818 struct prefix p;
819 u_short l = 0;
078430f6 820 u_char flags = 0;
fb018d25
DS
821
822 if (IS_ZEBRA_DEBUG_NHT)
078430f6
DS
823 zlog_debug("rnh_register msg from client %s: length=%d, type=%s\n",
824 zebra_route_string(client->proto), length,
825 (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route");
fb018d25
DS
826
827 s = client->ibuf;
828
2176b7c3 829 client->nh_reg_time = quagga_monotime();
078430f6 830
fb018d25
DS
831 while (l < length)
832 {
078430f6 833 flags = stream_getc(s);
fb018d25
DS
834 p.family = stream_getw(s);
835 p.prefixlen = stream_getc(s);
fc9a856f 836 l += 4;
078430f6
DS
837 if (p.family == AF_INET)
838 {
839 p.u.prefix4.s_addr = stream_get_ipv4(s);
840 l += IPV4_MAX_BYTELEN;
841 }
842 else if (p.family == AF_INET6)
843 {
844 stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
845 l += IPV6_MAX_BYTELEN;
846 }
847 else
848 {
849 zlog_err("rnh_register: Received unknown family type %d\n",
850 p.family);
851 return -1;
852 }
661512bf 853 rnh = zebra_add_rnh(&p, zvrf_id (zvrf), type);
078430f6
DS
854 if (type == RNH_NEXTHOP_TYPE)
855 {
856 if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
857 SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
858 else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
859 UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
860 }
861 else if (type == RNH_IMPORT_CHECK_TYPE)
862 {
863 if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
864 SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
865 else if (!flags && CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
866 UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
867 }
868
661512bf 869 zebra_add_rnh_client(rnh, client, type, zvrf_id (zvrf));
078430f6 870 /* Anything not AF_INET/INET6 has been filtered out above */
661512bf 871 zebra_evaluate_rnh(zvrf_id (zvrf), p.family, 1, type, &p);
fb018d25 872 }
fb018d25
DS
873 return 0;
874}
875
876/* Nexthop register */
877static int
078430f6 878zserv_rnh_unregister (struct zserv *client, int sock, u_short length,
d651649e 879 rnh_type_t type, struct zebra_vrf *zvrf)
fb018d25
DS
880{
881 struct rnh *rnh;
882 struct stream *s;
883 struct prefix p;
884 u_short l = 0;
885
886 if (IS_ZEBRA_DEBUG_NHT)
078430f6 887 zlog_debug("rnh_unregister msg from client %s: length=%d\n",
fb018d25
DS
888 zebra_route_string(client->proto), length);
889
890 s = client->ibuf;
891
892 while (l < length)
893 {
4e3afb14 894 (void)stream_getc(s); //Connected or not. Not used in this function
fb018d25
DS
895 p.family = stream_getw(s);
896 p.prefixlen = stream_getc(s);
fc9a856f 897 l += 4;
078430f6
DS
898 if (p.family == AF_INET)
899 {
900 p.u.prefix4.s_addr = stream_get_ipv4(s);
901 l += IPV4_MAX_BYTELEN;
902 }
903 else if (p.family == AF_INET6)
904 {
905 stream_get(&p.u.prefix6, s, IPV6_MAX_BYTELEN);
906 l += IPV6_MAX_BYTELEN;
907 }
908 else
909 {
910 zlog_err("rnh_register: Received unknown family type %d\n",
911 p.family);
912 return -1;
913 }
661512bf 914 rnh = zebra_lookup_rnh(&p, zvrf_id (zvrf), type);
fb018d25 915 if (rnh)
04b02fda 916 {
2176b7c3 917 client->nh_dereg_time = quagga_monotime();
078430f6 918 zebra_remove_rnh_client(rnh, client, type);
04b02fda 919 }
fb018d25
DS
920 }
921 return 0;
922}
923
6f61a5a3
EM
924/*
925 Modified version of zsend_ipv4_nexthop_lookup():
926 Query unicast rib if nexthop is not found on mrib.
927 Returns both route metric and protocol distance.
928*/
929static int
4623d897 930zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, struct rib *rib, struct zebra_vrf *zvrf)
6f61a5a3
EM
931{
932 struct stream *s;
6f61a5a3
EM
933 unsigned long nump;
934 u_char num;
935 struct nexthop *nexthop;
936
6f61a5a3
EM
937 /* Get output stream. */
938 s = client->obuf;
939 stream_reset (s);
940
941 /* Fill in result. */
661512bf 942 zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id (zvrf));
6f61a5a3
EM
943 stream_put_in_addr (s, &addr);
944
945 if (rib)
946 {
947 stream_putc (s, rib->distance);
948 stream_putl (s, rib->metric);
949 num = 0;
950 nump = stream_get_endp(s); /* remember position for nexthop_num */
951 stream_putc (s, 0); /* reserve room for nexthop_num */
952 /* Only non-recursive routes are elegible to resolve the nexthop we
953 * are looking up. Therefore, we will just iterate over the top
954 * chain of nexthops. */
955 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
446bb95e 956 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
10fbd59a 957 num += zsend_write_nexthop (s, nexthop);
6f61a5a3
EM
958
959 stream_putc_at (s, nump, num); /* store nexthop_num */
960 }
961 else
962 {
963 stream_putc (s, 0); /* distance */
964 stream_putl (s, 0); /* metric */
965 stream_putc (s, 0); /* nexthop_num */
966 }
967
968 stream_putw_at (s, 0, stream_get_endp (s));
969
970 return zebra_server_send_message(client);
971}
972
18a6dce6 973/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
974int
c6ffe645
FL
975zsend_router_id_update (struct zserv *client, struct prefix *p,
976 vrf_id_t vrf_id)
18a6dce6 977{
978 struct stream *s;
979 int blen;
980
981 /* Check this client need interface information. */
7076bb2f 982 if (! vrf_bitmap_check (client->ridinfo, vrf_id))
719e9741 983 return 0;
18a6dce6 984
985 s = client->obuf;
986 stream_reset (s);
987
18a6dce6 988 /* Message type. */
7076bb2f 989 zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE, vrf_id);
18a6dce6 990
991 /* Prefix information. */
992 stream_putc (s, p->family);
993 blen = prefix_blen (p);
994 stream_put (s, &p->u.prefix, blen);
995 stream_putc (s, p->prefixlen);
996
997 /* Write packet size. */
998 stream_putw_at (s, 0, stream_get_endp (s));
999
719e9741 1000 return zebra_server_send_message(client);
18a6dce6 1001}
6b0655a2 1002
718e3744 1003/* Register zebra server interface information. Send current all
1004 interface and address information. */
719e9741 1005static int
d651649e 1006zread_interface_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
718e3744 1007{
1a1a7065 1008 struct vrf *vrf;
1eb8ef25 1009 struct listnode *ifnode, *ifnnode;
718e3744 1010 struct interface *ifp;
718e3744 1011
1012 /* Interface information is needed. */
661512bf 1013 vrf_bitmap_set (client->ifinfo, zvrf_id (zvrf));
718e3744 1014
1a1a7065 1015 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
718e3744 1016 {
1a1a7065 1017 for (ALL_LIST_ELEMENTS (vrf->iflist, ifnode, ifnnode, ifp))
4fe51714
DS
1018 {
1019 /* Skip pseudo interface. */
1020 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1021 continue;
718e3744 1022
4fe51714
DS
1023 if (zsend_interface_add (client, ifp) < 0)
1024 return -1;
718e3744 1025
4fe51714
DS
1026 if (zsend_interface_addresses (client, ifp) < 0)
1027 return -1;
1028 }
718e3744 1029 }
719e9741 1030 return 0;
718e3744 1031}
1032
1033/* Unregister zebra server interface information. */
719e9741 1034static int
d651649e 1035zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
718e3744 1036{
661512bf 1037 vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf));
719e9741 1038 return 0;
718e3744 1039}
1040
6878b9db 1041void
4f87aceb 1042zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const unsigned int nexthop_num)
6878b9db 1043{
7c5d2b76 1044 if (nexthop_num > MULTIPATH_NUM)
6878b9db 1045 {
4690c7d7
DS
1046 char buff[PREFIX2STR_BUFFER];
1047 prefix2str(p, buff, sizeof (buff));
6878b9db
DS
1048 zlog_warn("%s: Prefix %s has %d nexthops, but we can only use the first %d",
1049 caller, buff, nexthop_num, MULTIPATH_NUM);
1050 }
1051}
1052
718e3744 1053/* This function support multiple nexthop. */
b9df2d25 1054/*
1055 * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
1056 * add kernel route.
1057 */
719e9741 1058static int
d651649e 1059zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
718e3744 1060{
1061 int i;
1062 struct rib *rib;
b4c034b0 1063 struct prefix p;
718e3744 1064 u_char message;
1065 struct in_addr nexthop;
1066 u_char nexthop_num;
1067 u_char nexthop_type;
1068 struct stream *s;
b892f1dd 1069 ifindex_t ifindex;
d44ca835 1070 safi_t safi;
04b02fda 1071 int ret;
718e3744 1072
1073 /* Get input stream. */
1074 s = client->ibuf;
1075
1076 /* Allocate new rib. */
4d38fdb4 1077 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1078
718e3744 1079 /* Type, flags, message. */
1080 rib->type = stream_getc (s);
7c8ff89e 1081 rib->instance = stream_getw (s);
0fc452dc 1082 rib->flags = stream_getl (s);
b9df2d25 1083 message = stream_getc (s);
cddf391b 1084 safi = stream_getw (s);
718e3744 1085 rib->uptime = time (NULL);
1086
1087 /* IPv4 prefix. */
1088 memset (&p, 0, sizeof (struct prefix_ipv4));
1089 p.family = AF_INET;
1090 p.prefixlen = stream_getc (s);
b4c034b0 1091 stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen));
718e3744 1092
78104b9b 1093 /* VRF ID */
661512bf 1094 rib->vrf_id = zvrf_id (zvrf);
78104b9b 1095
718e3744 1096 /* Nexthop parse. */
1097 if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
1098 {
1099 nexthop_num = stream_getc (s);
6878b9db 1100 zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num);
718e3744 1101
1102 for (i = 0; i < nexthop_num; i++)
1103 {
1104 nexthop_type = stream_getc (s);
1105
1106 switch (nexthop_type)
1107 {
5b30316e 1108 case NEXTHOP_TYPE_IFINDEX:
718e3744 1109 ifindex = stream_getl (s);
a399694f 1110 rib_nexthop_ifindex_add (rib, ifindex);
718e3744 1111 break;
5b30316e 1112 case NEXTHOP_TYPE_IPV4:
718e3744 1113 nexthop.s_addr = stream_get_ipv4 (s);
a399694f 1114 rib_nexthop_ipv4_add (rib, &nexthop, NULL);
718e3744 1115 break;
5b30316e 1116 case NEXTHOP_TYPE_IPV4_IFINDEX:
c963c203
JT
1117 nexthop.s_addr = stream_get_ipv4 (s);
1118 ifindex = stream_getl (s);
a399694f 1119 rib_nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
c963c203 1120 break;
5b30316e 1121 case NEXTHOP_TYPE_IPV6:
9985f83c 1122 stream_forward_getp (s, IPV6_MAX_BYTELEN);
718e3744 1123 break;
5b30316e 1124 case NEXTHOP_TYPE_BLACKHOLE:
a399694f 1125 rib_nexthop_blackhole_add (rib);
6902c69a
SV
1126 break;
1127 }
718e3744 1128 }
1129 }
1130
1131 /* Distance. */
1132 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
1133 rib->distance = stream_getc (s);
1134
1135 /* Metric. */
1136 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
1137 rib->metric = stream_getl (s);
1138
0d9551dc
DS
1139 /* Tag */
1140 if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG))
dc9ffce8 1141 rib->tag = stream_getl (s);
0d9551dc
DS
1142 else
1143 rib->tag = 0;
1144
c50ca33a
TT
1145 if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
1146 rib->mtu = stream_getl (s);
1147 else
1148 rib->mtu = 0;
1149
171eee31 1150 /* Table */
d651649e 1151 rib->table = zvrf->table_id;
12f6fb97 1152
b4c034b0 1153 ret = rib_add_multipath (AFI_IP, safi, &p, rib);
04b02fda
DS
1154
1155 /* Stats */
1156 if (ret > 0)
1157 client->v4_route_add_cnt++;
1158 else if (ret < 0)
1159 client->v4_route_upd8_cnt++;
719e9741 1160 return 0;
718e3744 1161}
1162
1163/* Zebra server IPv4 prefix delete function. */
719e9741 1164static int
d651649e 1165zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
718e3744 1166{
1167 int i;
1168 struct stream *s;
1169 struct zapi_ipv4 api;
616368ed
DS
1170 struct in_addr nexthop;
1171 union g_addr *nexthop_p;
718e3744 1172 unsigned long ifindex;
616368ed 1173 struct prefix p;
718e3744 1174 u_char nexthop_num;
1175 u_char nexthop_type;
12f6fb97 1176 u_int32_t table_id;
12f6fb97 1177
718e3744 1178 s = client->ibuf;
1179 ifindex = 0;
1180 nexthop.s_addr = 0;
6902c69a 1181 nexthop_p = NULL;
718e3744 1182
1183 /* Type, flags, message. */
1184 api.type = stream_getc (s);
7c8ff89e 1185 api.instance = stream_getw (s);
0fc452dc 1186 api.flags = stream_getl (s);
718e3744 1187 api.message = stream_getc (s);
cddf391b 1188 api.safi = stream_getw (s);
718e3744 1189
1190 /* IPv4 prefix. */
1191 memset (&p, 0, sizeof (struct prefix_ipv4));
1192 p.family = AF_INET;
1193 p.prefixlen = stream_getc (s);
616368ed 1194 stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen));
718e3744 1195
1196 /* Nexthop, ifindex, distance, metric. */
1197 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
1198 {
1199 nexthop_num = stream_getc (s);
1200
1201 for (i = 0; i < nexthop_num; i++)
1202 {
1203 nexthop_type = stream_getc (s);
1204
1205 switch (nexthop_type)
1206 {
5b30316e 1207 case NEXTHOP_TYPE_IFINDEX:
718e3744 1208 ifindex = stream_getl (s);
1209 break;
5b30316e 1210 case NEXTHOP_TYPE_IPV4:
718e3744 1211 nexthop.s_addr = stream_get_ipv4 (s);
616368ed 1212 nexthop_p = (union g_addr *)&nexthop;
718e3744 1213 break;
5b30316e 1214 case NEXTHOP_TYPE_IPV4_IFINDEX:
c963c203 1215 nexthop.s_addr = stream_get_ipv4 (s);
616368ed 1216 nexthop_p = (union g_addr *)&nexthop;
c963c203
JT
1217 ifindex = stream_getl (s);
1218 break;
5b30316e 1219 case NEXTHOP_TYPE_IPV6:
9985f83c 1220 stream_forward_getp (s, IPV6_MAX_BYTELEN);
718e3744 1221 break;
1222 }
1223 }
1224 }
1225
1226 /* Distance. */
1227 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
1228 api.distance = stream_getc (s);
1229 else
1230 api.distance = 0;
1231
1232 /* Metric. */
1233 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
1234 api.metric = stream_getl (s);
1235 else
1236 api.metric = 0;
1237
0d9551dc
DS
1238 /* tag */
1239 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
dc9ffce8 1240 api.tag = stream_getl (s);
0d9551dc
DS
1241 else
1242 api.tag = 0;
1243
d651649e 1244 table_id = zvrf->table_id;
12f6fb97 1245
661512bf 1246 rib_delete (AFI_IP, api.safi, zvrf_id (zvrf), api.type, api.instance,
616368ed 1247 api.flags, &p, nexthop_p, ifindex, table_id);
04b02fda 1248 client->v4_route_del_cnt++;
719e9741 1249 return 0;
718e3744 1250}
1251
6f61a5a3
EM
1252/* MRIB Nexthop lookup for IPv4. */
1253static int
1254zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
1255{
1256 struct in_addr addr;
4623d897 1257 struct rib *rib;
6f61a5a3
EM
1258
1259 addr.s_addr = stream_get_ipv4 (client->ibuf);
661512bf 1260 rib = rib_match_ipv4_multicast (zvrf_id (zvrf), addr, NULL);
4623d897 1261 return zsend_ipv4_nexthop_lookup_mrib (client, addr, rib, zvrf);
6f61a5a3
EM
1262}
1263
8a92a8a0
DS
1264/* Zebra server IPv6 prefix add function. */
1265static int
d651649e 1266zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
8a92a8a0
DS
1267{
1268 int i;
1269 struct stream *s;
1270 struct in6_addr nexthop;
1271 struct rib *rib;
1272 u_char message;
1273 u_char nexthop_num;
1274 u_char nexthop_type;
b4c034b0 1275 struct prefix p;
8a92a8a0
DS
1276 safi_t safi;
1277 static struct in6_addr nexthops[MULTIPATH_NUM];
1278 static unsigned int ifindices[MULTIPATH_NUM];
1279 int ret;
1280
1281 /* Get input stream. */
1282 s = client->ibuf;
1283
8a92a8a0
DS
1284 memset (&nexthop, 0, sizeof (struct in6_addr));
1285
1286 /* Allocate new rib. */
1287 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1288
1289 /* Type, flags, message. */
1290 rib->type = stream_getc (s);
1291 rib->instance = stream_getw (s);
0fc452dc 1292 rib->flags = stream_getl (s);
8a92a8a0
DS
1293 message = stream_getc (s);
1294 safi = stream_getw (s);
1295 rib->uptime = time (NULL);
1296
1297 /* IPv4 prefix. */
1298 memset (&p, 0, sizeof (struct prefix_ipv4));
1299 p.family = AF_INET;
1300 p.prefixlen = stream_getc (s);
b4c034b0 1301 stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen));
8a92a8a0 1302
154caaed 1303 /* VRF ID */
661512bf 1304 rib->vrf_id = zvrf_id (zvrf);
154caaed 1305
8a92a8a0
DS
1306 /* We need to give nh-addr, nh-ifindex with the same next-hop object
1307 * to the rib to ensure that IPv6 multipathing works; need to coalesce
1308 * these. Clients should send the same number of paired set of
1309 * next-hop-addr/next-hop-ifindices. */
1310 if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
1311 {
1312 int nh_count = 0;
1313 int if_count = 0;
1314 int max_nh_if = 0;
1315
1316 nexthop_num = stream_getc (s);
6878b9db 1317 zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num);
8a92a8a0
DS
1318 for (i = 0; i < nexthop_num; i++)
1319 {
1320 nexthop_type = stream_getc (s);
1321
1322 switch (nexthop_type)
1323 {
5b30316e 1324 case NEXTHOP_TYPE_IPV6:
8a92a8a0
DS
1325 stream_get (&nexthop, s, 16);
1326 if (nh_count < MULTIPATH_NUM) {
1327 nexthops[nh_count++] = nexthop;
1328 }
1329 break;
5b30316e 1330 case NEXTHOP_TYPE_IFINDEX:
8a92a8a0
DS
1331 if (if_count < MULTIPATH_NUM) {
1332 ifindices[if_count++] = stream_getl (s);
1333 }
1334 break;
5b30316e 1335 case NEXTHOP_TYPE_BLACKHOLE:
a399694f 1336 rib_nexthop_blackhole_add (rib);
8a92a8a0
DS
1337 break;
1338 }
1339 }
1340
1341 max_nh_if = (nh_count > if_count) ? nh_count : if_count;
1342 for (i = 0; i < max_nh_if; i++)
1343 {
1344 if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) {
1345 if ((i < if_count) && ifindices[i]) {
a399694f 1346 rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
8a92a8a0
DS
1347 }
1348 else {
a399694f 1349 rib_nexthop_ipv6_add (rib, &nexthops[i]);
8a92a8a0
DS
1350 }
1351 }
1352 else {
1353 if ((i < if_count) && ifindices[i]) {
a399694f 1354 rib_nexthop_ifindex_add (rib, ifindices[i]);
8a92a8a0
DS
1355 }
1356 }
1357 }
1358 }
1359
1360 /* Distance. */
1361 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
1362 rib->distance = stream_getc (s);
1363
1364 /* Metric. */
1365 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
1366 rib->metric = stream_getl (s);
1367
1368 /* Tag */
1369 if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG))
dc9ffce8 1370 rib->tag = stream_getl (s);
8a92a8a0
DS
1371 else
1372 rib->tag = 0;
1373
c50ca33a
TT
1374 if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
1375 rib->mtu = stream_getl (s);
1376 else
1377 rib->mtu = 0;
1378
8a92a8a0 1379 /* Table */
d651649e 1380 rib->table = zvrf->table_id;
12f6fb97 1381
b4c034b0 1382 ret = rib_add_multipath (AFI_IP6, safi, &p, rib);
8a92a8a0
DS
1383 /* Stats */
1384 if (ret > 0)
1385 client->v4_route_add_cnt++;
1386 else if (ret < 0)
1387 client->v4_route_upd8_cnt++;
1388
1389 return 0;
1390}
1391
719e9741 1392static int
d651649e 1393zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
718e3744 1394{
1395 int i;
1396 struct stream *s;
718e3744 1397 struct in6_addr nexthop;
41fc2714
DS
1398 struct rib *rib;
1399 u_char message;
1400 u_char nexthop_num;
1401 u_char nexthop_type;
b4c034b0 1402 struct prefix p;
41fc2714
DS
1403 safi_t safi;
1404 static struct in6_addr nexthops[MULTIPATH_NUM];
1405 static unsigned int ifindices[MULTIPATH_NUM];
04b02fda 1406 int ret;
41fc2714
DS
1407
1408 /* Get input stream. */
718e3744 1409 s = client->ibuf;
41fc2714 1410
718e3744 1411 memset (&nexthop, 0, sizeof (struct in6_addr));
1412
41fc2714
DS
1413 /* Allocate new rib. */
1414 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1415
718e3744 1416 /* Type, flags, message. */
41fc2714 1417 rib->type = stream_getc (s);
7c8ff89e 1418 rib->instance = stream_getw (s);
0fc452dc 1419 rib->flags = stream_getl (s);
41fc2714
DS
1420 message = stream_getc (s);
1421 safi = stream_getw (s);
1422 rib->uptime = time (NULL);
718e3744 1423
41fc2714 1424 /* IPv6 prefix. */
718e3744 1425 memset (&p, 0, sizeof (struct prefix_ipv6));
1426 p.family = AF_INET6;
1427 p.prefixlen = stream_getc (s);
b4c034b0 1428 stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen));
718e3744 1429
41fc2714
DS
1430 /* We need to give nh-addr, nh-ifindex with the same next-hop object
1431 * to the rib to ensure that IPv6 multipathing works; need to coalesce
1432 * these. Clients should send the same number of paired set of
1433 * next-hop-addr/next-hop-ifindices. */
1434 if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
718e3744 1435 {
41fc2714
DS
1436 int nh_count = 0;
1437 int if_count = 0;
1438 int max_nh_if = 0;
718e3744 1439
41fc2714 1440 nexthop_num = stream_getc (s);
6878b9db
DS
1441 zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num);
1442 for (i = 0; i < nexthop_num; i++)
718e3744 1443 {
1444 nexthop_type = stream_getc (s);
1445
1446 switch (nexthop_type)
1447 {
5b30316e 1448 case NEXTHOP_TYPE_IPV6:
718e3744 1449 stream_get (&nexthop, s, 16);
41fc2714
DS
1450 if (nh_count < MULTIPATH_NUM) {
1451 nexthops[nh_count++] = nexthop;
1452 }
718e3744 1453 break;
5b30316e 1454 case NEXTHOP_TYPE_IFINDEX:
41fc2714
DS
1455 if (if_count < MULTIPATH_NUM) {
1456 ifindices[if_count++] = stream_getl (s);
1457 }
718e3744 1458 break;
5b30316e 1459 case NEXTHOP_TYPE_BLACKHOLE:
a399694f 1460 rib_nexthop_blackhole_add (rib);
c3c0ac83 1461 break;
718e3744 1462 }
1463 }
41fc2714
DS
1464
1465 max_nh_if = (nh_count > if_count) ? nh_count : if_count;
1466 for (i = 0; i < max_nh_if; i++)
1467 {
1468 if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) {
6f20b80d 1469 if ((i < if_count) && ifindices[i])
a399694f 1470 rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
6f20b80d 1471 else
a399694f 1472 rib_nexthop_ipv6_add (rib, &nexthops[i]);
41fc2714
DS
1473 }
1474 else {
6f20b80d 1475 if ((i < if_count) && ifindices[i])
a399694f 1476 rib_nexthop_ifindex_add (rib, ifindices[i]);
41fc2714
DS
1477 }
1478 }
718e3744 1479 }
1480
41fc2714
DS
1481 /* Distance. */
1482 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
1483 rib->distance = stream_getc (s);
718e3744 1484
41fc2714
DS
1485 /* Metric. */
1486 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
1487 rib->metric = stream_getl (s);
718e3744 1488
0d9551dc
DS
1489 /* Tag */
1490 if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG))
dc9ffce8 1491 rib->tag = stream_getl (s);
0d9551dc
DS
1492 else
1493 rib->tag = 0;
c50ca33a
TT
1494
1495 if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
1496 rib->mtu = stream_getl (s);
1497 else
1498 rib->mtu = 0;
0d9551dc 1499
154caaed 1500 /* VRF ID */
661512bf 1501 rib->vrf_id = zvrf_id (zvrf);
d651649e 1502 rib->table = zvrf->table_id;
154caaed 1503
bb374626 1504 ret = rib_add_multipath (AFI_IP6, safi, &p, rib);
04b02fda
DS
1505 /* Stats */
1506 if (ret > 0)
1507 client->v6_route_add_cnt++;
1508 else if (ret < 0)
1509 client->v6_route_upd8_cnt++;
1510
719e9741 1511 return 0;
718e3744 1512}
1513
1514/* Zebra server IPv6 prefix delete function. */
719e9741 1515static int
d651649e 1516zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
718e3744 1517{
1518 int i;
1519 struct stream *s;
1520 struct zapi_ipv6 api;
1521 struct in6_addr nexthop;
616368ed 1522 union g_addr *pnexthop;
718e3744 1523 unsigned long ifindex;
616368ed 1524 struct prefix p;
718e3744 1525
1526 s = client->ibuf;
1527 ifindex = 0;
1528 memset (&nexthop, 0, sizeof (struct in6_addr));
1529
1530 /* Type, flags, message. */
1531 api.type = stream_getc (s);
7c8ff89e 1532 api.instance = stream_getw (s);
0fc452dc 1533 api.flags = stream_getl (s);
718e3744 1534 api.message = stream_getc (s);
f768f367 1535 api.safi = stream_getw (s);
718e3744 1536
1537 /* IPv4 prefix. */
1538 memset (&p, 0, sizeof (struct prefix_ipv6));
1539 p.family = AF_INET6;
1540 p.prefixlen = stream_getc (s);
616368ed 1541 stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen));
718e3744 1542
1543 /* Nexthop, ifindex, distance, metric. */
1544 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
1545 {
1546 u_char nexthop_type;
1547
1548 api.nexthop_num = stream_getc (s);
1549 for (i = 0; i < api.nexthop_num; i++)
1550 {
1551 nexthop_type = stream_getc (s);
1552
1553 switch (nexthop_type)
1554 {
5b30316e 1555 case NEXTHOP_TYPE_IPV6:
718e3744 1556 stream_get (&nexthop, s, 16);
616368ed 1557 pnexthop = (union g_addr *)&nexthop;
718e3744 1558 break;
5b30316e 1559 case NEXTHOP_TYPE_IFINDEX:
718e3744 1560 ifindex = stream_getl (s);
1561 break;
1562 }
1563 }
1564 }
1565
0d9551dc 1566 /* Distance. */
718e3744 1567 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
1568 api.distance = stream_getc (s);
1569 else
1570 api.distance = 0;
0d9551dc
DS
1571
1572 /* Metric. */
718e3744 1573 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
1574 api.metric = stream_getl (s);
1575 else
1576 api.metric = 0;
1577
0d9551dc
DS
1578 /* tag */
1579 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
dc9ffce8 1580 api.tag = stream_getl (s);
0d9551dc
DS
1581 else
1582 api.tag = 0;
1583
718e3744 1584 if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
661512bf 1585 rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance,
616368ed 1586 api.flags, &p, NULL, ifindex, client->rtm_table);
718e3744 1587 else
661512bf 1588 rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance,
616368ed 1589 api.flags, &p, pnexthop, ifindex, client->rtm_table);
04b02fda
DS
1590
1591 client->v6_route_del_cnt++;
719e9741 1592 return 0;
718e3744 1593}
1594
18a6dce6 1595/* Register zebra server router-id information. Send current router-id */
719e9741 1596static int
d651649e 1597zread_router_id_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
18a6dce6 1598{
1599 struct prefix p;
1600
1601 /* Router-id information is needed. */
661512bf 1602 vrf_bitmap_set (client->ridinfo, zvrf_id (zvrf));
18a6dce6 1603
661512bf 1604 router_id_get (&p, zvrf_id (zvrf));
18a6dce6 1605
661512bf 1606 return zsend_router_id_update (client, &p, zvrf_id (zvrf));
18a6dce6 1607}
1608
1609/* Unregister zebra server router-id information. */
719e9741 1610static int
d651649e 1611zread_router_id_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
18a6dce6 1612{
661512bf 1613 vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf));
719e9741 1614 return 0;
18a6dce6 1615}
1616
2ea1ab1c
VT
1617/* Tie up route-type and client->sock */
1618static void
1619zread_hello (struct zserv *client)
1620{
1621 /* type of protocol (lib/zebra.h) */
1622 u_char proto;
7c8ff89e
DS
1623 u_short instance;
1624
2ea1ab1c 1625 proto = stream_getc (client->ibuf);
7c8ff89e 1626 instance = stream_getw (client->ibuf);
2ea1ab1c
VT
1627
1628 /* accept only dynamic routing protocols */
1629 if ((proto < ZEBRA_ROUTE_MAX)
1630 && (proto > ZEBRA_ROUTE_STATIC))
1631 {
1632 zlog_notice ("client %d says hello and bids fair to announce only %s routes",
1633 client->sock, zebra_route_string(proto));
7c8ff89e
DS
1634 if (instance)
1635 zlog_notice ("client protocol instance %d", instance);
2ea1ab1c 1636
fb018d25 1637 client->proto = proto;
7c8ff89e 1638 client->instance = instance;
2ea1ab1c
VT
1639 }
1640}
1641
7076bb2f
FL
1642/* Unregister all information in a VRF. */
1643static int
d651649e 1644zread_vrf_unregister (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
7076bb2f
FL
1645{
1646 int i;
1647 afi_t afi;
1648
1649 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1650 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
661512bf
RW
1651 vrf_bitmap_unset (client->redist[afi][i], zvrf_id (zvrf));
1652 vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf));
1653 vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf));
1654 vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf));
7076bb2f
FL
1655
1656 return 0;
1657}
1658
ce549947
RW
1659static void
1660zread_mpls_labels (int command, struct zserv *client, u_short length,
1661 vrf_id_t vrf_id)
1662{
1663 struct stream *s;
1664 enum lsp_types_t type;
1665 struct prefix prefix;
1666 enum nexthop_types_t gtype;
1667 union g_addr gate;
88d88a9c 1668 ifindex_t ifindex;
ce549947
RW
1669 mpls_label_t in_label, out_label;
1670 u_int8_t distance;
1671 struct zebra_vrf *zvrf;
1672
1673 zvrf = vrf_info_lookup (vrf_id);
1674 if (!zvrf)
1675 return;
1676
1677 /* Get input stream. */
1678 s = client->ibuf;
1679
1680 /* Get data. */
1681 type = stream_getc (s);
1682 prefix.family = stream_getl (s);
1683 switch (prefix.family)
1684 {
1685 case AF_INET:
1686 prefix.u.prefix4.s_addr = stream_get_ipv4 (s);
1687 prefix.prefixlen = stream_getc (s);
ce549947
RW
1688 gate.ipv4.s_addr = stream_get_ipv4 (s);
1689 break;
1690 case AF_INET6:
1691 stream_get (&prefix.u.prefix6, s, 16);
1692 prefix.prefixlen = stream_getc (s);
ce549947
RW
1693 stream_get (&gate.ipv6, s, 16);
1694 break;
1695 default:
1696 return;
1697 }
88d88a9c 1698 ifindex = stream_getl (s);
ce549947
RW
1699 distance = stream_getc (s);
1700 in_label = stream_getl (s);
1701 out_label = stream_getl (s);
1702
88d88a9c
RW
1703 switch (prefix.family)
1704 {
1705 case AF_INET:
1706 if (ifindex)
1707 gtype = NEXTHOP_TYPE_IPV4_IFINDEX;
1708 else
1709 gtype = NEXTHOP_TYPE_IPV4;
1710 break;
1711 case AF_INET6:
1712 if (ifindex)
1713 gtype = NEXTHOP_TYPE_IPV6_IFINDEX;
1714 else
1715 gtype = NEXTHOP_TYPE_IPV6;
1716 break;
1717 default:
1718 return;
1719 }
1720
fe6c7157
RW
1721 if (! mpls_enabled)
1722 return;
1723
ce549947
RW
1724 if (command == ZEBRA_MPLS_LABELS_ADD)
1725 {
1726 mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate,
88d88a9c 1727 NULL, ifindex);
ce549947 1728 if (out_label != MPLS_IMP_NULL_LABEL)
88d88a9c
RW
1729 mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex,
1730 distance, out_label);
ce549947
RW
1731 }
1732 else if (command == ZEBRA_MPLS_LABELS_DELETE)
1733 {
88d88a9c 1734 mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, NULL, ifindex);
ce549947 1735 if (out_label != MPLS_IMP_NULL_LABEL)
88d88a9c
RW
1736 mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex,
1737 distance, out_label);
ce549947
RW
1738 }
1739}
1740
4b33b75a 1741/* Cleanup registered nexthops (across VRFs) upon client disconnect. */
1742static void
1743zebra_client_close_cleanup_rnh (struct zserv *client)
1744{
1a1a7065 1745 struct vrf *vrf;
4b33b75a 1746 struct zebra_vrf *zvrf;
1747
1a1a7065 1748 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
4b33b75a 1749 {
1a1a7065 1750 if ((zvrf = vrf->info) != NULL)
4b33b75a 1751 {
661512bf
RW
1752 zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_NEXTHOP_TYPE);
1753 zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_NEXTHOP_TYPE);
1754 zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_IMPORT_CHECK_TYPE);
1755 zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_IMPORT_CHECK_TYPE);
ce549947
RW
1756 if (client->proto == ZEBRA_ROUTE_LDP)
1757 {
1758 hash_iterate(zvrf->lsp_table, mpls_ldp_lsp_uninstall_all,
1759 zvrf->lsp_table);
1760 mpls_ldp_ftn_uninstall_all (zvrf, AFI_IP);
1761 mpls_ldp_ftn_uninstall_all (zvrf, AFI_IP6);
1762 }
4b33b75a 1763 }
1764 }
1765}
1766
718e3744 1767/* Close zebra client. */
b9df2d25 1768static void
718e3744 1769zebra_client_close (struct zserv *client)
1770{
567b877d 1771 /* Send client de-registration to BFD */
2376c3f2 1772 zebra_ptm_bfd_client_deregister(client->proto);
567b877d 1773
4b33b75a 1774 /* Cleanup any registered nexthops - across all VRFs. */
1775 zebra_client_close_cleanup_rnh (client);
fb018d25 1776
718e3744 1777 /* Close file descriptor. */
1778 if (client->sock)
1779 {
7c8ff89e
DS
1780 unsigned long nroutes;
1781
718e3744 1782 close (client->sock);
7c8ff89e
DS
1783 nroutes = rib_score_proto (client->proto, client->instance);
1784 zlog_notice ("client %d disconnected. %lu %s routes removed from the rib",
1785 client->sock, nroutes, zebra_route_string (client->proto));
718e3744 1786 client->sock = -1;
1787 }
1788
1789 /* Free stream buffers. */
1790 if (client->ibuf)
1791 stream_free (client->ibuf);
1792 if (client->obuf)
1793 stream_free (client->obuf);
719e9741 1794 if (client->wb)
1795 buffer_free(client->wb);
718e3744 1796
1797 /* Release threads. */
1798 if (client->t_read)
1799 thread_cancel (client->t_read);
1800 if (client->t_write)
1801 thread_cancel (client->t_write);
719e9741 1802 if (client->t_suicide)
1803 thread_cancel (client->t_suicide);
718e3744 1804
1805 /* Free client structure. */
b21b19c5 1806 listnode_delete (zebrad.client_list, client);
c66f9c61 1807 XFREE (MTYPE_TMP, client);
718e3744 1808}
1809
1810/* Make new client. */
b9df2d25 1811static void
718e3744 1812zebra_client_create (int sock)
1813{
1814 struct zserv *client;
7076bb2f
FL
1815 int i;
1816 afi_t afi;
718e3744 1817
c66f9c61 1818 client = XCALLOC (MTYPE_TMP, sizeof (struct zserv));
718e3744 1819
1820 /* Make client input/output buffer. */
1821 client->sock = sock;
1822 client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
1823 client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
719e9741 1824 client->wb = buffer_new(0);
718e3744 1825
1826 /* Set table number. */
b21b19c5 1827 client->rtm_table = zebrad.rtm_table_default;
718e3744 1828
2176b7c3 1829 client->connect_time = quagga_monotime();
7076bb2f
FL
1830 /* Initialize flags */
1831 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1832 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1833 client->redist[afi][i] = vrf_bitmap_init ();
1834 client->redist_default = vrf_bitmap_init ();
1835 client->ifinfo = vrf_bitmap_init ();
1836 client->ridinfo = vrf_bitmap_init ();
04b02fda 1837
718e3744 1838 /* Add this client to linked list. */
b21b19c5 1839 listnode_add (zebrad.client_list, client);
718e3744 1840
1841 /* Make new read thread. */
1842 zebra_event (ZEBRA_READ, sock, client);
12f6fb97
DS
1843
1844 zebra_vrf_update_all (client);
718e3744 1845}
1846
1847/* Handler of zebra service request. */
b9df2d25 1848static int
718e3744 1849zebra_client_read (struct thread *thread)
1850{
1851 int sock;
1852 struct zserv *client;
57a1477b 1853 size_t already;
c1b9800a 1854 uint16_t length, command;
1855 uint8_t marker, version;
7076bb2f 1856 vrf_id_t vrf_id;
d651649e 1857 struct zebra_vrf *zvrf;
718e3744 1858
1859 /* Get thread data. Reset reading thread because I'm running. */
1860 sock = THREAD_FD (thread);
1861 client = THREAD_ARG (thread);
1862 client->t_read = NULL;
1863
719e9741 1864 if (client->t_suicide)
718e3744 1865 {
719e9741 1866 zebra_client_close(client);
718e3744 1867 return -1;
1868 }
719e9741 1869
1870 /* Read length and command (if we don't have it already). */
57a1477b 1871 if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE)
719e9741 1872 {
57a1477b 1873 ssize_t nbyte;
719e9741 1874 if (((nbyte = stream_read_try (client->ibuf, sock,
57a1477b 1875 ZEBRA_HEADER_SIZE-already)) == 0) ||
719e9741 1876 (nbyte == -1))
1877 {
1878 if (IS_ZEBRA_DEBUG_EVENT)
1879 zlog_debug ("connection closed socket [%d]", sock);
1880 zebra_client_close (client);
1881 return -1;
1882 }
57a1477b 1883 if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
719e9741 1884 {
1885 /* Try again later. */
1886 zebra_event (ZEBRA_READ, sock, client);
1887 return 0;
1888 }
57a1477b 1889 already = ZEBRA_HEADER_SIZE;
719e9741 1890 }
1891
1892 /* Reset to read from the beginning of the incoming packet. */
1893 stream_set_getp(client->ibuf, 0);
1894
c1b9800a 1895 /* Fetch header values */
718e3744 1896 length = stream_getw (client->ibuf);
c1b9800a 1897 marker = stream_getc (client->ibuf);
1898 version = stream_getc (client->ibuf);
7076bb2f 1899 vrf_id = stream_getw (client->ibuf);
c1b9800a 1900 command = stream_getw (client->ibuf);
718e3744 1901
c1b9800a 1902 if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
1903 {
1904 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
1905 __func__, sock, marker, version);
1906 zebra_client_close (client);
1907 return -1;
1908 }
719e9741 1909 if (length < ZEBRA_HEADER_SIZE)
718e3744 1910 {
57a1477b 1911 zlog_warn("%s: socket %d message length %u is less than header size %d",
1912 __func__, sock, length, ZEBRA_HEADER_SIZE);
1913 zebra_client_close (client);
1914 return -1;
1915 }
1916 if (length > STREAM_SIZE(client->ibuf))
1917 {
1918 zlog_warn("%s: socket %d message length %u exceeds buffer size %lu",
1919 __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf));
718e3744 1920 zebra_client_close (client);
1921 return -1;
1922 }
1923
718e3744 1924 /* Read rest of data. */
57a1477b 1925 if (already < length)
718e3744 1926 {
57a1477b 1927 ssize_t nbyte;
1928 if (((nbyte = stream_read_try (client->ibuf, sock,
1929 length-already)) == 0) ||
1930 (nbyte == -1))
718e3744 1931 {
1932 if (IS_ZEBRA_DEBUG_EVENT)
b6178002 1933 zlog_debug ("connection closed [%d] when reading zebra data", sock);
718e3744 1934 zebra_client_close (client);
1935 return -1;
1936 }
57a1477b 1937 if (nbyte != (ssize_t)(length-already))
719e9741 1938 {
1939 /* Try again later. */
1940 zebra_event (ZEBRA_READ, sock, client);
1941 return 0;
1942 }
718e3744 1943 }
1944
719e9741 1945 length -= ZEBRA_HEADER_SIZE;
1946
718e3744 1947 /* Debug packet information. */
1948 if (IS_ZEBRA_DEBUG_EVENT)
b6178002 1949 zlog_debug ("zebra message comes from socket [%d]", sock);
718e3744 1950
1951 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
7076bb2f
FL
1952 zlog_debug ("zebra message received [%s] %d in VRF %u",
1953 zserv_command_string (command), length, vrf_id);
718e3744 1954
2176b7c3 1955 client->last_read_time = quagga_monotime();
04b02fda
DS
1956 client->last_read_cmd = command;
1957
5f3d1bdf 1958 zvrf = zebra_vrf_lookup_by_id (vrf_id);
d651649e
DS
1959 if (!zvrf)
1960 {
1961 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
1962 zlog_debug ("zebra received unknown VRF[%u]", vrf_id);
1963 goto zclient_read_out;
1964 }
1965
718e3744 1966 switch (command)
1967 {
18a6dce6 1968 case ZEBRA_ROUTER_ID_ADD:
d651649e 1969 zread_router_id_add (client, length, zvrf);
18a6dce6 1970 break;
1971 case ZEBRA_ROUTER_ID_DELETE:
d651649e 1972 zread_router_id_delete (client, length, zvrf);
18a6dce6 1973 break;
718e3744 1974 case ZEBRA_INTERFACE_ADD:
d651649e 1975 zread_interface_add (client, length, zvrf);
718e3744 1976 break;
1977 case ZEBRA_INTERFACE_DELETE:
d651649e 1978 zread_interface_delete (client, length, zvrf);
718e3744 1979 break;
1980 case ZEBRA_IPV4_ROUTE_ADD:
d651649e 1981 zread_ipv4_add (client, length, zvrf);
718e3744 1982 break;
1983 case ZEBRA_IPV4_ROUTE_DELETE:
d651649e 1984 zread_ipv4_delete (client, length, zvrf);
718e3744 1985 break;
8a92a8a0 1986 case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD:
d651649e 1987 zread_ipv4_route_ipv6_nexthop_add (client, length, zvrf);
8a92a8a0 1988 break;
65efcfce
LB
1989 case ZEBRA_IPV4_NEXTHOP_ADD:
1990 zread_ipv4_add(client, length, zvrf); /* LB: r1.0 merge - id was 1 */
1991 break;
1992 case ZEBRA_IPV4_NEXTHOP_DELETE:
1993 zread_ipv4_delete(client, length, zvrf); /* LB: r1.0 merge - id was 1 */
1994 break;
718e3744 1995 case ZEBRA_IPV6_ROUTE_ADD:
d651649e 1996 zread_ipv6_add (client, length, zvrf);
718e3744 1997 break;
1998 case ZEBRA_IPV6_ROUTE_DELETE:
d651649e 1999 zread_ipv6_delete (client, length, zvrf);
718e3744 2000 break;
718e3744 2001 case ZEBRA_REDISTRIBUTE_ADD:
d651649e 2002 zebra_redistribute_add (command, client, length, zvrf);
718e3744 2003 break;
2004 case ZEBRA_REDISTRIBUTE_DELETE:
d651649e 2005 zebra_redistribute_delete (command, client, length, zvrf);
718e3744 2006 break;
2007 case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
d651649e 2008 zebra_redistribute_default_add (command, client, length, zvrf);
718e3744 2009 break;
2010 case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
d651649e 2011 zebra_redistribute_default_delete (command, client, length, zvrf);
718e3744 2012 break;
6f61a5a3
EM
2013 case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB:
2014 zread_ipv4_nexthop_lookup_mrib (client, length, zvrf);
718e3744 2015 break;
2ea1ab1c
VT
2016 case ZEBRA_HELLO:
2017 zread_hello (client);
2018 break;
fb018d25 2019 case ZEBRA_NEXTHOP_REGISTER:
d651649e 2020 zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, zvrf);
fb018d25
DS
2021 break;
2022 case ZEBRA_NEXTHOP_UNREGISTER:
d651649e 2023 zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, zvrf);
078430f6
DS
2024 break;
2025 case ZEBRA_IMPORT_ROUTE_REGISTER:
d651649e 2026 zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf);
078430f6
DS
2027 break;
2028 case ZEBRA_IMPORT_ROUTE_UNREGISTER:
d651649e 2029 zserv_rnh_unregister(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf);
fb018d25 2030 break;
c43ed2e4
DS
2031 case ZEBRA_BFD_DEST_UPDATE:
2032 case ZEBRA_BFD_DEST_REGISTER:
d651649e 2033 zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf);
c43ed2e4
DS
2034 break;
2035 case ZEBRA_BFD_DEST_DEREGISTER:
d651649e 2036 zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf);
c43ed2e4 2037 break;
7076bb2f 2038 case ZEBRA_VRF_UNREGISTER:
d651649e 2039 zread_vrf_unregister (client, length, zvrf);
7076bb2f 2040 break;
055c4dfc 2041 case ZEBRA_BFD_CLIENT_REGISTER:
2042 zebra_ptm_bfd_client_register(client, sock, length);
2043 break;
4a04e5f7 2044 case ZEBRA_INTERFACE_ENABLE_RADV:
2045 zebra_interface_radv_set (client, sock, length, zvrf, 1);
2046 break;
2047 case ZEBRA_INTERFACE_DISABLE_RADV:
2048 zebra_interface_radv_set (client, sock, length, zvrf, 0);
2049 break;
ce549947
RW
2050 case ZEBRA_MPLS_LABELS_ADD:
2051 case ZEBRA_MPLS_LABELS_DELETE:
2052 zread_mpls_labels (command, client, length, vrf_id);
2053 break;
718e3744 2054 default:
2055 zlog_info ("Zebra received unknown command %d", command);
2056 break;
2057 }
2058
719e9741 2059 if (client->t_suicide)
2060 {
2061 /* No need to wait for thread callback, just kill immediately. */
2062 zebra_client_close(client);
2063 return -1;
2064 }
2065
d651649e 2066 zclient_read_out:
718e3744 2067 stream_reset (client->ibuf);
2068 zebra_event (ZEBRA_READ, sock, client);
718e3744 2069 return 0;
2070}
2071
718e3744 2072
2073/* Accept code of zebra server socket. */
b9df2d25 2074static int
718e3744 2075zebra_accept (struct thread *thread)
2076{
2077 int accept_sock;
2078 int client_sock;
2079 struct sockaddr_in client;
2080 socklen_t len;
2081
2082 accept_sock = THREAD_FD (thread);
2083
719e9741 2084 /* Reregister myself. */
2085 zebra_event (ZEBRA_SERV, accept_sock, NULL);
2086
718e3744 2087 len = sizeof (struct sockaddr_in);
2088 client_sock = accept (accept_sock, (struct sockaddr *) &client, &len);
2089
2090 if (client_sock < 0)
2091 {
6099b3b5 2092 zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno));
718e3744 2093 return -1;
2094 }
2095
ccf3557b 2096 /* Make client socket non-blocking. */
719e9741 2097 set_nonblocking(client_sock);
865b852c 2098
718e3744 2099 /* Create new zebra client. */
2100 zebra_client_create (client_sock);
2101
718e3744 2102 return 0;
2103}
2104
b9df2d25 2105#ifdef HAVE_TCP_ZEBRA
718e3744 2106/* Make zebra's server socket. */
b9df2d25 2107static void
718e3744 2108zebra_serv ()
2109{
2110 int ret;
2111 int accept_sock;
2112 struct sockaddr_in addr;
2113
2114 accept_sock = socket (AF_INET, SOCK_STREAM, 0);
2115
2116 if (accept_sock < 0)
2117 {
3d1dc857 2118 zlog_warn ("Can't create zserv stream socket: %s",
2119 safe_strerror (errno));
718e3744 2120 zlog_warn ("zebra can't provice full functionality due to above error");
2121 return;
2122 }
2123
2124 memset (&addr, 0, sizeof (struct sockaddr_in));
2125 addr.sin_family = AF_INET;
2126 addr.sin_port = htons (ZEBRA_PORT);
6f0e3f6e 2127#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
718e3744 2128 addr.sin_len = sizeof (struct sockaddr_in);
6f0e3f6e 2129#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
718e3744 2130 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
2131
2132 sockopt_reuseaddr (accept_sock);
2133 sockopt_reuseport (accept_sock);
2134
edd7c245 2135 if ( zserv_privs.change(ZPRIVS_RAISE) )
2136 zlog (NULL, LOG_ERR, "Can't raise privileges");
2137
718e3744 2138 ret = bind (accept_sock, (struct sockaddr *)&addr,
2139 sizeof (struct sockaddr_in));
2140 if (ret < 0)
2141 {
3d1dc857 2142 zlog_warn ("Can't bind to stream socket: %s",
2143 safe_strerror (errno));
718e3744 2144 zlog_warn ("zebra can't provice full functionality due to above error");
2145 close (accept_sock); /* Avoid sd leak. */
2146 return;
2147 }
edd7c245 2148
2149 if ( zserv_privs.change(ZPRIVS_LOWER) )
2150 zlog (NULL, LOG_ERR, "Can't lower privileges");
718e3744 2151
2152 ret = listen (accept_sock, 1);
2153 if (ret < 0)
2154 {
3d1dc857 2155 zlog_warn ("Can't listen to stream socket: %s",
2156 safe_strerror (errno));
718e3744 2157 zlog_warn ("zebra can't provice full functionality due to above error");
2158 close (accept_sock); /* Avoid sd leak. */
2159 return;
2160 }
2161
2162 zebra_event (ZEBRA_SERV, accept_sock, NULL);
2163}
fbedba64 2164#else /* HAVE_TCP_ZEBRA */
718e3744 2165
2166/* For sockaddr_un. */
2167#include <sys/un.h>
2168
2169/* zebra server UNIX domain socket. */
b9df2d25 2170static void
fce954f8 2171zebra_serv_un (const char *path)
718e3744 2172{
2173 int ret;
2174 int sock, len;
2175 struct sockaddr_un serv;
2176 mode_t old_mask;
2177
2178 /* First of all, unlink existing socket */
2179 unlink (path);
2180
2181 /* Set umask */
2182 old_mask = umask (0077);
2183
2184 /* Make UNIX domain socket. */
2185 sock = socket (AF_UNIX, SOCK_STREAM, 0);
2186 if (sock < 0)
2187 {
3d1dc857 2188 zlog_warn ("Can't create zserv unix socket: %s",
2189 safe_strerror (errno));
2190 zlog_warn ("zebra can't provide full functionality due to above error");
718e3744 2191 return;
2192 }
2193
2194 /* Make server socket. */
2195 memset (&serv, 0, sizeof (struct sockaddr_un));
2196 serv.sun_family = AF_UNIX;
2197 strncpy (serv.sun_path, path, strlen (path));
6f0e3f6e 2198#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
718e3744 2199 len = serv.sun_len = SUN_LEN(&serv);
2200#else
2201 len = sizeof (serv.sun_family) + strlen (serv.sun_path);
6f0e3f6e 2202#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
718e3744 2203
2204 ret = bind (sock, (struct sockaddr *) &serv, len);
2205 if (ret < 0)
2206 {
3d1dc857 2207 zlog_warn ("Can't bind to unix socket %s: %s",
2208 path, safe_strerror (errno));
2209 zlog_warn ("zebra can't provide full functionality due to above error");
718e3744 2210 close (sock);
2211 return;
2212 }
2213
2214 ret = listen (sock, 5);
2215 if (ret < 0)
2216 {
3d1dc857 2217 zlog_warn ("Can't listen to unix socket %s: %s",
2218 path, safe_strerror (errno));
2219 zlog_warn ("zebra can't provide full functionality due to above error");
718e3744 2220 close (sock);
2221 return;
2222 }
2223
2224 umask (old_mask);
2225
2226 zebra_event (ZEBRA_SERV, sock, NULL);
2227}
fbedba64 2228#endif /* HAVE_TCP_ZEBRA */
6b0655a2 2229
718e3744 2230
b9df2d25 2231static void
718e3744 2232zebra_event (enum event event, int sock, struct zserv *client)
2233{
2234 switch (event)
2235 {
2236 case ZEBRA_SERV:
b21b19c5 2237 thread_add_read (zebrad.master, zebra_accept, client, sock);
718e3744 2238 break;
2239 case ZEBRA_READ:
2240 client->t_read =
b21b19c5 2241 thread_add_read (zebrad.master, zebra_client_read, client, sock);
718e3744 2242 break;
2243 case ZEBRA_WRITE:
2244 /**/
2245 break;
2246 }
2247}
6b0655a2 2248
04b02fda
DS
2249#define ZEBRA_TIME_BUF 32
2250static char *
2251zserv_time_buf(time_t *time1, char *buf, int buflen)
2252{
2253 struct tm *tm;
2254 time_t now;
2255
2256 assert (buf != NULL);
2257 assert (buflen >= ZEBRA_TIME_BUF);
2258 assert (time1 != NULL);
2259
2260 if (!*time1)
2261 {
2262 snprintf(buf, buflen, "never ");
2263 return (buf);
2264 }
2265
2176b7c3 2266 now = quagga_monotime();
04b02fda
DS
2267 now -= *time1;
2268 tm = gmtime(&now);
2269
2270 /* Making formatted timer strings. */
2271#define ONE_DAY_SECOND 60*60*24
2272#define ONE_WEEK_SECOND 60*60*24*7
2273
2274 if (now < ONE_DAY_SECOND)
2275 snprintf (buf, buflen, "%02d:%02d:%02d",
2276 tm->tm_hour, tm->tm_min, tm->tm_sec);
2277 else if (now < ONE_WEEK_SECOND)
2278 snprintf (buf, buflen, "%dd%02dh%02dm",
2279 tm->tm_yday, tm->tm_hour, tm->tm_min);
2280 else
2281 snprintf (buf, buflen, "%02dw%dd%02dh",
2282 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
2283 return buf;
2284}
2285
2286static void
2287zebra_show_client_detail (struct vty *vty, struct zserv *client)
2288{
2289 char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
2290 char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
2291
7c8ff89e
DS
2292 vty_out (vty, "Client: %s", zebra_route_string(client->proto));
2293 if (client->instance)
2294 vty_out (vty, " Instance: %d", client->instance);
2295 vty_out (vty, "%s", VTY_NEWLINE);
2296
04b02fda
DS
2297 vty_out (vty, "------------------------ %s", VTY_NEWLINE);
2298 vty_out (vty, "FD: %d %s", client->sock, VTY_NEWLINE);
2299 vty_out (vty, "Route Table ID: %d %s", client->rtm_table, VTY_NEWLINE);
2300
2301 vty_out (vty, "Connect Time: %s %s",
2302 zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF),
2303 VTY_NEWLINE);
2304 if (client->nh_reg_time)
2305 {
2306 vty_out (vty, "Nexthop Registry Time: %s %s",
2307 zserv_time_buf(&client->nh_reg_time, nhbuf, ZEBRA_TIME_BUF),
2308 VTY_NEWLINE);
2309 if (client->nh_last_upd_time)
2310 vty_out (vty, "Nexthop Last Update Time: %s %s",
2311 zserv_time_buf(&client->nh_last_upd_time, mbuf, ZEBRA_TIME_BUF),
2312 VTY_NEWLINE);
2313 else
2314 vty_out (vty, "No Nexthop Update sent%s", VTY_NEWLINE);
2315 }
2316 else
2317 vty_out (vty, "Not registered for Nexthop Updates%s", VTY_NEWLINE);
2318
2319 vty_out (vty, "Last Msg Rx Time: %s %s",
2320 zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF),
2321 VTY_NEWLINE);
2322 vty_out (vty, "Last Msg Tx Time: %s %s",
2323 zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF),
2324 VTY_NEWLINE);
2325 if (client->last_read_time)
2326 vty_out (vty, "Last Rcvd Cmd: %s %s",
2327 zserv_command_string(client->last_read_cmd), VTY_NEWLINE);
2328 if (client->last_write_time)
2329 vty_out (vty, "Last Sent Cmd: %s %s",
2330 zserv_command_string(client->last_write_cmd), VTY_NEWLINE);
2331 vty_out (vty, "%s", VTY_NEWLINE);
2332
2333 vty_out (vty, "Type Add Update Del %s", VTY_NEWLINE);
2334 vty_out (vty, "================================================== %s", VTY_NEWLINE);
2335 vty_out (vty, "IPv4 %-12d%-12d%-12d%s", client->v4_route_add_cnt,
2336 client->v4_route_upd8_cnt, client->v4_route_del_cnt, VTY_NEWLINE);
2337 vty_out (vty, "IPv6 %-12d%-12d%-12d%s", client->v6_route_add_cnt,
2338 client->v6_route_upd8_cnt, client->v6_route_del_cnt, VTY_NEWLINE);
2339 vty_out (vty, "Redist:v4 %-12d%-12d%-12d%s", client->redist_v4_add_cnt, 0,
2340 client->redist_v4_del_cnt, VTY_NEWLINE);
2341 vty_out (vty, "Redist:v6 %-12d%-12d%-12d%s", client->redist_v6_add_cnt, 0,
2342 client->redist_v6_del_cnt, VTY_NEWLINE);
2343 vty_out (vty, "Connected %-12d%-12d%-12d%s", client->ifadd_cnt, 0,
2344 client->ifdel_cnt, VTY_NEWLINE);
c43ed2e4
DS
2345 vty_out (vty, "BFD peer %-12d%-12d%-12d%s", client->bfd_peer_add_cnt,
2346 client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt, VTY_NEWLINE);
04b02fda
DS
2347 vty_out (vty, "Interface Up Notifications: %d%s", client->ifup_cnt,
2348 VTY_NEWLINE);
2349 vty_out (vty, "Interface Down Notifications: %d%s", client->ifdown_cnt,
2350 VTY_NEWLINE);
2351
2352 vty_out (vty, "%s", VTY_NEWLINE);
2353 return;
2354}
2355
2356static void
2357zebra_show_client_brief (struct vty *vty, struct zserv *client)
2358{
2359 char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
2360 char wbuf[ZEBRA_TIME_BUF];
2361
2362 vty_out (vty, "%-8s%12s %12s%12s%8d/%-8d%8d/%-8d%s",
2363 zebra_route_string(client->proto),
2364 zserv_time_buf(&client->connect_time, cbuf, ZEBRA_TIME_BUF),
2365 zserv_time_buf(&client->last_read_time, rbuf, ZEBRA_TIME_BUF),
2366 zserv_time_buf(&client->last_write_time, wbuf, ZEBRA_TIME_BUF),
2367 client->v4_route_add_cnt+client->v4_route_upd8_cnt,
2368 client->v4_route_del_cnt,
2369 client->v6_route_add_cnt+client->v6_route_upd8_cnt,
2370 client->v6_route_del_cnt, VTY_NEWLINE);
2371
2372}
2373
5e08fee1 2374struct zserv *
2375zebra_find_client (u_char proto)
2376{
2377 struct listnode *node, *nnode;
2378 struct zserv *client;
2379
2380 for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
2381 {
2382 if (client->proto == proto)
2383 return client;
2384 }
2385
2386 return NULL;
2387}
2388
04b02fda 2389
718e3744 2390/* Display default rtm_table for all clients. */
2391DEFUN (show_table,
2392 show_table_cmd,
2393 "show table",
2394 SHOW_STR
2395 "default routing table to use for all clients\n")
2396{
b21b19c5 2397 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
718e3744 2398 VTY_NEWLINE);
2399 return CMD_SUCCESS;
2400}
2401
6147e2c6 2402DEFUN (config_table,
718e3744 2403 config_table_cmd,
2404 "table TABLENO",
2405 "Configure target kernel routing table\n"
2406 "TABLE integer\n")
2407{
6af6be86 2408 zebrad.rtm_table_default = strtol (argv[1]->arg, (char**)0, 10);
718e3744 2409 return CMD_SUCCESS;
2410}
2411
813d4307
DW
2412DEFUN (no_config_table,
2413 no_config_table_cmd,
6af6be86 2414 "no table [TABLENO]",
813d4307
DW
2415 NO_STR
2416 "Configure target kernel routing table\n"
2417 "TABLE integer\n")
2418{
2419 zebrad.rtm_table_default = 0;
2420 return CMD_SUCCESS;
2421}
2422
647e4f1f 2423DEFUN (ip_forwarding,
2424 ip_forwarding_cmd,
2425 "ip forwarding",
2426 IP_STR
2427 "Turn on IP forwarding")
2428{
2429 int ret;
2430
2431 ret = ipforward ();
b71f00f2 2432 if (ret == 0)
2433 ret = ipforward_on ();
647e4f1f 2434
647e4f1f 2435 if (ret == 0)
2436 {
2437 vty_out (vty, "Can't turn on IP forwarding%s", VTY_NEWLINE);
2438 return CMD_WARNING;
2439 }
2440
2441 return CMD_SUCCESS;
2442}
2443
718e3744 2444DEFUN (no_ip_forwarding,
2445 no_ip_forwarding_cmd,
2446 "no ip forwarding",
2447 NO_STR
2448 IP_STR
2449 "Turn off IP forwarding")
2450{
2451 int ret;
2452
2453 ret = ipforward ();
b71f00f2 2454 if (ret != 0)
2455 ret = ipforward_off ();
718e3744 2456
718e3744 2457 if (ret != 0)
2458 {
2459 vty_out (vty, "Can't turn off IP forwarding%s", VTY_NEWLINE);
2460 return CMD_WARNING;
2461 }
2462
2463 return CMD_SUCCESS;
2464}
2465
2466/* This command is for debugging purpose. */
2467DEFUN (show_zebra_client,
2468 show_zebra_client_cmd,
2469 "show zebra client",
2470 SHOW_STR
49d73233 2471 "Zebra information\n"
718e3744 2472 "Client information")
2473{
52dc7ee6 2474 struct listnode *node;
718e3744 2475 struct zserv *client;
2476
1eb8ef25 2477 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
04b02fda
DS
2478 zebra_show_client_detail(vty, client);
2479
2480 return CMD_SUCCESS;
2481}
2482
2483/* This command is for debugging purpose. */
2484DEFUN (show_zebra_client_summary,
2485 show_zebra_client_summary_cmd,
2486 "show zebra client summary",
2487 SHOW_STR
2488 "Zebra information brief"
2489 "Client information brief")
2490{
2491 struct listnode *node;
2492 struct zserv *client;
2493
2494 vty_out (vty, "Name Connect Time Last Read Last Write IPv4 Routes IPv6 Routes %s",
2495 VTY_NEWLINE);
2496 vty_out (vty,"--------------------------------------------------------------------------------%s",
2497 VTY_NEWLINE);
2498
2499 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
2500 zebra_show_client_brief(vty, client);
fb018d25 2501
04b02fda 2502 vty_out (vty, "Routes column shows (added+updated)/deleted%s", VTY_NEWLINE);
718e3744 2503 return CMD_SUCCESS;
2504}
2505
2506/* Table configuration write function. */
b9df2d25 2507static int
718e3744 2508config_write_table (struct vty *vty)
2509{
b21b19c5 2510 if (zebrad.rtm_table_default)
2511 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
718e3744 2512 VTY_NEWLINE);
2513 return 0;
2514}
2515
2516/* table node for routing tables. */
7fc626de 2517static struct cmd_node table_node =
718e3744 2518{
2519 TABLE_NODE,
2520 "", /* This node has no interface. */
2521 1
2522};
6b0655a2 2523
718e3744 2524/* Only display ip forwarding is enabled or not. */
2525DEFUN (show_ip_forwarding,
2526 show_ip_forwarding_cmd,
2527 "show ip forwarding",
2528 SHOW_STR
2529 IP_STR
2530 "IP forwarding status\n")
2531{
2532 int ret;
2533
2534 ret = ipforward ();
2535
2536 if (ret == 0)
2537 vty_out (vty, "IP forwarding is off%s", VTY_NEWLINE);
2538 else
2539 vty_out (vty, "IP forwarding is on%s", VTY_NEWLINE);
2540 return CMD_SUCCESS;
2541}
2542
2543#ifdef HAVE_IPV6
2544/* Only display ipv6 forwarding is enabled or not. */
2545DEFUN (show_ipv6_forwarding,
2546 show_ipv6_forwarding_cmd,
2547 "show ipv6 forwarding",
2548 SHOW_STR
2549 "IPv6 information\n"
2550 "Forwarding status\n")
2551{
2552 int ret;
2553
2554 ret = ipforward_ipv6 ();
2555
2556 switch (ret)
2557 {
2558 case -1:
2559 vty_out (vty, "ipv6 forwarding is unknown%s", VTY_NEWLINE);
2560 break;
2561 case 0:
2562 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
2563 break;
2564 case 1:
2565 vty_out (vty, "ipv6 forwarding is %s%s", "on", VTY_NEWLINE);
2566 break;
2567 default:
2568 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
2569 break;
2570 }
2571 return CMD_SUCCESS;
2572}
2573
55906724 2574DEFUN (ipv6_forwarding,
2575 ipv6_forwarding_cmd,
2576 "ipv6 forwarding",
2577 IPV6_STR
2578 "Turn on IPv6 forwarding")
2579{
2580 int ret;
2581
41d3fc96 2582 ret = ipforward_ipv6 ();
b71f00f2 2583 if (ret == 0)
2584 ret = ipforward_ipv6_on ();
41d3fc96 2585
41d3fc96 2586 if (ret == 0)
55906724 2587 {
2588 vty_out (vty, "Can't turn on IPv6 forwarding%s", VTY_NEWLINE);
2589 return CMD_WARNING;
2590 }
2591
2592 return CMD_SUCCESS;
2593}
2594
718e3744 2595DEFUN (no_ipv6_forwarding,
2596 no_ipv6_forwarding_cmd,
2597 "no ipv6 forwarding",
2598 NO_STR
55906724 2599 IPV6_STR
2600 "Turn off IPv6 forwarding")
718e3744 2601{
2602 int ret;
2603
41d3fc96 2604 ret = ipforward_ipv6 ();
b71f00f2 2605 if (ret != 0)
2606 ret = ipforward_ipv6_off ();
41d3fc96 2607
718e3744 2608 if (ret != 0)
2609 {
2610 vty_out (vty, "Can't turn off IPv6 forwarding%s", VTY_NEWLINE);
2611 return CMD_WARNING;
2612 }
2613
2614 return CMD_SUCCESS;
2615}
2616
2617#endif /* HAVE_IPV6 */
2618
2619/* IPForwarding configuration write function. */
719e9741 2620static int
718e3744 2621config_write_forwarding (struct vty *vty)
2622{
18a6dce6 2623 /* FIXME: Find better place for that. */
2624 router_id_write (vty);
2625
f40dd648
QY
2626 if (!ipforward ())
2627 vty_out (vty, "no ip forwarding%s", VTY_NEWLINE);
718e3744 2628#ifdef HAVE_IPV6
f40dd648
QY
2629 if (!ipforward_ipv6 ())
2630 vty_out (vty, "no ipv6 forwarding%s", VTY_NEWLINE);
718e3744 2631#endif /* HAVE_IPV6 */
2632 vty_out (vty, "!%s", VTY_NEWLINE);
2633 return 0;
2634}
2635
2636/* table node for routing tables. */
7fc626de 2637static struct cmd_node forwarding_node =
718e3744 2638{
2639 FORWARDING_NODE,
2640 "", /* This node has no interface. */
2641 1
2642};
2643
711ff0ba
USK
2644#ifdef HAVE_FPM
2645/* function to write the fpm config info */
2646static int
2647config_write_fpm (struct vty *vty)
2648{
2649 return
2650 fpm_remote_srv_write (vty);
2651}
2652
2653/* Zebra node */
2654static struct cmd_node zebra_node =
2655{
2656 ZEBRA_NODE,
2657 "",
2658 1
2659};
2660#endif
2661
6b0655a2 2662
718e3744 2663/* Initialisation of zebra and installation of commands. */
2664void
a1ac18c4 2665zebra_init (void)
718e3744 2666{
2667 /* Client list init. */
b21b19c5 2668 zebrad.client_list = list_new ();
718e3744 2669
718e3744 2670 /* Install configuration write function. */
2671 install_node (&table_node, config_write_table);
2672 install_node (&forwarding_node, config_write_forwarding);
711ff0ba
USK
2673#ifdef HAVE_FPM
2674 install_node (&zebra_node, config_write_fpm);
2675#endif
718e3744 2676
2677 install_element (VIEW_NODE, &show_ip_forwarding_cmd);
647e4f1f 2678 install_element (CONFIG_NODE, &ip_forwarding_cmd);
718e3744 2679 install_element (CONFIG_NODE, &no_ip_forwarding_cmd);
2680 install_element (ENABLE_NODE, &show_zebra_client_cmd);
04b02fda 2681 install_element (ENABLE_NODE, &show_zebra_client_summary_cmd);
718e3744 2682
2683#ifdef HAVE_NETLINK
2684 install_element (VIEW_NODE, &show_table_cmd);
718e3744 2685 install_element (CONFIG_NODE, &config_table_cmd);
813d4307 2686 install_element (CONFIG_NODE, &no_config_table_cmd);
718e3744 2687#endif /* HAVE_NETLINK */
2688
2689#ifdef HAVE_IPV6
2690 install_element (VIEW_NODE, &show_ipv6_forwarding_cmd);
55906724 2691 install_element (CONFIG_NODE, &ipv6_forwarding_cmd);
718e3744 2692 install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
2693#endif /* HAVE_IPV6 */
7514fb77
PJ
2694
2695 /* Route-map */
2696 zebra_route_map_init ();
718e3744 2697}
97be79f9
DO
2698
2699/* Make zebra server socket, wiping any existing one (see bug #403). */
2700void
b5114685 2701zebra_zserv_socket_init (char *path)
97be79f9
DO
2702{
2703#ifdef HAVE_TCP_ZEBRA
2704 zebra_serv ();
2705#else
b5114685 2706 zebra_serv_un (path ? path : ZEBRA_SERV_PATH);
97be79f9
DO
2707#endif /* HAVE_TCP_ZEBRA */
2708}