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