]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zserv.c
Save the last message from a peer that caused us to send a NOTIFICATION
[mirror_frr.git] / zebra / zserv.c
CommitLineData
718e3744 1/* Zebra daemon server routine.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "command.h"
26#include "if.h"
27#include "thread.h"
28#include "stream.h"
29#include "memory.h"
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"
718e3744 40
41#include "zebra/zserv.h"
18a6dce6 42#include "zebra/router-id.h"
718e3744 43#include "zebra/redistribute.h"
44#include "zebra/debug.h"
45#include "zebra/ipforward.h"
fb018d25 46#include "zebra/zebra_rnh.h"
6b0655a2 47
718e3744 48/* Event list of zebra. */
49enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
50
b21b19c5 51extern struct zebra_t zebrad;
718e3744 52
b9df2d25 53static void zebra_event (enum event event, int sock, struct zserv *client);
ccf3557b 54
edd7c245 55extern struct zebra_privs_t zserv_privs;
6b0655a2 56
719e9741 57static void zebra_client_close (struct zserv *client);
ccf3557b 58
719e9741 59static int
60zserv_delayed_close(struct thread *thread)
ccf3557b 61{
719e9741 62 struct zserv *client = THREAD_ARG(thread);
ccf3557b 63
719e9741 64 client->t_suicide = NULL;
65 zebra_client_close(client);
ccf3557b 66 return 0;
67}
68
2ea1ab1c
VT
69/* When client connects, it sends hello message
70 * with promise to send zebra routes of specific type.
71 * Zebra stores a socket fd of the client into
72 * this array. And use it to clean up routes that
73 * client didn't remove for some reasons after closing
74 * connection.
75 */
76static int route_type_oaths[ZEBRA_ROUTE_MAX];
77
719e9741 78static int
79zserv_flush_data(struct thread *thread)
ccf3557b 80{
719e9741 81 struct zserv *client = THREAD_ARG(thread);
ccf3557b 82
719e9741 83 client->t_write = NULL;
84 if (client->t_suicide)
ccf3557b 85 {
719e9741 86 zebra_client_close(client);
87 return -1;
ccf3557b 88 }
719e9741 89 switch (buffer_flush_available(client->wb, client->sock))
ccf3557b 90 {
719e9741 91 case BUFFER_ERROR:
92 zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, "
93 "closing", __func__, client->sock);
94 zebra_client_close(client);
95 break;
96 case BUFFER_PENDING:
97 client->t_write = thread_add_write(zebrad.master, zserv_flush_data,
98 client, client->sock);
99 break;
100 case BUFFER_EMPTY:
101 break;
ccf3557b 102 }
719e9741 103 return 0;
104}
ccf3557b 105
fb018d25 106int
719e9741 107zebra_server_send_message(struct zserv *client)
108{
109 if (client->t_suicide)
110 return -1;
111 switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf),
112 stream_get_endp(client->obuf)))
113 {
114 case BUFFER_ERROR:
115 zlog_warn("%s: buffer_write failed to zserv client fd %d, closing",
116 __func__, client->sock);
117 /* Schedule a delayed close since many of the functions that call this
118 one do not check the return code. They do not allow for the
119 possibility that an I/O error may have caused the client to be
120 deleted. */
121 client->t_suicide = thread_add_event(zebrad.master, zserv_delayed_close,
122 client, 0);
123 return -1;
719e9741 124 case BUFFER_EMPTY:
125 THREAD_OFF(client->t_write);
126 break;
127 case BUFFER_PENDING:
128 THREAD_WRITE_ON(zebrad.master, client->t_write,
129 zserv_flush_data, client, client->sock);
130 break;
131 }
ccf3557b 132 return 0;
133}
134
fb018d25 135void
c1b9800a 136zserv_create_header (struct stream *s, uint16_t cmd)
137{
138 /* length placeholder, caller can update */
139 stream_putw (s, ZEBRA_HEADER_SIZE);
140 stream_putc (s, ZEBRA_HEADER_MARKER);
141 stream_putc (s, ZSERV_VERSION);
142 stream_putw (s, cmd);
143}
144
51d4ef83
JB
145static void
146zserv_encode_interface (struct stream *s, struct interface *ifp)
147{
148 /* Interface information. */
149 stream_put (s, ifp->name, INTERFACE_NAMSIZ);
150 stream_putl (s, ifp->ifindex);
151 stream_putc (s, ifp->status);
152 stream_putq (s, ifp->flags);
153 stream_putl (s, ifp->metric);
154 stream_putl (s, ifp->mtu);
155 stream_putl (s, ifp->mtu6);
156 stream_putl (s, ifp->bandwidth);
157#ifdef HAVE_STRUCT_SOCKADDR_DL
ca3ccd87 158 stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage));
51d4ef83
JB
159#else
160 stream_putl (s, ifp->hw_addr_len);
161 if (ifp->hw_addr_len)
162 stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
163#endif /* HAVE_STRUCT_SOCKADDR_DL */
164
165 /* Write packet size. */
166 stream_putw_at (s, 0, stream_get_endp (s));
167}
168
718e3744 169/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
b9df2d25 170/*
171 * This function is called in the following situations:
172 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
173 * from the client.
174 * - at startup, when zebra figures out the available interfaces
175 * - when an interface is added (where support for
176 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
177 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
178 * received)
179 */
718e3744 180int
181zsend_interface_add (struct zserv *client, struct interface *ifp)
182{
183 struct stream *s;
184
185 /* Check this client need interface information. */
186 if (! client->ifinfo)
719e9741 187 return 0;
718e3744 188
189 s = client->obuf;
190 stream_reset (s);
191
c1b9800a 192 zserv_create_header (s, ZEBRA_INTERFACE_ADD);
51d4ef83 193 zserv_encode_interface (s, ifp);
718e3744 194
719e9741 195 return zebra_server_send_message(client);
718e3744 196}
197
198/* Interface deletion from zebra daemon. */
199int
200zsend_interface_delete (struct zserv *client, struct interface *ifp)
201{
202 struct stream *s;
203
204 /* Check this client need interface information. */
205 if (! client->ifinfo)
719e9741 206 return 0;
718e3744 207
208 s = client->obuf;
209 stream_reset (s);
718e3744 210
51d4ef83
JB
211 zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
212 zserv_encode_interface (s, ifp);
718e3744 213
719e9741 214 return zebra_server_send_message (client);
718e3744 215}
216
b9df2d25 217/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
218 * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
219 *
220 * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
221 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
222 * from the client, after the ZEBRA_INTERFACE_ADD has been
223 * sent from zebra to the client
224 * - redistribute new address info to all clients in the following situations
225 * - at startup, when zebra figures out the available interfaces
226 * - when an interface is added (where support for
227 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
228 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
229 * received)
230 * - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
231 * and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
232 * - when an RTM_NEWADDR message is received from the kernel,
233 *
234 * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:
235 *
236 * zsend_interface_address(DELETE)
237 * ^
238 * |
239 * zebra_interface_address_delete_update
240 * ^ ^ ^
6eb8827d 241 * | | if_delete_update
242 * | |
b9df2d25 243 * ip_address_uninstall connected_delete_ipv4
244 * [ipv6_addresss_uninstall] [connected_delete_ipv6]
245 * ^ ^
246 * | |
247 * | RTM_NEWADDR on routing/netlink socket
248 * |
249 * vty commands:
250 * "no ip address A.B.C.D/M [label LINE]"
251 * "no ip address A.B.C.D/M secondary"
252 * ["no ipv6 address X:X::X:X/M"]
253 *
254 */
718e3744 255int
b9df2d25 256zsend_interface_address (int cmd, struct zserv *client,
257 struct interface *ifp, struct connected *ifc)
718e3744 258{
259 int blen;
260 struct stream *s;
261 struct prefix *p;
262
263 /* Check this client need interface information. */
264 if (! client->ifinfo)
719e9741 265 return 0;
718e3744 266
267 s = client->obuf;
268 stream_reset (s);
c1b9800a 269
270 zserv_create_header (s, cmd);
718e3744 271 stream_putl (s, ifp->ifindex);
272
273 /* Interface address flag. */
274 stream_putc (s, ifc->flags);
275
276 /* Prefix information. */
277 p = ifc->address;
278 stream_putc (s, p->family);
279 blen = prefix_blen (p);
280 stream_put (s, &p->u.prefix, blen);
b9df2d25 281
282 /*
283 * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE
284 * but zebra_interface_address_delete_read() in the gnu version
285 * expects to find it
286 */
718e3744 287 stream_putc (s, p->prefixlen);
288
289 /* Destination. */
290 p = ifc->destination;
291 if (p)
292 stream_put (s, &p->u.prefix, blen);
293 else
294 stream_put (s, NULL, blen);
295
296 /* Write packet size. */
297 stream_putw_at (s, 0, stream_get_endp (s));
298
719e9741 299 return zebra_server_send_message(client);
718e3744 300}
301
b9df2d25 302/*
303 * The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or
304 * ZEBRA_INTERFACE_DOWN.
305 *
306 * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
307 * the clients in one of 2 situations:
308 * - an if_up is detected e.g., as a result of an RTM_IFINFO message
309 * - a vty command modifying the bandwidth of an interface is received.
310 * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
311 */
718e3744 312int
b9df2d25 313zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
718e3744 314{
315 struct stream *s;
316
317 /* Check this client need interface information. */
318 if (! client->ifinfo)
719e9741 319 return 0;
718e3744 320
321 s = client->obuf;
322 stream_reset (s);
323
c1b9800a 324 zserv_create_header (s, cmd);
51d4ef83 325 zserv_encode_interface (s, ifp);
718e3744 326
719e9741 327 return zebra_server_send_message(client);
718e3744 328}
329
b9df2d25 330/*
331 * The zebra server sends the clients a ZEBRA_IPV4_ROUTE_ADD or a
332 * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following
333 * situations:
334 * - when the client starts up, and requests default information
335 * by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the
336 * - case of rip, ripngd, ospfd and ospf6d, when the client sends a
337 * ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd,
338 * - when the zebra server redistributes routes after it updates its rib
339 *
340 * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a
341 * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when:
342 * - a "ip route" or "ipv6 route" vty command is issued, a prefix is
343 * - deleted from zebra's rib, and this info
344 * has to be redistributed to the clients
345 *
346 * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the
347 * zebra server when the client wants to tell the zebra server to add a
348 * route to the kernel (zapi_ipv4_add etc. ). Since it's essentially the
349 * same message being sent back and forth, this function and
350 * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code
351 * duplication.
352 */
718e3744 353int
b9df2d25 354zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
355 struct rib *rib)
718e3744 356{
357 int psize;
358 struct stream *s;
359 struct nexthop *nexthop;
1dcb5172 360 unsigned long nhnummark = 0, messmark = 0;
b9df2d25 361 int nhnum = 0;
1dcb5172 362 u_char zapi_flags = 0;
b9df2d25 363
718e3744 364 s = client->obuf;
365 stream_reset (s);
c1b9800a 366
367 zserv_create_header (s, cmd);
368
369 /* Put type and nexthop. */
718e3744 370 stream_putc (s, rib->type);
371 stream_putc (s, rib->flags);
1dcb5172 372
373 /* marker for message flags field */
374 messmark = stream_get_endp (s);
375 stream_putc (s, 0);
718e3744 376
377 /* Prefix. */
378 psize = PSIZE (p->prefixlen);
379 stream_putc (s, p->prefixlen);
b9df2d25 380 stream_write (s, (u_char *) & p->u.prefix, psize);
381
382 /*
383 * XXX The message format sent by zebra below does not match the format
384 * of the corresponding message expected by the zebra server
385 * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly,
386 * (is there a bug on the client side if more than one segment is sent?)
387 * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX
388 * is hard-coded.
389 */
718e3744 390 /* Nexthop */
1dcb5172 391
718e3744 392 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
393 {
fa713d9e
CF
394 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
395 || nexthop_has_fib_child(nexthop))
b9df2d25 396 {
1dcb5172 397 SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
398 SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
399
400 if (nhnummark == 0)
401 {
402 nhnummark = stream_get_endp (s);
403 stream_putc (s, 1); /* placeholder */
404 }
405
b9df2d25 406 nhnum++;
407
408 switch(nexthop->type)
409 {
410 case NEXTHOP_TYPE_IPV4:
411 case NEXTHOP_TYPE_IPV4_IFINDEX:
412 stream_put_in_addr (s, &nexthop->gate.ipv4);
413 break;
718e3744 414#ifdef HAVE_IPV6
b9df2d25 415 case NEXTHOP_TYPE_IPV6:
416 case NEXTHOP_TYPE_IPV6_IFINDEX:
417 case NEXTHOP_TYPE_IPV6_IFNAME:
418 stream_write (s, (u_char *) &nexthop->gate.ipv6, 16);
419 break;
420#endif
421 default:
422 if (cmd == ZEBRA_IPV4_ROUTE_ADD
423 || cmd == ZEBRA_IPV4_ROUTE_DELETE)
424 {
425 struct in_addr empty;
44983cf8 426 memset (&empty, 0, sizeof (struct in_addr));
b9df2d25 427 stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN);
428 }
429 else
430 {
431 struct in6_addr empty;
432 memset (&empty, 0, sizeof (struct in6_addr));
433 stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN);
434 }
435 }
436
437 /* Interface index. */
438 stream_putc (s, 1);
439 stream_putl (s, nexthop->ifindex);
440
441 break;
442 }
718e3744 443 }
444
445 /* Metric */
cf8a831b 446 if (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV6_ROUTE_ADD)
1dcb5172 447 {
fbf5d033 448 SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE);
449 stream_putc (s, rib->distance);
1dcb5172 450 SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC);
451 stream_putl (s, rib->metric);
452 }
453
454 /* write real message flags value */
455 stream_putc_at (s, messmark, zapi_flags);
456
b9df2d25 457 /* Write next-hop number */
458 if (nhnummark)
c1eaa442 459 stream_putc_at (s, nhnummark, nhnum);
b9df2d25 460
718e3744 461 /* Write packet size. */
462 stream_putw_at (s, 0, stream_get_endp (s));
463
719e9741 464 return zebra_server_send_message(client);
718e3744 465}
466
b9df2d25 467#ifdef HAVE_IPV6
719e9741 468static int
718e3744 469zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr)
470{
471 struct stream *s;
472 struct rib *rib;
473 unsigned long nump;
474 u_char num;
475 struct nexthop *nexthop;
476
477 /* Lookup nexthop. */
478 rib = rib_match_ipv6 (addr);
479
480 /* Get output stream. */
481 s = client->obuf;
482 stream_reset (s);
483
484 /* Fill in result. */
c1b9800a 485 zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
718e3744 486 stream_put (s, &addr, 16);
487
488 if (rib)
489 {
490 stream_putl (s, rib->metric);
491 num = 0;
9985f83c 492 nump = stream_get_endp(s);
718e3744 493 stream_putc (s, 0);
fa713d9e
CF
494 /* Only non-recursive routes are elegible to resolve nexthop we
495 * are looking up. Therefore, we will just iterate over the top
496 * chain of nexthops. */
718e3744 497 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
498 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
499 {
500 stream_putc (s, nexthop->type);
501 switch (nexthop->type)
502 {
503 case ZEBRA_NEXTHOP_IPV6:
504 stream_put (s, &nexthop->gate.ipv6, 16);
505 break;
506 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
507 case ZEBRA_NEXTHOP_IPV6_IFNAME:
508 stream_put (s, &nexthop->gate.ipv6, 16);
509 stream_putl (s, nexthop->ifindex);
510 break;
511 case ZEBRA_NEXTHOP_IFINDEX:
512 case ZEBRA_NEXTHOP_IFNAME:
513 stream_putl (s, nexthop->ifindex);
514 break;
fa2b17e3 515 default:
516 /* do nothing */
517 break;
718e3744 518 }
519 num++;
520 }
521 stream_putc_at (s, nump, num);
522 }
523 else
524 {
525 stream_putl (s, 0);
526 stream_putc (s, 0);
527 }
528
529 stream_putw_at (s, 0, stream_get_endp (s));
530
719e9741 531 return zebra_server_send_message(client);
718e3744 532}
533#endif /* HAVE_IPV6 */
534
b9df2d25 535static int
718e3744 536zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
537{
538 struct stream *s;
539 struct rib *rib;
540 unsigned long nump;
541 u_char num;
542 struct nexthop *nexthop;
543
544 /* Lookup nexthop. */
545 rib = rib_match_ipv4 (addr);
546
547 /* Get output stream. */
548 s = client->obuf;
549 stream_reset (s);
550
551 /* Fill in result. */
c1b9800a 552 zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
718e3744 553 stream_put_in_addr (s, &addr);
554
555 if (rib)
556 {
bb97e462
CF
557 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
558 zlog_debug("%s: Matching rib entry found.", __func__);
718e3744 559 stream_putl (s, rib->metric);
560 num = 0;
9985f83c 561 nump = stream_get_endp(s);
718e3744 562 stream_putc (s, 0);
fa713d9e
CF
563 /* Only non-recursive routes are elegible to resolve the nexthop we
564 * are looking up. Therefore, we will just iterate over the top
565 * chain of nexthops. */
718e3744 566 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
567 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
568 {
569 stream_putc (s, nexthop->type);
570 switch (nexthop->type)
571 {
572 case ZEBRA_NEXTHOP_IPV4:
573 stream_put_in_addr (s, &nexthop->gate.ipv4);
574 break;
bb97e462
CF
575 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
576 stream_put_in_addr (s, &nexthop->gate.ipv4);
577 stream_putl (s, nexthop->ifindex);
578 break;
718e3744 579 case ZEBRA_NEXTHOP_IFINDEX:
580 case ZEBRA_NEXTHOP_IFNAME:
581 stream_putl (s, nexthop->ifindex);
582 break;
fa2b17e3 583 default:
584 /* do nothing */
585 break;
718e3744 586 }
587 num++;
588 }
589 stream_putc_at (s, nump, num);
590 }
591 else
592 {
bb97e462
CF
593 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
594 zlog_debug("%s: No matching rib entry found.", __func__);
718e3744 595 stream_putl (s, 0);
596 stream_putc (s, 0);
597 }
598
599 stream_putw_at (s, 0, stream_get_endp (s));
600
719e9741 601 return zebra_server_send_message(client);
718e3744 602}
603
fb018d25
DS
604/* Nexthop register */
605static int
606zserv_nexthop_register (struct zserv *client, int sock, u_short length)
607{
608 struct rnh *rnh;
609 struct stream *s;
610 struct prefix p;
611 u_short l = 0;
612
613 if (IS_ZEBRA_DEBUG_NHT)
614 zlog_debug("nexthop_register msg from client %s: length=%d\n",
615 zebra_route_string(client->proto), length);
616
617 s = client->ibuf;
618
619 while (l < length)
620 {
621 p.family = stream_getw(s);
622 p.prefixlen = stream_getc(s);
623 l += 3;
624 stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
625 l += PSIZE(p.prefixlen);
626 rnh = zebra_add_rnh(&p, 0);
627 zebra_add_rnh_client(rnh, client);
628 }
629 zebra_evaluate_rnh_table(0, AF_INET);
630 zebra_evaluate_rnh_table(0, AF_INET6);
631 return 0;
632}
633
634/* Nexthop register */
635static int
636zserv_nexthop_unregister (struct zserv *client, int sock, u_short length)
637{
638 struct rnh *rnh;
639 struct stream *s;
640 struct prefix p;
641 u_short l = 0;
642
643 if (IS_ZEBRA_DEBUG_NHT)
644 zlog_debug("nexthop_unregister msg from client %s: length=%d\n",
645 zebra_route_string(client->proto), length);
646
647 s = client->ibuf;
648
649 while (l < length)
650 {
651 p.family = stream_getw(s);
652 p.prefixlen = stream_getc(s);
653 l += 3;
654 stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
655 l += PSIZE(p.prefixlen);
656 rnh = zebra_lookup_rnh(&p, 0);
657 if (rnh)
658 zebra_remove_rnh_client(rnh, client);
659 }
660 return 0;
661}
662
b9df2d25 663static int
718e3744 664zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
665{
666 struct stream *s;
667 struct rib *rib;
668 unsigned long nump;
669 u_char num;
670 struct nexthop *nexthop;
671
672 /* Lookup nexthop. */
673 rib = rib_lookup_ipv4 (p);
674
675 /* Get output stream. */
676 s = client->obuf;
677 stream_reset (s);
678
679 /* Fill in result. */
c1b9800a 680 zserv_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
718e3744 681 stream_put_in_addr (s, &p->prefix);
682
683 if (rib)
684 {
685 stream_putl (s, rib->metric);
686 num = 0;
9985f83c 687 nump = stream_get_endp(s);
718e3744 688 stream_putc (s, 0);
689 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
fa713d9e
CF
690 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
691 || nexthop_has_fib_child(nexthop))
718e3744 692 {
693 stream_putc (s, nexthop->type);
694 switch (nexthop->type)
695 {
696 case ZEBRA_NEXTHOP_IPV4:
697 stream_put_in_addr (s, &nexthop->gate.ipv4);
698 break;
a12afd5e
CF
699 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
700 stream_put_in_addr (s, &nexthop->gate.ipv4);
701 stream_putl (s, nexthop->ifindex);
702 break;
718e3744 703 case ZEBRA_NEXTHOP_IFINDEX:
704 case ZEBRA_NEXTHOP_IFNAME:
705 stream_putl (s, nexthop->ifindex);
706 break;
fa2b17e3 707 default:
708 /* do nothing */
709 break;
718e3744 710 }
711 num++;
712 }
713 stream_putc_at (s, nump, num);
714 }
715 else
716 {
717 stream_putl (s, 0);
718 stream_putc (s, 0);
719 }
720
721 stream_putw_at (s, 0, stream_get_endp (s));
722
719e9741 723 return zebra_server_send_message(client);
718e3744 724}
6b0655a2 725
18a6dce6 726/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
727int
728zsend_router_id_update (struct zserv *client, struct prefix *p)
729{
730 struct stream *s;
731 int blen;
732
733 /* Check this client need interface information. */
734 if (!client->ridinfo)
719e9741 735 return 0;
18a6dce6 736
737 s = client->obuf;
738 stream_reset (s);
739
18a6dce6 740 /* Message type. */
c1b9800a 741 zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE);
18a6dce6 742
743 /* Prefix information. */
744 stream_putc (s, p->family);
745 blen = prefix_blen (p);
746 stream_put (s, &p->u.prefix, blen);
747 stream_putc (s, p->prefixlen);
748
749 /* Write packet size. */
750 stream_putw_at (s, 0, stream_get_endp (s));
751
719e9741 752 return zebra_server_send_message(client);
18a6dce6 753}
6b0655a2 754
718e3744 755/* Register zebra server interface information. Send current all
756 interface and address information. */
719e9741 757static int
718e3744 758zread_interface_add (struct zserv *client, u_short length)
759{
1eb8ef25 760 struct listnode *ifnode, *ifnnode;
761 struct listnode *cnode, *cnnode;
718e3744 762 struct interface *ifp;
763 struct connected *c;
764
765 /* Interface information is needed. */
766 client->ifinfo = 1;
767
1eb8ef25 768 for (ALL_LIST_ELEMENTS (iflist, ifnode, ifnnode, ifp))
718e3744 769 {
718e3744 770 /* Skip pseudo interface. */
771 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
772 continue;
773
719e9741 774 if (zsend_interface_add (client, ifp) < 0)
775 return -1;
718e3744 776
1eb8ef25 777 for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
718e3744 778 {
719e9741 779 if (CHECK_FLAG (c->conf, ZEBRA_IFC_REAL) &&
780 (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client,
781 ifp, c) < 0))
782 return -1;
718e3744 783 }
784 }
719e9741 785 return 0;
718e3744 786}
787
788/* Unregister zebra server interface information. */
719e9741 789static int
718e3744 790zread_interface_delete (struct zserv *client, u_short length)
791{
792 client->ifinfo = 0;
719e9741 793 return 0;
718e3744 794}
795
796/* This function support multiple nexthop. */
b9df2d25 797/*
798 * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
799 * add kernel route.
800 */
719e9741 801static int
718e3744 802zread_ipv4_add (struct zserv *client, u_short length)
803{
804 int i;
805 struct rib *rib;
806 struct prefix_ipv4 p;
807 u_char message;
808 struct in_addr nexthop;
809 u_char nexthop_num;
810 u_char nexthop_type;
811 struct stream *s;
812 unsigned int ifindex;
813 u_char ifname_len;
cddf391b
B
814 safi_t safi;
815
718e3744 816
817 /* Get input stream. */
818 s = client->ibuf;
819
820 /* Allocate new rib. */
4d38fdb4 821 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
822
718e3744 823 /* Type, flags, message. */
824 rib->type = stream_getc (s);
825 rib->flags = stream_getc (s);
b9df2d25 826 message = stream_getc (s);
cddf391b 827 safi = stream_getw (s);
718e3744 828 rib->uptime = time (NULL);
829
830 /* IPv4 prefix. */
831 memset (&p, 0, sizeof (struct prefix_ipv4));
832 p.family = AF_INET;
833 p.prefixlen = stream_getc (s);
834 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
835
836 /* Nexthop parse. */
837 if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
838 {
839 nexthop_num = stream_getc (s);
840
841 for (i = 0; i < nexthop_num; i++)
842 {
843 nexthop_type = stream_getc (s);
844
845 switch (nexthop_type)
846 {
847 case ZEBRA_NEXTHOP_IFINDEX:
848 ifindex = stream_getl (s);
849 nexthop_ifindex_add (rib, ifindex);
850 break;
851 case ZEBRA_NEXTHOP_IFNAME:
852 ifname_len = stream_getc (s);
9985f83c 853 stream_forward_getp (s, ifname_len);
718e3744 854 break;
855 case ZEBRA_NEXTHOP_IPV4:
856 nexthop.s_addr = stream_get_ipv4 (s);
7514fb77 857 nexthop_ipv4_add (rib, &nexthop, NULL);
718e3744 858 break;
c963c203
JT
859 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
860 nexthop.s_addr = stream_get_ipv4 (s);
861 ifindex = stream_getl (s);
862 nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
863 break;
718e3744 864 case ZEBRA_NEXTHOP_IPV6:
9985f83c 865 stream_forward_getp (s, IPV6_MAX_BYTELEN);
718e3744 866 break;
6902c69a
SV
867 case ZEBRA_NEXTHOP_BLACKHOLE:
868 nexthop_blackhole_add (rib);
869 break;
870 }
718e3744 871 }
872 }
873
874 /* Distance. */
875 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
876 rib->distance = stream_getc (s);
877
878 /* Metric. */
879 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
880 rib->metric = stream_getl (s);
881
171eee31
PJ
882 /* Table */
883 rib->table=zebrad.rtm_table_default;
cddf391b 884 rib_add_ipv4_multipath (&p, rib, safi);
719e9741 885 return 0;
718e3744 886}
887
888/* Zebra server IPv4 prefix delete function. */
719e9741 889static int
718e3744 890zread_ipv4_delete (struct zserv *client, u_short length)
891{
892 int i;
893 struct stream *s;
894 struct zapi_ipv4 api;
6902c69a 895 struct in_addr nexthop, *nexthop_p;
718e3744 896 unsigned long ifindex;
897 struct prefix_ipv4 p;
898 u_char nexthop_num;
899 u_char nexthop_type;
900 u_char ifname_len;
901
902 s = client->ibuf;
903 ifindex = 0;
904 nexthop.s_addr = 0;
6902c69a 905 nexthop_p = NULL;
718e3744 906
907 /* Type, flags, message. */
908 api.type = stream_getc (s);
909 api.flags = stream_getc (s);
910 api.message = stream_getc (s);
cddf391b 911 api.safi = stream_getw (s);
718e3744 912
913 /* IPv4 prefix. */
914 memset (&p, 0, sizeof (struct prefix_ipv4));
915 p.family = AF_INET;
916 p.prefixlen = stream_getc (s);
917 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
918
919 /* Nexthop, ifindex, distance, metric. */
920 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
921 {
922 nexthop_num = stream_getc (s);
923
924 for (i = 0; i < nexthop_num; i++)
925 {
926 nexthop_type = stream_getc (s);
927
928 switch (nexthop_type)
929 {
930 case ZEBRA_NEXTHOP_IFINDEX:
931 ifindex = stream_getl (s);
932 break;
933 case ZEBRA_NEXTHOP_IFNAME:
934 ifname_len = stream_getc (s);
9985f83c 935 stream_forward_getp (s, ifname_len);
718e3744 936 break;
937 case ZEBRA_NEXTHOP_IPV4:
938 nexthop.s_addr = stream_get_ipv4 (s);
6902c69a 939 nexthop_p = &nexthop;
718e3744 940 break;
c963c203
JT
941 case ZEBRA_NEXTHOP_IPV4_IFINDEX:
942 nexthop.s_addr = stream_get_ipv4 (s);
23f5f7c3 943 nexthop_p = &nexthop;
c963c203
JT
944 ifindex = stream_getl (s);
945 break;
718e3744 946 case ZEBRA_NEXTHOP_IPV6:
9985f83c 947 stream_forward_getp (s, IPV6_MAX_BYTELEN);
718e3744 948 break;
949 }
950 }
951 }
952
953 /* Distance. */
954 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
955 api.distance = stream_getc (s);
956 else
957 api.distance = 0;
958
959 /* Metric. */
960 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
961 api.metric = stream_getl (s);
962 else
963 api.metric = 0;
964
6902c69a 965 rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
cddf391b 966 client->rtm_table, api.safi);
719e9741 967 return 0;
718e3744 968}
969
970/* Nexthop lookup for IPv4. */
719e9741 971static int
718e3744 972zread_ipv4_nexthop_lookup (struct zserv *client, u_short length)
973{
974 struct in_addr addr;
bb97e462 975 char buf[BUFSIZ];
718e3744 976
977 addr.s_addr = stream_get_ipv4 (client->ibuf);
bb97e462
CF
978 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
979 zlog_debug("%s: looking up %s", __func__,
980 inet_ntop (AF_INET, &addr, buf, BUFSIZ));
719e9741 981 return zsend_ipv4_nexthop_lookup (client, addr);
718e3744 982}
983
984/* Nexthop lookup for IPv4. */
719e9741 985static int
718e3744 986zread_ipv4_import_lookup (struct zserv *client, u_short length)
987{
988 struct prefix_ipv4 p;
989
990 p.family = AF_INET;
991 p.prefixlen = stream_getc (client->ibuf);
992 p.prefix.s_addr = stream_get_ipv4 (client->ibuf);
993
719e9741 994 return zsend_ipv4_import_lookup (client, &p);
718e3744 995}
996
997#ifdef HAVE_IPV6
998/* Zebra server IPv6 prefix add function. */
719e9741 999static int
718e3744 1000zread_ipv6_add (struct zserv *client, u_short length)
1001{
1002 int i;
1003 struct stream *s;
718e3744 1004 struct in6_addr nexthop;
41fc2714
DS
1005 struct rib *rib;
1006 u_char message;
1007 u_char nexthop_num;
1008 u_char nexthop_type;
718e3744 1009 unsigned long ifindex;
1010 struct prefix_ipv6 p;
41fc2714
DS
1011 u_char ifname_len;
1012 safi_t safi;
1013 static struct in6_addr nexthops[MULTIPATH_NUM];
1014 static unsigned int ifindices[MULTIPATH_NUM];
1015
1016 /* Get input stream. */
718e3744 1017 s = client->ibuf;
41fc2714 1018
718e3744 1019 ifindex = 0;
1020 memset (&nexthop, 0, sizeof (struct in6_addr));
1021
41fc2714
DS
1022 /* Allocate new rib. */
1023 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
1024
718e3744 1025 /* Type, flags, message. */
41fc2714
DS
1026 rib->type = stream_getc (s);
1027 rib->flags = stream_getc (s);
1028 message = stream_getc (s);
1029 safi = stream_getw (s);
1030 rib->uptime = time (NULL);
718e3744 1031
41fc2714 1032 /* IPv6 prefix. */
718e3744 1033 memset (&p, 0, sizeof (struct prefix_ipv6));
1034 p.family = AF_INET6;
1035 p.prefixlen = stream_getc (s);
1036 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
1037
41fc2714
DS
1038 /* We need to give nh-addr, nh-ifindex with the same next-hop object
1039 * to the rib to ensure that IPv6 multipathing works; need to coalesce
1040 * these. Clients should send the same number of paired set of
1041 * next-hop-addr/next-hop-ifindices. */
1042 if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
718e3744 1043 {
41fc2714
DS
1044 int nh_count = 0;
1045 int if_count = 0;
1046 int max_nh_if = 0;
718e3744 1047
41fc2714
DS
1048 nexthop_num = stream_getc (s);
1049 for (i = 0; i < nexthop_num; i++)
718e3744 1050 {
1051 nexthop_type = stream_getc (s);
1052
1053 switch (nexthop_type)
1054 {
1055 case ZEBRA_NEXTHOP_IPV6:
1056 stream_get (&nexthop, s, 16);
41fc2714
DS
1057 if (nh_count < MULTIPATH_NUM) {
1058 nexthops[nh_count++] = nexthop;
1059 }
718e3744 1060 break;
1061 case ZEBRA_NEXTHOP_IFINDEX:
41fc2714
DS
1062 if (if_count < MULTIPATH_NUM) {
1063 ifindices[if_count++] = stream_getl (s);
1064 }
718e3744 1065 break;
1066 }
1067 }
41fc2714
DS
1068
1069 max_nh_if = (nh_count > if_count) ? nh_count : if_count;
1070 for (i = 0; i < max_nh_if; i++)
1071 {
1072 if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) {
1073 if ((i < if_count) && ifindices[i]) {
1074 if (rib_bogus_ipv6 (rib->type, &p, &nexthops[i], ifindices[i], 0)) {
1075 continue;
1076 }
1077 nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
1078 }
1079 else {
1080 if (rib_bogus_ipv6 (rib->type, &p, &nexthops[i], 0, 0)) {
1081 continue;
1082 }
1083 nexthop_ipv6_add (rib, &nexthops[i]);
1084 }
1085 }
1086 else {
1087 if ((i < if_count) && ifindices[i]) {
1088 if (rib_bogus_ipv6 (rib->type, &p, NULL, ifindices[i], 0)) {
1089 continue;
1090 }
1091 nexthop_ifindex_add (rib, ifindices[i]);
1092 }
1093 }
1094 }
718e3744 1095 }
1096
41fc2714
DS
1097 /* Distance. */
1098 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
1099 rib->distance = stream_getc (s);
718e3744 1100
41fc2714
DS
1101 /* Metric. */
1102 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
1103 rib->metric = stream_getl (s);
718e3744 1104
41fc2714
DS
1105 /* Table */
1106 rib->table=zebrad.rtm_table_default;
1107 rib_add_ipv6_multipath (&p, rib, safi, ifindex);
719e9741 1108 return 0;
718e3744 1109}
1110
1111/* Zebra server IPv6 prefix delete function. */
719e9741 1112static int
718e3744 1113zread_ipv6_delete (struct zserv *client, u_short length)
1114{
1115 int i;
1116 struct stream *s;
1117 struct zapi_ipv6 api;
1118 struct in6_addr nexthop;
1119 unsigned long ifindex;
1120 struct prefix_ipv6 p;
1121
1122 s = client->ibuf;
1123 ifindex = 0;
1124 memset (&nexthop, 0, sizeof (struct in6_addr));
1125
1126 /* Type, flags, message. */
1127 api.type = stream_getc (s);
1128 api.flags = stream_getc (s);
1129 api.message = stream_getc (s);
f768f367 1130 api.safi = stream_getw (s);
718e3744 1131
1132 /* IPv4 prefix. */
1133 memset (&p, 0, sizeof (struct prefix_ipv6));
1134 p.family = AF_INET6;
1135 p.prefixlen = stream_getc (s);
1136 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
1137
1138 /* Nexthop, ifindex, distance, metric. */
1139 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
1140 {
1141 u_char nexthop_type;
1142
1143 api.nexthop_num = stream_getc (s);
1144 for (i = 0; i < api.nexthop_num; i++)
1145 {
1146 nexthop_type = stream_getc (s);
1147
1148 switch (nexthop_type)
1149 {
1150 case ZEBRA_NEXTHOP_IPV6:
1151 stream_get (&nexthop, s, 16);
1152 break;
1153 case ZEBRA_NEXTHOP_IFINDEX:
1154 ifindex = stream_getl (s);
1155 break;
1156 }
1157 }
1158 }
1159
1160 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
1161 api.distance = stream_getc (s);
1162 else
1163 api.distance = 0;
1164 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
1165 api.metric = stream_getl (s);
1166 else
1167 api.metric = 0;
1168
1169 if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
f768f367 1170 rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi);
718e3744 1171 else
f768f367 1172 rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi);
719e9741 1173 return 0;
718e3744 1174}
1175
719e9741 1176static int
718e3744 1177zread_ipv6_nexthop_lookup (struct zserv *client, u_short length)
1178{
1179 struct in6_addr addr;
1180 char buf[BUFSIZ];
1181
1182 stream_get (&addr, client->ibuf, 16);
a5207089
CF
1183 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
1184 zlog_debug("%s: looking up %s", __func__,
1185 inet_ntop (AF_INET6, &addr, buf, BUFSIZ));
718e3744 1186
719e9741 1187 return zsend_ipv6_nexthop_lookup (client, &addr);
718e3744 1188}
1189#endif /* HAVE_IPV6 */
1190
18a6dce6 1191/* Register zebra server router-id information. Send current router-id */
719e9741 1192static int
18a6dce6 1193zread_router_id_add (struct zserv *client, u_short length)
1194{
1195 struct prefix p;
1196
1197 /* Router-id information is needed. */
1198 client->ridinfo = 1;
1199
1200 router_id_get (&p);
1201
719e9741 1202 return zsend_router_id_update (client,&p);
18a6dce6 1203}
1204
1205/* Unregister zebra server router-id information. */
719e9741 1206static int
18a6dce6 1207zread_router_id_delete (struct zserv *client, u_short length)
1208{
1209 client->ridinfo = 0;
719e9741 1210 return 0;
18a6dce6 1211}
1212
2ea1ab1c
VT
1213/* Tie up route-type and client->sock */
1214static void
1215zread_hello (struct zserv *client)
1216{
1217 /* type of protocol (lib/zebra.h) */
1218 u_char proto;
1219 proto = stream_getc (client->ibuf);
1220
1221 /* accept only dynamic routing protocols */
1222 if ((proto < ZEBRA_ROUTE_MAX)
1223 && (proto > ZEBRA_ROUTE_STATIC))
1224 {
1225 zlog_notice ("client %d says hello and bids fair to announce only %s routes",
1226 client->sock, zebra_route_string(proto));
1227
1228 /* if route-type was binded by other client */
1229 if (route_type_oaths[proto])
1230 zlog_warn ("sender of %s routes changed %c->%c",
1231 zebra_route_string(proto), route_type_oaths[proto],
1232 client->sock);
1233
1234 route_type_oaths[proto] = client->sock;
fb018d25 1235 client->proto = proto;
2ea1ab1c
VT
1236 }
1237}
1238
1239/* If client sent routes of specific type, zebra removes it
1240 * and returns number of deleted routes.
1241 */
1242static void
1243zebra_score_rib (int client_sock)
1244{
1245 int i;
1246
1247 for (i = ZEBRA_ROUTE_RIP; i < ZEBRA_ROUTE_MAX; i++)
1248 if (client_sock == route_type_oaths[i])
1249 {
1250 zlog_notice ("client %d disconnected. %lu %s routes removed from the rib",
1251 client_sock, rib_score_proto (i), zebra_route_string (i));
1252 route_type_oaths[i] = 0;
1253 break;
1254 }
1255}
1256
718e3744 1257/* Close zebra client. */
b9df2d25 1258static void
718e3744 1259zebra_client_close (struct zserv *client)
1260{
fb018d25
DS
1261 zebra_cleanup_rnh_client(0, AF_INET, client);
1262 zebra_cleanup_rnh_client(0, AF_INET6, client);
1263
718e3744 1264 /* Close file descriptor. */
1265 if (client->sock)
1266 {
1267 close (client->sock);
2ea1ab1c 1268 zebra_score_rib (client->sock);
718e3744 1269 client->sock = -1;
1270 }
1271
1272 /* Free stream buffers. */
1273 if (client->ibuf)
1274 stream_free (client->ibuf);
1275 if (client->obuf)
1276 stream_free (client->obuf);
719e9741 1277 if (client->wb)
1278 buffer_free(client->wb);
718e3744 1279
1280 /* Release threads. */
1281 if (client->t_read)
1282 thread_cancel (client->t_read);
1283 if (client->t_write)
1284 thread_cancel (client->t_write);
719e9741 1285 if (client->t_suicide)
1286 thread_cancel (client->t_suicide);
718e3744 1287
1288 /* Free client structure. */
b21b19c5 1289 listnode_delete (zebrad.client_list, client);
718e3744 1290 XFREE (0, client);
1291}
1292
1293/* Make new client. */
b9df2d25 1294static void
718e3744 1295zebra_client_create (int sock)
1296{
1297 struct zserv *client;
1298
1299 client = XCALLOC (0, sizeof (struct zserv));
1300
1301 /* Make client input/output buffer. */
1302 client->sock = sock;
1303 client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
1304 client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
719e9741 1305 client->wb = buffer_new(0);
718e3744 1306
1307 /* Set table number. */
b21b19c5 1308 client->rtm_table = zebrad.rtm_table_default;
718e3744 1309
1310 /* Add this client to linked list. */
b21b19c5 1311 listnode_add (zebrad.client_list, client);
718e3744 1312
1313 /* Make new read thread. */
1314 zebra_event (ZEBRA_READ, sock, client);
1315}
1316
1317/* Handler of zebra service request. */
b9df2d25 1318static int
718e3744 1319zebra_client_read (struct thread *thread)
1320{
1321 int sock;
1322 struct zserv *client;
57a1477b 1323 size_t already;
c1b9800a 1324 uint16_t length, command;
1325 uint8_t marker, version;
718e3744 1326
1327 /* Get thread data. Reset reading thread because I'm running. */
1328 sock = THREAD_FD (thread);
1329 client = THREAD_ARG (thread);
1330 client->t_read = NULL;
1331
719e9741 1332 if (client->t_suicide)
718e3744 1333 {
719e9741 1334 zebra_client_close(client);
718e3744 1335 return -1;
1336 }
719e9741 1337
1338 /* Read length and command (if we don't have it already). */
57a1477b 1339 if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE)
719e9741 1340 {
57a1477b 1341 ssize_t nbyte;
719e9741 1342 if (((nbyte = stream_read_try (client->ibuf, sock,
57a1477b 1343 ZEBRA_HEADER_SIZE-already)) == 0) ||
719e9741 1344 (nbyte == -1))
1345 {
1346 if (IS_ZEBRA_DEBUG_EVENT)
1347 zlog_debug ("connection closed socket [%d]", sock);
1348 zebra_client_close (client);
1349 return -1;
1350 }
57a1477b 1351 if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
719e9741 1352 {
1353 /* Try again later. */
1354 zebra_event (ZEBRA_READ, sock, client);
1355 return 0;
1356 }
57a1477b 1357 already = ZEBRA_HEADER_SIZE;
719e9741 1358 }
1359
1360 /* Reset to read from the beginning of the incoming packet. */
1361 stream_set_getp(client->ibuf, 0);
1362
c1b9800a 1363 /* Fetch header values */
718e3744 1364 length = stream_getw (client->ibuf);
c1b9800a 1365 marker = stream_getc (client->ibuf);
1366 version = stream_getc (client->ibuf);
1367 command = stream_getw (client->ibuf);
718e3744 1368
c1b9800a 1369 if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
1370 {
1371 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
1372 __func__, sock, marker, version);
1373 zebra_client_close (client);
1374 return -1;
1375 }
719e9741 1376 if (length < ZEBRA_HEADER_SIZE)
718e3744 1377 {
57a1477b 1378 zlog_warn("%s: socket %d message length %u is less than header size %d",
1379 __func__, sock, length, ZEBRA_HEADER_SIZE);
1380 zebra_client_close (client);
1381 return -1;
1382 }
1383 if (length > STREAM_SIZE(client->ibuf))
1384 {
1385 zlog_warn("%s: socket %d message length %u exceeds buffer size %lu",
1386 __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf));
718e3744 1387 zebra_client_close (client);
1388 return -1;
1389 }
1390
718e3744 1391 /* Read rest of data. */
57a1477b 1392 if (already < length)
718e3744 1393 {
57a1477b 1394 ssize_t nbyte;
1395 if (((nbyte = stream_read_try (client->ibuf, sock,
1396 length-already)) == 0) ||
1397 (nbyte == -1))
718e3744 1398 {
1399 if (IS_ZEBRA_DEBUG_EVENT)
b6178002 1400 zlog_debug ("connection closed [%d] when reading zebra data", sock);
718e3744 1401 zebra_client_close (client);
1402 return -1;
1403 }
57a1477b 1404 if (nbyte != (ssize_t)(length-already))
719e9741 1405 {
1406 /* Try again later. */
1407 zebra_event (ZEBRA_READ, sock, client);
1408 return 0;
1409 }
718e3744 1410 }
1411
719e9741 1412 length -= ZEBRA_HEADER_SIZE;
1413
718e3744 1414 /* Debug packet information. */
1415 if (IS_ZEBRA_DEBUG_EVENT)
b6178002 1416 zlog_debug ("zebra message comes from socket [%d]", sock);
718e3744 1417
1418 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
b6178002 1419 zlog_debug ("zebra message received [%s] %d",
66859780 1420 zserv_command_string (command), length);
718e3744 1421
1422 switch (command)
1423 {
18a6dce6 1424 case ZEBRA_ROUTER_ID_ADD:
1425 zread_router_id_add (client, length);
1426 break;
1427 case ZEBRA_ROUTER_ID_DELETE:
1428 zread_router_id_delete (client, length);
1429 break;
718e3744 1430 case ZEBRA_INTERFACE_ADD:
1431 zread_interface_add (client, length);
1432 break;
1433 case ZEBRA_INTERFACE_DELETE:
1434 zread_interface_delete (client, length);
1435 break;
1436 case ZEBRA_IPV4_ROUTE_ADD:
1437 zread_ipv4_add (client, length);
1438 break;
1439 case ZEBRA_IPV4_ROUTE_DELETE:
1440 zread_ipv4_delete (client, length);
1441 break;
1442#ifdef HAVE_IPV6
1443 case ZEBRA_IPV6_ROUTE_ADD:
1444 zread_ipv6_add (client, length);
1445 break;
1446 case ZEBRA_IPV6_ROUTE_DELETE:
1447 zread_ipv6_delete (client, length);
1448 break;
1449#endif /* HAVE_IPV6 */
1450 case ZEBRA_REDISTRIBUTE_ADD:
1451 zebra_redistribute_add (command, client, length);
1452 break;
1453 case ZEBRA_REDISTRIBUTE_DELETE:
1454 zebra_redistribute_delete (command, client, length);
1455 break;
1456 case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
1457 zebra_redistribute_default_add (command, client, length);
1458 break;
1459 case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
1460 zebra_redistribute_default_delete (command, client, length);
1461 break;
1462 case ZEBRA_IPV4_NEXTHOP_LOOKUP:
1463 zread_ipv4_nexthop_lookup (client, length);
1464 break;
1465#ifdef HAVE_IPV6
1466 case ZEBRA_IPV6_NEXTHOP_LOOKUP:
1467 zread_ipv6_nexthop_lookup (client, length);
1468 break;
1469#endif /* HAVE_IPV6 */
1470 case ZEBRA_IPV4_IMPORT_LOOKUP:
1471 zread_ipv4_import_lookup (client, length);
1472 break;
2ea1ab1c
VT
1473 case ZEBRA_HELLO:
1474 zread_hello (client);
1475 break;
fb018d25
DS
1476 case ZEBRA_NEXTHOP_REGISTER:
1477 zserv_nexthop_register(client, sock, length);
1478 break;
1479 case ZEBRA_NEXTHOP_UNREGISTER:
1480 zserv_nexthop_unregister(client, sock, length);
1481 break;
718e3744 1482 default:
1483 zlog_info ("Zebra received unknown command %d", command);
1484 break;
1485 }
1486
719e9741 1487 if (client->t_suicide)
1488 {
1489 /* No need to wait for thread callback, just kill immediately. */
1490 zebra_client_close(client);
1491 return -1;
1492 }
1493
718e3744 1494 stream_reset (client->ibuf);
1495 zebra_event (ZEBRA_READ, sock, client);
718e3744 1496 return 0;
1497}
1498
718e3744 1499
1500/* Accept code of zebra server socket. */
b9df2d25 1501static int
718e3744 1502zebra_accept (struct thread *thread)
1503{
1504 int accept_sock;
1505 int client_sock;
1506 struct sockaddr_in client;
1507 socklen_t len;
1508
1509 accept_sock = THREAD_FD (thread);
1510
719e9741 1511 /* Reregister myself. */
1512 zebra_event (ZEBRA_SERV, accept_sock, NULL);
1513
718e3744 1514 len = sizeof (struct sockaddr_in);
1515 client_sock = accept (accept_sock, (struct sockaddr *) &client, &len);
1516
1517 if (client_sock < 0)
1518 {
6099b3b5 1519 zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno));
718e3744 1520 return -1;
1521 }
1522
ccf3557b 1523 /* Make client socket non-blocking. */
719e9741 1524 set_nonblocking(client_sock);
865b852c 1525
718e3744 1526 /* Create new zebra client. */
1527 zebra_client_create (client_sock);
1528
718e3744 1529 return 0;
1530}
1531
b9df2d25 1532#ifdef HAVE_TCP_ZEBRA
718e3744 1533/* Make zebra's server socket. */
b9df2d25 1534static void
718e3744 1535zebra_serv ()
1536{
1537 int ret;
1538 int accept_sock;
1539 struct sockaddr_in addr;
1540
1541 accept_sock = socket (AF_INET, SOCK_STREAM, 0);
1542
1543 if (accept_sock < 0)
1544 {
3d1dc857 1545 zlog_warn ("Can't create zserv stream socket: %s",
1546 safe_strerror (errno));
718e3744 1547 zlog_warn ("zebra can't provice full functionality due to above error");
1548 return;
1549 }
1550
2ea1ab1c 1551 memset (&route_type_oaths, 0, sizeof (route_type_oaths));
718e3744 1552 memset (&addr, 0, sizeof (struct sockaddr_in));
1553 addr.sin_family = AF_INET;
1554 addr.sin_port = htons (ZEBRA_PORT);
6f0e3f6e 1555#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
718e3744 1556 addr.sin_len = sizeof (struct sockaddr_in);
6f0e3f6e 1557#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
718e3744 1558 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1559
1560 sockopt_reuseaddr (accept_sock);
1561 sockopt_reuseport (accept_sock);
1562
edd7c245 1563 if ( zserv_privs.change(ZPRIVS_RAISE) )
1564 zlog (NULL, LOG_ERR, "Can't raise privileges");
1565
718e3744 1566 ret = bind (accept_sock, (struct sockaddr *)&addr,
1567 sizeof (struct sockaddr_in));
1568 if (ret < 0)
1569 {
3d1dc857 1570 zlog_warn ("Can't bind to stream socket: %s",
1571 safe_strerror (errno));
718e3744 1572 zlog_warn ("zebra can't provice full functionality due to above error");
1573 close (accept_sock); /* Avoid sd leak. */
1574 return;
1575 }
edd7c245 1576
1577 if ( zserv_privs.change(ZPRIVS_LOWER) )
1578 zlog (NULL, LOG_ERR, "Can't lower privileges");
718e3744 1579
1580 ret = listen (accept_sock, 1);
1581 if (ret < 0)
1582 {
3d1dc857 1583 zlog_warn ("Can't listen to stream socket: %s",
1584 safe_strerror (errno));
718e3744 1585 zlog_warn ("zebra can't provice full functionality due to above error");
1586 close (accept_sock); /* Avoid sd leak. */
1587 return;
1588 }
1589
1590 zebra_event (ZEBRA_SERV, accept_sock, NULL);
1591}
b9df2d25 1592#endif /* HAVE_TCP_ZEBRA */
718e3744 1593
1594/* For sockaddr_un. */
1595#include <sys/un.h>
1596
1597/* zebra server UNIX domain socket. */
b9df2d25 1598static void
fce954f8 1599zebra_serv_un (const char *path)
718e3744 1600{
1601 int ret;
1602 int sock, len;
1603 struct sockaddr_un serv;
1604 mode_t old_mask;
1605
1606 /* First of all, unlink existing socket */
1607 unlink (path);
1608
1609 /* Set umask */
1610 old_mask = umask (0077);
1611
1612 /* Make UNIX domain socket. */
1613 sock = socket (AF_UNIX, SOCK_STREAM, 0);
1614 if (sock < 0)
1615 {
3d1dc857 1616 zlog_warn ("Can't create zserv unix socket: %s",
1617 safe_strerror (errno));
1618 zlog_warn ("zebra can't provide full functionality due to above error");
718e3744 1619 return;
1620 }
1621
2ea1ab1c
VT
1622 memset (&route_type_oaths, 0, sizeof (route_type_oaths));
1623
718e3744 1624 /* Make server socket. */
1625 memset (&serv, 0, sizeof (struct sockaddr_un));
1626 serv.sun_family = AF_UNIX;
1627 strncpy (serv.sun_path, path, strlen (path));
6f0e3f6e 1628#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
718e3744 1629 len = serv.sun_len = SUN_LEN(&serv);
1630#else
1631 len = sizeof (serv.sun_family) + strlen (serv.sun_path);
6f0e3f6e 1632#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
718e3744 1633
1634 ret = bind (sock, (struct sockaddr *) &serv, len);
1635 if (ret < 0)
1636 {
3d1dc857 1637 zlog_warn ("Can't bind to unix socket %s: %s",
1638 path, safe_strerror (errno));
1639 zlog_warn ("zebra can't provide full functionality due to above error");
718e3744 1640 close (sock);
1641 return;
1642 }
1643
1644 ret = listen (sock, 5);
1645 if (ret < 0)
1646 {
3d1dc857 1647 zlog_warn ("Can't listen to unix socket %s: %s",
1648 path, safe_strerror (errno));
1649 zlog_warn ("zebra can't provide full functionality due to above error");
718e3744 1650 close (sock);
1651 return;
1652 }
1653
1654 umask (old_mask);
1655
1656 zebra_event (ZEBRA_SERV, sock, NULL);
1657}
6b0655a2 1658
718e3744 1659
b9df2d25 1660static void
718e3744 1661zebra_event (enum event event, int sock, struct zserv *client)
1662{
1663 switch (event)
1664 {
1665 case ZEBRA_SERV:
b21b19c5 1666 thread_add_read (zebrad.master, zebra_accept, client, sock);
718e3744 1667 break;
1668 case ZEBRA_READ:
1669 client->t_read =
b21b19c5 1670 thread_add_read (zebrad.master, zebra_client_read, client, sock);
718e3744 1671 break;
1672 case ZEBRA_WRITE:
1673 /**/
1674 break;
1675 }
1676}
6b0655a2 1677
718e3744 1678/* Display default rtm_table for all clients. */
1679DEFUN (show_table,
1680 show_table_cmd,
1681 "show table",
1682 SHOW_STR
1683 "default routing table to use for all clients\n")
1684{
b21b19c5 1685 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
718e3744 1686 VTY_NEWLINE);
1687 return CMD_SUCCESS;
1688}
1689
1690DEFUN (config_table,
1691 config_table_cmd,
1692 "table TABLENO",
1693 "Configure target kernel routing table\n"
1694 "TABLE integer\n")
1695{
b21b19c5 1696 zebrad.rtm_table_default = strtol (argv[0], (char**)0, 10);
718e3744 1697 return CMD_SUCCESS;
1698}
1699
647e4f1f 1700DEFUN (ip_forwarding,
1701 ip_forwarding_cmd,
1702 "ip forwarding",
1703 IP_STR
1704 "Turn on IP forwarding")
1705{
1706 int ret;
1707
1708 ret = ipforward ();
b71f00f2 1709 if (ret == 0)
1710 ret = ipforward_on ();
647e4f1f 1711
647e4f1f 1712 if (ret == 0)
1713 {
1714 vty_out (vty, "Can't turn on IP forwarding%s", VTY_NEWLINE);
1715 return CMD_WARNING;
1716 }
1717
1718 return CMD_SUCCESS;
1719}
1720
718e3744 1721DEFUN (no_ip_forwarding,
1722 no_ip_forwarding_cmd,
1723 "no ip forwarding",
1724 NO_STR
1725 IP_STR
1726 "Turn off IP forwarding")
1727{
1728 int ret;
1729
1730 ret = ipforward ();
b71f00f2 1731 if (ret != 0)
1732 ret = ipforward_off ();
718e3744 1733
718e3744 1734 if (ret != 0)
1735 {
1736 vty_out (vty, "Can't turn off IP forwarding%s", VTY_NEWLINE);
1737 return CMD_WARNING;
1738 }
1739
1740 return CMD_SUCCESS;
1741}
1742
1743/* This command is for debugging purpose. */
1744DEFUN (show_zebra_client,
1745 show_zebra_client_cmd,
1746 "show zebra client",
1747 SHOW_STR
1748 "Zebra information"
1749 "Client information")
1750{
52dc7ee6 1751 struct listnode *node;
718e3744 1752 struct zserv *client;
1753
1eb8ef25 1754 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
fb018d25
DS
1755 vty_out (vty, "Client %s fd %d%s",
1756 zebra_route_string(client->proto), client->sock,
1757 VTY_NEWLINE);
1758
718e3744 1759 return CMD_SUCCESS;
1760}
1761
1762/* Table configuration write function. */
b9df2d25 1763static int
718e3744 1764config_write_table (struct vty *vty)
1765{
b21b19c5 1766 if (zebrad.rtm_table_default)
1767 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
718e3744 1768 VTY_NEWLINE);
1769 return 0;
1770}
1771
1772/* table node for routing tables. */
7fc626de 1773static struct cmd_node table_node =
718e3744 1774{
1775 TABLE_NODE,
1776 "", /* This node has no interface. */
1777 1
1778};
6b0655a2 1779
718e3744 1780/* Only display ip forwarding is enabled or not. */
1781DEFUN (show_ip_forwarding,
1782 show_ip_forwarding_cmd,
1783 "show ip forwarding",
1784 SHOW_STR
1785 IP_STR
1786 "IP forwarding status\n")
1787{
1788 int ret;
1789
1790 ret = ipforward ();
1791
1792 if (ret == 0)
1793 vty_out (vty, "IP forwarding is off%s", VTY_NEWLINE);
1794 else
1795 vty_out (vty, "IP forwarding is on%s", VTY_NEWLINE);
1796 return CMD_SUCCESS;
1797}
1798
1799#ifdef HAVE_IPV6
1800/* Only display ipv6 forwarding is enabled or not. */
1801DEFUN (show_ipv6_forwarding,
1802 show_ipv6_forwarding_cmd,
1803 "show ipv6 forwarding",
1804 SHOW_STR
1805 "IPv6 information\n"
1806 "Forwarding status\n")
1807{
1808 int ret;
1809
1810 ret = ipforward_ipv6 ();
1811
1812 switch (ret)
1813 {
1814 case -1:
1815 vty_out (vty, "ipv6 forwarding is unknown%s", VTY_NEWLINE);
1816 break;
1817 case 0:
1818 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
1819 break;
1820 case 1:
1821 vty_out (vty, "ipv6 forwarding is %s%s", "on", VTY_NEWLINE);
1822 break;
1823 default:
1824 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
1825 break;
1826 }
1827 return CMD_SUCCESS;
1828}
1829
55906724 1830DEFUN (ipv6_forwarding,
1831 ipv6_forwarding_cmd,
1832 "ipv6 forwarding",
1833 IPV6_STR
1834 "Turn on IPv6 forwarding")
1835{
1836 int ret;
1837
41d3fc96 1838 ret = ipforward_ipv6 ();
b71f00f2 1839 if (ret == 0)
1840 ret = ipforward_ipv6_on ();
41d3fc96 1841
41d3fc96 1842 if (ret == 0)
55906724 1843 {
1844 vty_out (vty, "Can't turn on IPv6 forwarding%s", VTY_NEWLINE);
1845 return CMD_WARNING;
1846 }
1847
1848 return CMD_SUCCESS;
1849}
1850
718e3744 1851DEFUN (no_ipv6_forwarding,
1852 no_ipv6_forwarding_cmd,
1853 "no ipv6 forwarding",
1854 NO_STR
55906724 1855 IPV6_STR
1856 "Turn off IPv6 forwarding")
718e3744 1857{
1858 int ret;
1859
41d3fc96 1860 ret = ipforward_ipv6 ();
b71f00f2 1861 if (ret != 0)
1862 ret = ipforward_ipv6_off ();
41d3fc96 1863
718e3744 1864 if (ret != 0)
1865 {
1866 vty_out (vty, "Can't turn off IPv6 forwarding%s", VTY_NEWLINE);
1867 return CMD_WARNING;
1868 }
1869
1870 return CMD_SUCCESS;
1871}
1872
1873#endif /* HAVE_IPV6 */
1874
1875/* IPForwarding configuration write function. */
719e9741 1876static int
718e3744 1877config_write_forwarding (struct vty *vty)
1878{
18a6dce6 1879 /* FIXME: Find better place for that. */
1880 router_id_write (vty);
1881
3e0b3a56 1882 if (ipforward ())
1883 vty_out (vty, "ip forwarding%s", VTY_NEWLINE);
718e3744 1884#ifdef HAVE_IPV6
3e0b3a56 1885 if (ipforward_ipv6 ())
1886 vty_out (vty, "ipv6 forwarding%s", VTY_NEWLINE);
718e3744 1887#endif /* HAVE_IPV6 */
1888 vty_out (vty, "!%s", VTY_NEWLINE);
1889 return 0;
1890}
1891
1892/* table node for routing tables. */
7fc626de 1893static struct cmd_node forwarding_node =
718e3744 1894{
1895 FORWARDING_NODE,
1896 "", /* This node has no interface. */
1897 1
1898};
1899
6b0655a2 1900
718e3744 1901/* Initialisation of zebra and installation of commands. */
1902void
a1ac18c4 1903zebra_init (void)
718e3744 1904{
1905 /* Client list init. */
b21b19c5 1906 zebrad.client_list = list_new ();
718e3744 1907
718e3744 1908 /* Install configuration write function. */
1909 install_node (&table_node, config_write_table);
1910 install_node (&forwarding_node, config_write_forwarding);
1911
1912 install_element (VIEW_NODE, &show_ip_forwarding_cmd);
1913 install_element (ENABLE_NODE, &show_ip_forwarding_cmd);
647e4f1f 1914 install_element (CONFIG_NODE, &ip_forwarding_cmd);
718e3744 1915 install_element (CONFIG_NODE, &no_ip_forwarding_cmd);
1916 install_element (ENABLE_NODE, &show_zebra_client_cmd);
1917
1918#ifdef HAVE_NETLINK
1919 install_element (VIEW_NODE, &show_table_cmd);
1920 install_element (ENABLE_NODE, &show_table_cmd);
1921 install_element (CONFIG_NODE, &config_table_cmd);
1922#endif /* HAVE_NETLINK */
1923
1924#ifdef HAVE_IPV6
1925 install_element (VIEW_NODE, &show_ipv6_forwarding_cmd);
1926 install_element (ENABLE_NODE, &show_ipv6_forwarding_cmd);
55906724 1927 install_element (CONFIG_NODE, &ipv6_forwarding_cmd);
718e3744 1928 install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
1929#endif /* HAVE_IPV6 */
7514fb77
PJ
1930
1931 /* Route-map */
1932 zebra_route_map_init ();
718e3744 1933}
97be79f9
DO
1934
1935/* Make zebra server socket, wiping any existing one (see bug #403). */
1936void
b5114685 1937zebra_zserv_socket_init (char *path)
97be79f9
DO
1938{
1939#ifdef HAVE_TCP_ZEBRA
1940 zebra_serv ();
1941#else
b5114685 1942 zebra_serv_un (path ? path : ZEBRA_SERV_PATH);
97be79f9
DO
1943#endif /* HAVE_TCP_ZEBRA */
1944}