blob: 23a5c4e84f837d30b2302c71011e4cf977b4d27e [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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"
pauledd7c242003-06-04 13:59:38 +000036#include "privs.h"
ajs719e9742005-02-28 20:52:15 +000037#include "network.h"
38#include "buffer.h"
paul718e3742002-12-13 20:15:29 +000039
40#include "zebra/zserv.h"
hasso18a6dce2004-10-03 18:18:34 +000041#include "zebra/router-id.h"
paul718e3742002-12-13 20:15:29 +000042#include "zebra/redistribute.h"
43#include "zebra/debug.h"
44#include "zebra/ipforward.h"
45
46/* Event list of zebra. */
47enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
48
paulb21b19c2003-06-15 01:28:29 +000049extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000050
paulb9df2d22004-05-09 09:09:59 +000051static void zebra_event (enum event event, int sock, struct zserv *client);
paulccf35572003-03-01 11:42:20 +000052
pauledd7c242003-06-04 13:59:38 +000053extern struct zebra_privs_t zserv_privs;
paul718e3742002-12-13 20:15:29 +000054
ajs719e9742005-02-28 20:52:15 +000055static void zebra_client_close (struct zserv *client);
56
57static int
58zserv_delayed_close(struct thread *thread)
paulccf35572003-03-01 11:42:20 +000059{
ajs719e9742005-02-28 20:52:15 +000060 struct zserv *client = THREAD_ARG(thread);
paulccf35572003-03-01 11:42:20 +000061
ajs719e9742005-02-28 20:52:15 +000062 client->t_suicide = NULL;
63 zebra_client_close(client);
paulccf35572003-03-01 11:42:20 +000064 return 0;
65}
66
ajs719e9742005-02-28 20:52:15 +000067static int
68zserv_flush_data(struct thread *thread)
paulccf35572003-03-01 11:42:20 +000069{
ajs719e9742005-02-28 20:52:15 +000070 struct zserv *client = THREAD_ARG(thread);
paulccf35572003-03-01 11:42:20 +000071
ajs719e9742005-02-28 20:52:15 +000072 client->t_write = NULL;
73 if (client->t_suicide)
74 {
75 zebra_client_close(client);
76 return -1;
77 }
78 switch (buffer_flush_available(client->wb, client->sock))
79 {
80 case BUFFER_ERROR:
81 zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, "
82 "closing", __func__, client->sock);
83 zebra_client_close(client);
84 break;
85 case BUFFER_PENDING:
86 client->t_write = thread_add_write(zebrad.master, zserv_flush_data,
87 client, client->sock);
88 break;
89 case BUFFER_EMPTY:
90 break;
91 }
92 return 0;
paulccf35572003-03-01 11:42:20 +000093}
94
ajs719e9742005-02-28 20:52:15 +000095static int
96zebra_server_send_message(struct zserv *client)
paulccf35572003-03-01 11:42:20 +000097{
ajs719e9742005-02-28 20:52:15 +000098 if (client->t_suicide)
99 return -1;
100 switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf),
101 stream_get_endp(client->obuf)))
paulccf35572003-03-01 11:42:20 +0000102 {
ajs719e9742005-02-28 20:52:15 +0000103 case BUFFER_ERROR:
104 zlog_warn("%s: buffer_write failed to zserv client fd %d, closing",
105 __func__, client->sock);
106 /* Schedule a delayed close since many of the functions that call this
107 one do not check the return code. They do not allow for the
108 possibility that an I/O error may have caused the client to be
109 deleted. */
110 client->t_suicide = thread_add_event(zebrad.master, zserv_delayed_close,
111 client, 0);
112 return -1;
ajs719e9742005-02-28 20:52:15 +0000113 case BUFFER_EMPTY:
114 THREAD_OFF(client->t_write);
115 break;
116 case BUFFER_PENDING:
117 THREAD_WRITE_ON(zebrad.master, client->t_write,
118 zserv_flush_data, client, client->sock);
119 break;
paulccf35572003-03-01 11:42:20 +0000120 }
paulccf35572003-03-01 11:42:20 +0000121 return 0;
122}
123
paulc1b98002006-01-16 01:54:02 +0000124static void
125zserv_create_header (struct stream *s, uint16_t cmd)
126{
127 /* length placeholder, caller can update */
128 stream_putw (s, ZEBRA_HEADER_SIZE);
129 stream_putc (s, ZEBRA_HEADER_MARKER);
130 stream_putc (s, ZSERV_VERSION);
131 stream_putw (s, cmd);
132}
133
Josh Bailey51d4ef82012-03-21 17:13:39 -0700134static void
135zserv_encode_interface (struct stream *s, struct interface *ifp)
136{
137 /* Interface information. */
138 stream_put (s, ifp->name, INTERFACE_NAMSIZ);
139 stream_putl (s, ifp->ifindex);
140 stream_putc (s, ifp->status);
141 stream_putq (s, ifp->flags);
142 stream_putl (s, ifp->metric);
143 stream_putl (s, ifp->mtu);
144 stream_putl (s, ifp->mtu6);
145 stream_putl (s, ifp->bandwidth);
146#ifdef HAVE_STRUCT_SOCKADDR_DL
147 stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
148#else
149 stream_putl (s, ifp->hw_addr_len);
150 if (ifp->hw_addr_len)
151 stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
152#endif /* HAVE_STRUCT_SOCKADDR_DL */
153
154 /* Write packet size. */
155 stream_putw_at (s, 0, stream_get_endp (s));
156}
157
paul718e3742002-12-13 20:15:29 +0000158/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
paulb9df2d22004-05-09 09:09:59 +0000159/*
160 * This function is called in the following situations:
161 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
162 * from the client.
163 * - at startup, when zebra figures out the available interfaces
164 * - when an interface is added (where support for
165 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
166 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
167 * received)
168 */
paul718e3742002-12-13 20:15:29 +0000169int
170zsend_interface_add (struct zserv *client, struct interface *ifp)
171{
172 struct stream *s;
173
174 /* Check this client need interface information. */
175 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000176 return 0;
paul718e3742002-12-13 20:15:29 +0000177
178 s = client->obuf;
179 stream_reset (s);
180
paulc1b98002006-01-16 01:54:02 +0000181 zserv_create_header (s, ZEBRA_INTERFACE_ADD);
Josh Bailey51d4ef82012-03-21 17:13:39 -0700182 zserv_encode_interface (s, ifp);
paul718e3742002-12-13 20:15:29 +0000183
ajs719e9742005-02-28 20:52:15 +0000184 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000185}
186
187/* Interface deletion from zebra daemon. */
188int
189zsend_interface_delete (struct zserv *client, struct interface *ifp)
190{
191 struct stream *s;
192
193 /* Check this client need interface information. */
194 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000195 return 0;
paul718e3742002-12-13 20:15:29 +0000196
197 s = client->obuf;
198 stream_reset (s);
paul718e3742002-12-13 20:15:29 +0000199
Josh Bailey51d4ef82012-03-21 17:13:39 -0700200 zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
201 zserv_encode_interface (s, ifp);
paul718e3742002-12-13 20:15:29 +0000202
ajs719e9742005-02-28 20:52:15 +0000203 return zebra_server_send_message (client);
paul718e3742002-12-13 20:15:29 +0000204}
205
paulb9df2d22004-05-09 09:09:59 +0000206/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
207 * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
208 *
209 * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
210 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
211 * from the client, after the ZEBRA_INTERFACE_ADD has been
212 * sent from zebra to the client
213 * - redistribute new address info to all clients in the following situations
214 * - at startup, when zebra figures out the available interfaces
215 * - when an interface is added (where support for
216 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
217 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
218 * received)
219 * - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
220 * and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
221 * - when an RTM_NEWADDR message is received from the kernel,
222 *
223 * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:
224 *
225 * zsend_interface_address(DELETE)
226 * ^
227 * |
228 * zebra_interface_address_delete_update
229 * ^ ^ ^
paul6eb88272005-07-29 14:36:00 +0000230 * | | if_delete_update
231 * | |
paulb9df2d22004-05-09 09:09:59 +0000232 * ip_address_uninstall connected_delete_ipv4
233 * [ipv6_addresss_uninstall] [connected_delete_ipv6]
234 * ^ ^
235 * | |
236 * | RTM_NEWADDR on routing/netlink socket
237 * |
238 * vty commands:
239 * "no ip address A.B.C.D/M [label LINE]"
240 * "no ip address A.B.C.D/M secondary"
241 * ["no ipv6 address X:X::X:X/M"]
242 *
243 */
paul718e3742002-12-13 20:15:29 +0000244int
paulb9df2d22004-05-09 09:09:59 +0000245zsend_interface_address (int cmd, struct zserv *client,
246 struct interface *ifp, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +0000247{
248 int blen;
249 struct stream *s;
250 struct prefix *p;
251
252 /* Check this client need interface information. */
253 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000254 return 0;
paul718e3742002-12-13 20:15:29 +0000255
256 s = client->obuf;
257 stream_reset (s);
paulc1b98002006-01-16 01:54:02 +0000258
259 zserv_create_header (s, cmd);
paul718e3742002-12-13 20:15:29 +0000260 stream_putl (s, ifp->ifindex);
261
262 /* Interface address flag. */
263 stream_putc (s, ifc->flags);
264
265 /* Prefix information. */
266 p = ifc->address;
267 stream_putc (s, p->family);
268 blen = prefix_blen (p);
269 stream_put (s, &p->u.prefix, blen);
paulb9df2d22004-05-09 09:09:59 +0000270
271 /*
272 * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE
273 * but zebra_interface_address_delete_read() in the gnu version
274 * expects to find it
275 */
paul718e3742002-12-13 20:15:29 +0000276 stream_putc (s, p->prefixlen);
277
278 /* Destination. */
279 p = ifc->destination;
280 if (p)
281 stream_put (s, &p->u.prefix, blen);
282 else
283 stream_put (s, NULL, blen);
284
285 /* Write packet size. */
286 stream_putw_at (s, 0, stream_get_endp (s));
287
ajs719e9742005-02-28 20:52:15 +0000288 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000289}
290
paulb9df2d22004-05-09 09:09:59 +0000291/*
292 * The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or
293 * ZEBRA_INTERFACE_DOWN.
294 *
295 * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
296 * the clients in one of 2 situations:
297 * - an if_up is detected e.g., as a result of an RTM_IFINFO message
298 * - a vty command modifying the bandwidth of an interface is received.
299 * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
300 */
paul718e3742002-12-13 20:15:29 +0000301int
paulb9df2d22004-05-09 09:09:59 +0000302zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000303{
304 struct stream *s;
305
306 /* Check this client need interface information. */
307 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000308 return 0;
paul718e3742002-12-13 20:15:29 +0000309
310 s = client->obuf;
311 stream_reset (s);
312
paulc1b98002006-01-16 01:54:02 +0000313 zserv_create_header (s, cmd);
Josh Bailey51d4ef82012-03-21 17:13:39 -0700314 zserv_encode_interface (s, ifp);
paul718e3742002-12-13 20:15:29 +0000315
ajs719e9742005-02-28 20:52:15 +0000316 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000317}
318
paulb9df2d22004-05-09 09:09:59 +0000319/*
320 * The zebra server sends the clients a ZEBRA_IPV4_ROUTE_ADD or a
321 * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following
322 * situations:
323 * - when the client starts up, and requests default information
324 * by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the
325 * - case of rip, ripngd, ospfd and ospf6d, when the client sends a
326 * ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd,
327 * - when the zebra server redistributes routes after it updates its rib
328 *
329 * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a
330 * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when:
331 * - a "ip route" or "ipv6 route" vty command is issued, a prefix is
332 * - deleted from zebra's rib, and this info
333 * has to be redistributed to the clients
334 *
335 * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the
336 * zebra server when the client wants to tell the zebra server to add a
337 * route to the kernel (zapi_ipv4_add etc. ). Since it's essentially the
338 * same message being sent back and forth, this function and
339 * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code
340 * duplication.
341 */
paul718e3742002-12-13 20:15:29 +0000342int
paulb9df2d22004-05-09 09:09:59 +0000343zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
344 struct rib *rib)
paul718e3742002-12-13 20:15:29 +0000345{
346 int psize;
347 struct stream *s;
348 struct nexthop *nexthop;
paul1dcb5172005-05-31 08:38:50 +0000349 unsigned long nhnummark = 0, messmark = 0;
paulb9df2d22004-05-09 09:09:59 +0000350 int nhnum = 0;
paul1dcb5172005-05-31 08:38:50 +0000351 u_char zapi_flags = 0;
paulb9df2d22004-05-09 09:09:59 +0000352
paul718e3742002-12-13 20:15:29 +0000353 s = client->obuf;
354 stream_reset (s);
paulc1b98002006-01-16 01:54:02 +0000355
356 zserv_create_header (s, cmd);
357
358 /* Put type and nexthop. */
paul718e3742002-12-13 20:15:29 +0000359 stream_putc (s, rib->type);
360 stream_putc (s, rib->flags);
paul1dcb5172005-05-31 08:38:50 +0000361
362 /* marker for message flags field */
363 messmark = stream_get_endp (s);
364 stream_putc (s, 0);
paul718e3742002-12-13 20:15:29 +0000365
366 /* Prefix. */
367 psize = PSIZE (p->prefixlen);
368 stream_putc (s, p->prefixlen);
paulb9df2d22004-05-09 09:09:59 +0000369 stream_write (s, (u_char *) & p->u.prefix, psize);
paul718e3742002-12-13 20:15:29 +0000370
paulb9df2d22004-05-09 09:09:59 +0000371 /*
372 * XXX The message format sent by zebra below does not match the format
373 * of the corresponding message expected by the zebra server
374 * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly,
375 * (is there a bug on the client side if more than one segment is sent?)
376 * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX
377 * is hard-coded.
378 */
paul718e3742002-12-13 20:15:29 +0000379 /* Nexthop */
paul1dcb5172005-05-31 08:38:50 +0000380
paul718e3742002-12-13 20:15:29 +0000381 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
382 {
383 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paulb9df2d22004-05-09 09:09:59 +0000384 {
paul1dcb5172005-05-31 08:38:50 +0000385 SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
386 SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
387
388 if (nhnummark == 0)
389 {
390 nhnummark = stream_get_endp (s);
391 stream_putc (s, 1); /* placeholder */
392 }
393
paulb9df2d22004-05-09 09:09:59 +0000394 nhnum++;
paul718e3742002-12-13 20:15:29 +0000395
paulb9df2d22004-05-09 09:09:59 +0000396 switch(nexthop->type)
397 {
398 case NEXTHOP_TYPE_IPV4:
399 case NEXTHOP_TYPE_IPV4_IFINDEX:
400 stream_put_in_addr (s, &nexthop->gate.ipv4);
401 break;
402#ifdef HAVE_IPV6
403 case NEXTHOP_TYPE_IPV6:
404 case NEXTHOP_TYPE_IPV6_IFINDEX:
405 case NEXTHOP_TYPE_IPV6_IFNAME:
406 stream_write (s, (u_char *) &nexthop->gate.ipv6, 16);
407 break;
408#endif
409 default:
410 if (cmd == ZEBRA_IPV4_ROUTE_ADD
411 || cmd == ZEBRA_IPV4_ROUTE_DELETE)
412 {
413 struct in_addr empty;
paul44983cf2004-09-22 13:15:58 +0000414 memset (&empty, 0, sizeof (struct in_addr));
paulb9df2d22004-05-09 09:09:59 +0000415 stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN);
416 }
417 else
418 {
419 struct in6_addr empty;
420 memset (&empty, 0, sizeof (struct in6_addr));
421 stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN);
422 }
423 }
paul718e3742002-12-13 20:15:29 +0000424
paulb9df2d22004-05-09 09:09:59 +0000425 /* Interface index. */
426 stream_putc (s, 1);
427 stream_putl (s, nexthop->ifindex);
paul718e3742002-12-13 20:15:29 +0000428
paulb9df2d22004-05-09 09:09:59 +0000429 break;
430 }
paul718e3742002-12-13 20:15:29 +0000431 }
432
433 /* Metric */
Stephen Hemmingercf8a8312010-08-18 15:56:46 -0700434 if (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV6_ROUTE_ADD)
paul1dcb5172005-05-31 08:38:50 +0000435 {
vincentfbf5d032005-09-29 11:25:50 +0000436 SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE);
437 stream_putc (s, rib->distance);
paul1dcb5172005-05-31 08:38:50 +0000438 SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC);
439 stream_putl (s, rib->metric);
440 }
441
442 /* write real message flags value */
443 stream_putc_at (s, messmark, zapi_flags);
444
paulb9df2d22004-05-09 09:09:59 +0000445 /* Write next-hop number */
446 if (nhnummark)
hassoc1eaa442004-10-19 06:26:01 +0000447 stream_putc_at (s, nhnummark, nhnum);
paulb9df2d22004-05-09 09:09:59 +0000448
paul718e3742002-12-13 20:15:29 +0000449 /* Write packet size. */
450 stream_putw_at (s, 0, stream_get_endp (s));
451
ajs719e9742005-02-28 20:52:15 +0000452 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000453}
454
paul718e3742002-12-13 20:15:29 +0000455#ifdef HAVE_IPV6
ajs719e9742005-02-28 20:52:15 +0000456static int
paul718e3742002-12-13 20:15:29 +0000457zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr)
458{
459 struct stream *s;
460 struct rib *rib;
461 unsigned long nump;
462 u_char num;
463 struct nexthop *nexthop;
464
465 /* Lookup nexthop. */
466 rib = rib_match_ipv6 (addr);
467
468 /* Get output stream. */
469 s = client->obuf;
470 stream_reset (s);
471
472 /* Fill in result. */
paulc1b98002006-01-16 01:54:02 +0000473 zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
paul718e3742002-12-13 20:15:29 +0000474 stream_put (s, &addr, 16);
475
476 if (rib)
477 {
478 stream_putl (s, rib->metric);
479 num = 0;
paul9985f832005-02-09 15:51:56 +0000480 nump = stream_get_endp(s);
paul718e3742002-12-13 20:15:29 +0000481 stream_putc (s, 0);
482 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
483 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
484 {
485 stream_putc (s, nexthop->type);
486 switch (nexthop->type)
487 {
488 case ZEBRA_NEXTHOP_IPV6:
489 stream_put (s, &nexthop->gate.ipv6, 16);
490 break;
491 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
492 case ZEBRA_NEXTHOP_IPV6_IFNAME:
493 stream_put (s, &nexthop->gate.ipv6, 16);
494 stream_putl (s, nexthop->ifindex);
495 break;
496 case ZEBRA_NEXTHOP_IFINDEX:
497 case ZEBRA_NEXTHOP_IFNAME:
498 stream_putl (s, nexthop->ifindex);
499 break;
hassofa2b17e2004-03-04 17:45:00 +0000500 default:
501 /* do nothing */
502 break;
paul718e3742002-12-13 20:15:29 +0000503 }
504 num++;
505 }
506 stream_putc_at (s, nump, num);
507 }
508 else
509 {
510 stream_putl (s, 0);
511 stream_putc (s, 0);
512 }
513
514 stream_putw_at (s, 0, stream_get_endp (s));
515
ajs719e9742005-02-28 20:52:15 +0000516 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000517}
518#endif /* HAVE_IPV6 */
519
paulb9df2d22004-05-09 09:09:59 +0000520static int
paul718e3742002-12-13 20:15:29 +0000521zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
522{
523 struct stream *s;
524 struct rib *rib;
525 unsigned long nump;
526 u_char num;
527 struct nexthop *nexthop;
528
529 /* Lookup nexthop. */
530 rib = rib_match_ipv4 (addr);
531
532 /* Get output stream. */
533 s = client->obuf;
534 stream_reset (s);
535
536 /* Fill in result. */
paulc1b98002006-01-16 01:54:02 +0000537 zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
paul718e3742002-12-13 20:15:29 +0000538 stream_put_in_addr (s, &addr);
539
540 if (rib)
541 {
542 stream_putl (s, rib->metric);
543 num = 0;
paul9985f832005-02-09 15:51:56 +0000544 nump = stream_get_endp(s);
paul718e3742002-12-13 20:15:29 +0000545 stream_putc (s, 0);
546 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
547 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
548 {
549 stream_putc (s, nexthop->type);
550 switch (nexthop->type)
551 {
552 case ZEBRA_NEXTHOP_IPV4:
553 stream_put_in_addr (s, &nexthop->gate.ipv4);
554 break;
555 case ZEBRA_NEXTHOP_IFINDEX:
556 case ZEBRA_NEXTHOP_IFNAME:
557 stream_putl (s, nexthop->ifindex);
558 break;
hassofa2b17e2004-03-04 17:45:00 +0000559 default:
560 /* do nothing */
561 break;
paul718e3742002-12-13 20:15:29 +0000562 }
563 num++;
564 }
565 stream_putc_at (s, nump, num);
566 }
567 else
568 {
569 stream_putl (s, 0);
570 stream_putc (s, 0);
571 }
572
573 stream_putw_at (s, 0, stream_get_endp (s));
574
ajs719e9742005-02-28 20:52:15 +0000575 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000576}
577
paulb9df2d22004-05-09 09:09:59 +0000578static int
paul718e3742002-12-13 20:15:29 +0000579zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
580{
581 struct stream *s;
582 struct rib *rib;
583 unsigned long nump;
584 u_char num;
585 struct nexthop *nexthop;
586
587 /* Lookup nexthop. */
588 rib = rib_lookup_ipv4 (p);
589
590 /* Get output stream. */
591 s = client->obuf;
592 stream_reset (s);
593
594 /* Fill in result. */
paulc1b98002006-01-16 01:54:02 +0000595 zserv_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
paul718e3742002-12-13 20:15:29 +0000596 stream_put_in_addr (s, &p->prefix);
597
598 if (rib)
599 {
600 stream_putl (s, rib->metric);
601 num = 0;
paul9985f832005-02-09 15:51:56 +0000602 nump = stream_get_endp(s);
paul718e3742002-12-13 20:15:29 +0000603 stream_putc (s, 0);
604 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
605 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
606 {
607 stream_putc (s, nexthop->type);
608 switch (nexthop->type)
609 {
610 case ZEBRA_NEXTHOP_IPV4:
611 stream_put_in_addr (s, &nexthop->gate.ipv4);
612 break;
613 case ZEBRA_NEXTHOP_IFINDEX:
614 case ZEBRA_NEXTHOP_IFNAME:
615 stream_putl (s, nexthop->ifindex);
616 break;
hassofa2b17e2004-03-04 17:45:00 +0000617 default:
618 /* do nothing */
619 break;
paul718e3742002-12-13 20:15:29 +0000620 }
621 num++;
622 }
623 stream_putc_at (s, nump, num);
624 }
625 else
626 {
627 stream_putl (s, 0);
628 stream_putc (s, 0);
629 }
630
631 stream_putw_at (s, 0, stream_get_endp (s));
632
ajs719e9742005-02-28 20:52:15 +0000633 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000634}
635
hasso18a6dce2004-10-03 18:18:34 +0000636/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
637int
638zsend_router_id_update (struct zserv *client, struct prefix *p)
639{
640 struct stream *s;
641 int blen;
642
643 /* Check this client need interface information. */
644 if (!client->ridinfo)
ajs719e9742005-02-28 20:52:15 +0000645 return 0;
hasso18a6dce2004-10-03 18:18:34 +0000646
647 s = client->obuf;
648 stream_reset (s);
649
hasso18a6dce2004-10-03 18:18:34 +0000650 /* Message type. */
paulc1b98002006-01-16 01:54:02 +0000651 zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE);
hasso18a6dce2004-10-03 18:18:34 +0000652
653 /* Prefix information. */
654 stream_putc (s, p->family);
655 blen = prefix_blen (p);
656 stream_put (s, &p->u.prefix, blen);
657 stream_putc (s, p->prefixlen);
658
659 /* Write packet size. */
660 stream_putw_at (s, 0, stream_get_endp (s));
661
ajs719e9742005-02-28 20:52:15 +0000662 return zebra_server_send_message(client);
hasso18a6dce2004-10-03 18:18:34 +0000663}
664
paul718e3742002-12-13 20:15:29 +0000665/* Register zebra server interface information. Send current all
666 interface and address information. */
ajs719e9742005-02-28 20:52:15 +0000667static int
paul718e3742002-12-13 20:15:29 +0000668zread_interface_add (struct zserv *client, u_short length)
669{
paul1eb8ef22005-04-07 07:30:20 +0000670 struct listnode *ifnode, *ifnnode;
671 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000672 struct interface *ifp;
673 struct connected *c;
674
675 /* Interface information is needed. */
676 client->ifinfo = 1;
677
paul1eb8ef22005-04-07 07:30:20 +0000678 for (ALL_LIST_ELEMENTS (iflist, ifnode, ifnnode, ifp))
paul718e3742002-12-13 20:15:29 +0000679 {
paul718e3742002-12-13 20:15:29 +0000680 /* Skip pseudo interface. */
681 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
682 continue;
683
ajs719e9742005-02-28 20:52:15 +0000684 if (zsend_interface_add (client, ifp) < 0)
685 return -1;
paul718e3742002-12-13 20:15:29 +0000686
paul1eb8ef22005-04-07 07:30:20 +0000687 for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
paul718e3742002-12-13 20:15:29 +0000688 {
ajs719e9742005-02-28 20:52:15 +0000689 if (CHECK_FLAG (c->conf, ZEBRA_IFC_REAL) &&
690 (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client,
691 ifp, c) < 0))
692 return -1;
paul718e3742002-12-13 20:15:29 +0000693 }
694 }
ajs719e9742005-02-28 20:52:15 +0000695 return 0;
paul718e3742002-12-13 20:15:29 +0000696}
697
698/* Unregister zebra server interface information. */
ajs719e9742005-02-28 20:52:15 +0000699static int
paul718e3742002-12-13 20:15:29 +0000700zread_interface_delete (struct zserv *client, u_short length)
701{
702 client->ifinfo = 0;
ajs719e9742005-02-28 20:52:15 +0000703 return 0;
paul718e3742002-12-13 20:15:29 +0000704}
705
706/* This function support multiple nexthop. */
paulb9df2d22004-05-09 09:09:59 +0000707/*
708 * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
709 * add kernel route.
710 */
ajs719e9742005-02-28 20:52:15 +0000711static int
paul718e3742002-12-13 20:15:29 +0000712zread_ipv4_add (struct zserv *client, u_short length)
713{
714 int i;
715 struct rib *rib;
716 struct prefix_ipv4 p;
717 u_char message;
718 struct in_addr nexthop;
719 u_char nexthop_num;
720 u_char nexthop_type;
721 struct stream *s;
722 unsigned int ifindex;
723 u_char ifname_len;
724
725 /* Get input stream. */
726 s = client->ibuf;
727
728 /* Allocate new rib. */
paul4d38fdb2005-04-28 17:35:14 +0000729 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
730
paul718e3742002-12-13 20:15:29 +0000731 /* Type, flags, message. */
732 rib->type = stream_getc (s);
Josh Baileyaf56d402012-03-21 18:47:51 -0700733 /* Update client's route type if it is not done yet. */
734 /* It is done here since only zread_ipv4/6_add() and
735 * zread_ipv4/6_delete() decode Zebra messages and retrieve
736 * route types. */
737 if (client->route_type == ZEBRA_ROUTE_MAX)
738 client->route_type = rib->type;
739
paul718e3742002-12-13 20:15:29 +0000740 rib->flags = stream_getc (s);
paulb9df2d22004-05-09 09:09:59 +0000741 message = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000742 rib->uptime = time (NULL);
743
744 /* IPv4 prefix. */
745 memset (&p, 0, sizeof (struct prefix_ipv4));
746 p.family = AF_INET;
747 p.prefixlen = stream_getc (s);
748 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
749
750 /* Nexthop parse. */
751 if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
752 {
753 nexthop_num = stream_getc (s);
754
755 for (i = 0; i < nexthop_num; i++)
756 {
757 nexthop_type = stream_getc (s);
758
759 switch (nexthop_type)
760 {
761 case ZEBRA_NEXTHOP_IFINDEX:
762 ifindex = stream_getl (s);
763 nexthop_ifindex_add (rib, ifindex);
764 break;
765 case ZEBRA_NEXTHOP_IFNAME:
766 ifname_len = stream_getc (s);
paul9985f832005-02-09 15:51:56 +0000767 stream_forward_getp (s, ifname_len);
paul718e3742002-12-13 20:15:29 +0000768 break;
769 case ZEBRA_NEXTHOP_IPV4:
770 nexthop.s_addr = stream_get_ipv4 (s);
Paul Jakma7514fb72007-05-02 16:05:35 +0000771 nexthop_ipv4_add (rib, &nexthop, NULL);
paul718e3742002-12-13 20:15:29 +0000772 break;
773 case ZEBRA_NEXTHOP_IPV6:
paul9985f832005-02-09 15:51:56 +0000774 stream_forward_getp (s, IPV6_MAX_BYTELEN);
paul718e3742002-12-13 20:15:29 +0000775 break;
Subbaiah Venkata6902c692012-03-27 19:21:29 -0700776 case ZEBRA_NEXTHOP_BLACKHOLE:
777 nexthop_blackhole_add (rib);
778 break;
779 }
paul718e3742002-12-13 20:15:29 +0000780 }
781 }
782
783 /* Distance. */
784 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
785 rib->distance = stream_getc (s);
786
787 /* Metric. */
788 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
789 rib->metric = stream_getl (s);
790
Paul Jakma171eee32006-07-27 16:11:02 +0000791 /* Table */
792 rib->table=zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +0000793 rib_add_ipv4_multipath (&p, rib);
ajs719e9742005-02-28 20:52:15 +0000794 return 0;
paul718e3742002-12-13 20:15:29 +0000795}
796
797/* Zebra server IPv4 prefix delete function. */
ajs719e9742005-02-28 20:52:15 +0000798static int
paul718e3742002-12-13 20:15:29 +0000799zread_ipv4_delete (struct zserv *client, u_short length)
800{
801 int i;
802 struct stream *s;
803 struct zapi_ipv4 api;
Subbaiah Venkata6902c692012-03-27 19:21:29 -0700804 struct in_addr nexthop, *nexthop_p;
paul718e3742002-12-13 20:15:29 +0000805 unsigned long ifindex;
806 struct prefix_ipv4 p;
807 u_char nexthop_num;
808 u_char nexthop_type;
809 u_char ifname_len;
810
811 s = client->ibuf;
812 ifindex = 0;
813 nexthop.s_addr = 0;
Subbaiah Venkata6902c692012-03-27 19:21:29 -0700814 nexthop_p = NULL;
paul718e3742002-12-13 20:15:29 +0000815
816 /* Type, flags, message. */
817 api.type = stream_getc (s);
818 api.flags = stream_getc (s);
819 api.message = stream_getc (s);
820
821 /* IPv4 prefix. */
822 memset (&p, 0, sizeof (struct prefix_ipv4));
823 p.family = AF_INET;
824 p.prefixlen = stream_getc (s);
825 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
826
827 /* Nexthop, ifindex, distance, metric. */
828 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
829 {
830 nexthop_num = stream_getc (s);
831
832 for (i = 0; i < nexthop_num; i++)
833 {
834 nexthop_type = stream_getc (s);
835
836 switch (nexthop_type)
837 {
838 case ZEBRA_NEXTHOP_IFINDEX:
839 ifindex = stream_getl (s);
840 break;
841 case ZEBRA_NEXTHOP_IFNAME:
842 ifname_len = stream_getc (s);
paul9985f832005-02-09 15:51:56 +0000843 stream_forward_getp (s, ifname_len);
paul718e3742002-12-13 20:15:29 +0000844 break;
845 case ZEBRA_NEXTHOP_IPV4:
846 nexthop.s_addr = stream_get_ipv4 (s);
Subbaiah Venkata6902c692012-03-27 19:21:29 -0700847 nexthop_p = &nexthop;
paul718e3742002-12-13 20:15:29 +0000848 break;
849 case ZEBRA_NEXTHOP_IPV6:
paul9985f832005-02-09 15:51:56 +0000850 stream_forward_getp (s, IPV6_MAX_BYTELEN);
paul718e3742002-12-13 20:15:29 +0000851 break;
852 }
853 }
854 }
855
856 /* Distance. */
857 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
858 api.distance = stream_getc (s);
859 else
860 api.distance = 0;
861
862 /* Metric. */
863 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
864 api.metric = stream_getl (s);
865 else
866 api.metric = 0;
867
Subbaiah Venkata6902c692012-03-27 19:21:29 -0700868 rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex,
paul718e3742002-12-13 20:15:29 +0000869 client->rtm_table);
ajs719e9742005-02-28 20:52:15 +0000870 return 0;
paul718e3742002-12-13 20:15:29 +0000871}
872
873/* Nexthop lookup for IPv4. */
ajs719e9742005-02-28 20:52:15 +0000874static int
paul718e3742002-12-13 20:15:29 +0000875zread_ipv4_nexthop_lookup (struct zserv *client, u_short length)
876{
877 struct in_addr addr;
878
879 addr.s_addr = stream_get_ipv4 (client->ibuf);
ajs719e9742005-02-28 20:52:15 +0000880 return zsend_ipv4_nexthop_lookup (client, addr);
paul718e3742002-12-13 20:15:29 +0000881}
882
883/* Nexthop lookup for IPv4. */
ajs719e9742005-02-28 20:52:15 +0000884static int
paul718e3742002-12-13 20:15:29 +0000885zread_ipv4_import_lookup (struct zserv *client, u_short length)
886{
887 struct prefix_ipv4 p;
888
889 p.family = AF_INET;
890 p.prefixlen = stream_getc (client->ibuf);
891 p.prefix.s_addr = stream_get_ipv4 (client->ibuf);
892
ajs719e9742005-02-28 20:52:15 +0000893 return zsend_ipv4_import_lookup (client, &p);
paul718e3742002-12-13 20:15:29 +0000894}
895
896#ifdef HAVE_IPV6
897/* Zebra server IPv6 prefix add function. */
ajs719e9742005-02-28 20:52:15 +0000898static int
paul718e3742002-12-13 20:15:29 +0000899zread_ipv6_add (struct zserv *client, u_short length)
900{
901 int i;
902 struct stream *s;
903 struct zapi_ipv6 api;
904 struct in6_addr nexthop;
905 unsigned long ifindex;
906 struct prefix_ipv6 p;
907
908 s = client->ibuf;
909 ifindex = 0;
910 memset (&nexthop, 0, sizeof (struct in6_addr));
911
912 /* Type, flags, message. */
913 api.type = stream_getc (s);
Josh Baileyaf56d402012-03-21 18:47:51 -0700914 /* Update the route type of the client.
915 * Same as in zread_ipv4_add(). */
916 if (client->route_type == ZEBRA_ROUTE_MAX)
917 client->route_type = api.type;
918
paul718e3742002-12-13 20:15:29 +0000919 api.flags = stream_getc (s);
920 api.message = stream_getc (s);
921
922 /* IPv4 prefix. */
923 memset (&p, 0, sizeof (struct prefix_ipv6));
924 p.family = AF_INET6;
925 p.prefixlen = stream_getc (s);
926 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
927
928 /* Nexthop, ifindex, distance, metric. */
929 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
930 {
931 u_char nexthop_type;
932
933 api.nexthop_num = stream_getc (s);
934 for (i = 0; i < api.nexthop_num; i++)
935 {
936 nexthop_type = stream_getc (s);
937
938 switch (nexthop_type)
939 {
940 case ZEBRA_NEXTHOP_IPV6:
941 stream_get (&nexthop, s, 16);
942 break;
943 case ZEBRA_NEXTHOP_IFINDEX:
944 ifindex = stream_getl (s);
945 break;
946 }
947 }
948 }
949
950 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
951 api.distance = stream_getc (s);
952 else
953 api.distance = 0;
954
955 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
956 api.metric = stream_getl (s);
957 else
958 api.metric = 0;
959
960 if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
Mathieu Goessensd13c3b42009-06-23 15:59:45 +0100961 rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, zebrad.rtm_table_default, api.metric,
hassobe61c4e2005-08-27 06:05:47 +0000962 api.distance);
paul718e3742002-12-13 20:15:29 +0000963 else
Mathieu Goessensd13c3b42009-06-23 15:59:45 +0100964 rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, zebrad.rtm_table_default, api.metric,
hassobe61c4e2005-08-27 06:05:47 +0000965 api.distance);
ajs719e9742005-02-28 20:52:15 +0000966 return 0;
paul718e3742002-12-13 20:15:29 +0000967}
968
969/* Zebra server IPv6 prefix delete function. */
ajs719e9742005-02-28 20:52:15 +0000970static int
paul718e3742002-12-13 20:15:29 +0000971zread_ipv6_delete (struct zserv *client, u_short length)
972{
973 int i;
974 struct stream *s;
975 struct zapi_ipv6 api;
976 struct in6_addr nexthop;
977 unsigned long ifindex;
978 struct prefix_ipv6 p;
979
980 s = client->ibuf;
981 ifindex = 0;
982 memset (&nexthop, 0, sizeof (struct in6_addr));
983
984 /* Type, flags, message. */
985 api.type = stream_getc (s);
986 api.flags = stream_getc (s);
987 api.message = stream_getc (s);
988
989 /* IPv4 prefix. */
990 memset (&p, 0, sizeof (struct prefix_ipv6));
991 p.family = AF_INET6;
992 p.prefixlen = stream_getc (s);
993 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
994
995 /* Nexthop, ifindex, distance, metric. */
996 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
997 {
998 u_char nexthop_type;
999
1000 api.nexthop_num = stream_getc (s);
1001 for (i = 0; i < api.nexthop_num; i++)
1002 {
1003 nexthop_type = stream_getc (s);
1004
1005 switch (nexthop_type)
1006 {
1007 case ZEBRA_NEXTHOP_IPV6:
1008 stream_get (&nexthop, s, 16);
1009 break;
1010 case ZEBRA_NEXTHOP_IFINDEX:
1011 ifindex = stream_getl (s);
1012 break;
1013 }
1014 }
1015 }
1016
1017 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
1018 api.distance = stream_getc (s);
1019 else
1020 api.distance = 0;
1021 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
1022 api.metric = stream_getl (s);
1023 else
1024 api.metric = 0;
1025
1026 if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
Mathieu Goessensd13c3b42009-06-23 15:59:45 +01001027 rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table);
paul718e3742002-12-13 20:15:29 +00001028 else
Mathieu Goessensd13c3b42009-06-23 15:59:45 +01001029 rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table);
ajs719e9742005-02-28 20:52:15 +00001030 return 0;
paul718e3742002-12-13 20:15:29 +00001031}
1032
ajs719e9742005-02-28 20:52:15 +00001033static int
paul718e3742002-12-13 20:15:29 +00001034zread_ipv6_nexthop_lookup (struct zserv *client, u_short length)
1035{
1036 struct in6_addr addr;
1037 char buf[BUFSIZ];
1038
1039 stream_get (&addr, client->ibuf, 16);
1040 printf ("DEBUG %s\n", inet_ntop (AF_INET6, &addr, buf, BUFSIZ));
1041
ajs719e9742005-02-28 20:52:15 +00001042 return zsend_ipv6_nexthop_lookup (client, &addr);
paul718e3742002-12-13 20:15:29 +00001043}
1044#endif /* HAVE_IPV6 */
1045
hasso18a6dce2004-10-03 18:18:34 +00001046/* Register zebra server router-id information. Send current router-id */
ajs719e9742005-02-28 20:52:15 +00001047static int
hasso18a6dce2004-10-03 18:18:34 +00001048zread_router_id_add (struct zserv *client, u_short length)
1049{
1050 struct prefix p;
1051
1052 /* Router-id information is needed. */
1053 client->ridinfo = 1;
1054
1055 router_id_get (&p);
1056
ajs719e9742005-02-28 20:52:15 +00001057 return zsend_router_id_update (client,&p);
hasso18a6dce2004-10-03 18:18:34 +00001058}
1059
1060/* Unregister zebra server router-id information. */
ajs719e9742005-02-28 20:52:15 +00001061static int
hasso18a6dce2004-10-03 18:18:34 +00001062zread_router_id_delete (struct zserv *client, u_short length)
1063{
1064 client->ridinfo = 0;
ajs719e9742005-02-28 20:52:15 +00001065 return 0;
hasso18a6dce2004-10-03 18:18:34 +00001066}
1067
paul718e3742002-12-13 20:15:29 +00001068/* Close zebra client. */
paulb9df2d22004-05-09 09:09:59 +00001069static void
paul718e3742002-12-13 20:15:29 +00001070zebra_client_close (struct zserv *client)
1071{
Josh Baileyaf56d402012-03-21 18:47:51 -07001072 struct stream *s;
1073
1074 /* Sweep all routes learned from the client first. */
1075 rib_sweep_client_route(client);
1076 /* Reset the route type. It may not be necessary since the
1077 * whole client will be freed. */
1078 client->route_type = ZEBRA_ROUTE_MAX;
1079
paul718e3742002-12-13 20:15:29 +00001080 /* Close file descriptor. */
1081 if (client->sock)
1082 {
1083 close (client->sock);
1084 client->sock = -1;
1085 }
1086
1087 /* Free stream buffers. */
1088 if (client->ibuf)
1089 stream_free (client->ibuf);
1090 if (client->obuf)
1091 stream_free (client->obuf);
ajs719e9742005-02-28 20:52:15 +00001092 if (client->wb)
1093 buffer_free(client->wb);
paul718e3742002-12-13 20:15:29 +00001094
1095 /* Release threads. */
1096 if (client->t_read)
1097 thread_cancel (client->t_read);
1098 if (client->t_write)
1099 thread_cancel (client->t_write);
ajs719e9742005-02-28 20:52:15 +00001100 if (client->t_suicide)
1101 thread_cancel (client->t_suicide);
paul718e3742002-12-13 20:15:29 +00001102
1103 /* Free client structure. */
paulb21b19c2003-06-15 01:28:29 +00001104 listnode_delete (zebrad.client_list, client);
paul718e3742002-12-13 20:15:29 +00001105 XFREE (0, client);
1106}
1107
1108/* Make new client. */
paulb9df2d22004-05-09 09:09:59 +00001109static void
paul718e3742002-12-13 20:15:29 +00001110zebra_client_create (int sock)
1111{
1112 struct zserv *client;
1113
1114 client = XCALLOC (0, sizeof (struct zserv));
1115
1116 /* Make client input/output buffer. */
1117 client->sock = sock;
Josh Baileyaf56d402012-03-21 18:47:51 -07001118 /* Set the default route type to ZEBRA_ROUTE_MAX; it will be updated
1119 * once new routes are received. */
1120 client->route_type = ZEBRA_ROUTE_MAX;
paul718e3742002-12-13 20:15:29 +00001121 client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
1122 client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
ajs719e9742005-02-28 20:52:15 +00001123 client->wb = buffer_new(0);
paul718e3742002-12-13 20:15:29 +00001124
1125 /* Set table number. */
paulb21b19c2003-06-15 01:28:29 +00001126 client->rtm_table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00001127
1128 /* Add this client to linked list. */
paulb21b19c2003-06-15 01:28:29 +00001129 listnode_add (zebrad.client_list, client);
paul718e3742002-12-13 20:15:29 +00001130
1131 /* Make new read thread. */
1132 zebra_event (ZEBRA_READ, sock, client);
1133}
1134
1135/* Handler of zebra service request. */
paulb9df2d22004-05-09 09:09:59 +00001136static int
paul718e3742002-12-13 20:15:29 +00001137zebra_client_read (struct thread *thread)
1138{
1139 int sock;
1140 struct zserv *client;
ajs57a14772005-04-10 15:01:56 +00001141 size_t already;
paulc1b98002006-01-16 01:54:02 +00001142 uint16_t length, command;
1143 uint8_t marker, version;
paul718e3742002-12-13 20:15:29 +00001144
1145 /* Get thread data. Reset reading thread because I'm running. */
1146 sock = THREAD_FD (thread);
1147 client = THREAD_ARG (thread);
1148 client->t_read = NULL;
1149
ajs719e9742005-02-28 20:52:15 +00001150 if (client->t_suicide)
paul718e3742002-12-13 20:15:29 +00001151 {
ajs719e9742005-02-28 20:52:15 +00001152 zebra_client_close(client);
paul718e3742002-12-13 20:15:29 +00001153 return -1;
1154 }
ajs719e9742005-02-28 20:52:15 +00001155
1156 /* Read length and command (if we don't have it already). */
ajs57a14772005-04-10 15:01:56 +00001157 if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE)
ajs719e9742005-02-28 20:52:15 +00001158 {
ajs57a14772005-04-10 15:01:56 +00001159 ssize_t nbyte;
ajs719e9742005-02-28 20:52:15 +00001160 if (((nbyte = stream_read_try (client->ibuf, sock,
ajs57a14772005-04-10 15:01:56 +00001161 ZEBRA_HEADER_SIZE-already)) == 0) ||
ajs719e9742005-02-28 20:52:15 +00001162 (nbyte == -1))
1163 {
1164 if (IS_ZEBRA_DEBUG_EVENT)
1165 zlog_debug ("connection closed socket [%d]", sock);
1166 zebra_client_close (client);
1167 return -1;
1168 }
ajs57a14772005-04-10 15:01:56 +00001169 if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
ajs719e9742005-02-28 20:52:15 +00001170 {
1171 /* Try again later. */
1172 zebra_event (ZEBRA_READ, sock, client);
1173 return 0;
1174 }
ajs57a14772005-04-10 15:01:56 +00001175 already = ZEBRA_HEADER_SIZE;
ajs719e9742005-02-28 20:52:15 +00001176 }
1177
1178 /* Reset to read from the beginning of the incoming packet. */
1179 stream_set_getp(client->ibuf, 0);
1180
paulc1b98002006-01-16 01:54:02 +00001181 /* Fetch header values */
paul718e3742002-12-13 20:15:29 +00001182 length = stream_getw (client->ibuf);
paulc1b98002006-01-16 01:54:02 +00001183 marker = stream_getc (client->ibuf);
1184 version = stream_getc (client->ibuf);
1185 command = stream_getw (client->ibuf);
paul718e3742002-12-13 20:15:29 +00001186
paulc1b98002006-01-16 01:54:02 +00001187 if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
1188 {
1189 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
1190 __func__, sock, marker, version);
1191 zebra_client_close (client);
1192 return -1;
1193 }
ajs719e9742005-02-28 20:52:15 +00001194 if (length < ZEBRA_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00001195 {
ajs57a14772005-04-10 15:01:56 +00001196 zlog_warn("%s: socket %d message length %u is less than header size %d",
1197 __func__, sock, length, ZEBRA_HEADER_SIZE);
1198 zebra_client_close (client);
1199 return -1;
1200 }
1201 if (length > STREAM_SIZE(client->ibuf))
1202 {
1203 zlog_warn("%s: socket %d message length %u exceeds buffer size %lu",
1204 __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf));
paul718e3742002-12-13 20:15:29 +00001205 zebra_client_close (client);
1206 return -1;
1207 }
1208
paul718e3742002-12-13 20:15:29 +00001209 /* Read rest of data. */
ajs57a14772005-04-10 15:01:56 +00001210 if (already < length)
paul718e3742002-12-13 20:15:29 +00001211 {
ajs57a14772005-04-10 15:01:56 +00001212 ssize_t nbyte;
1213 if (((nbyte = stream_read_try (client->ibuf, sock,
1214 length-already)) == 0) ||
1215 (nbyte == -1))
paul718e3742002-12-13 20:15:29 +00001216 {
1217 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +00001218 zlog_debug ("connection closed [%d] when reading zebra data", sock);
paul718e3742002-12-13 20:15:29 +00001219 zebra_client_close (client);
1220 return -1;
1221 }
ajs57a14772005-04-10 15:01:56 +00001222 if (nbyte != (ssize_t)(length-already))
ajs719e9742005-02-28 20:52:15 +00001223 {
1224 /* Try again later. */
1225 zebra_event (ZEBRA_READ, sock, client);
1226 return 0;
1227 }
paul718e3742002-12-13 20:15:29 +00001228 }
1229
ajs719e9742005-02-28 20:52:15 +00001230 length -= ZEBRA_HEADER_SIZE;
1231
paul718e3742002-12-13 20:15:29 +00001232 /* Debug packet information. */
1233 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +00001234 zlog_debug ("zebra message comes from socket [%d]", sock);
paul718e3742002-12-13 20:15:29 +00001235
1236 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
ajsb6178002004-12-07 21:12:56 +00001237 zlog_debug ("zebra message received [%s] %d",
Paul Jakma66859782006-05-15 17:00:37 +00001238 zserv_command_string (command), length);
paul718e3742002-12-13 20:15:29 +00001239
1240 switch (command)
1241 {
hasso18a6dce2004-10-03 18:18:34 +00001242 case ZEBRA_ROUTER_ID_ADD:
1243 zread_router_id_add (client, length);
1244 break;
1245 case ZEBRA_ROUTER_ID_DELETE:
1246 zread_router_id_delete (client, length);
1247 break;
paul718e3742002-12-13 20:15:29 +00001248 case ZEBRA_INTERFACE_ADD:
1249 zread_interface_add (client, length);
1250 break;
1251 case ZEBRA_INTERFACE_DELETE:
1252 zread_interface_delete (client, length);
1253 break;
1254 case ZEBRA_IPV4_ROUTE_ADD:
1255 zread_ipv4_add (client, length);
1256 break;
1257 case ZEBRA_IPV4_ROUTE_DELETE:
1258 zread_ipv4_delete (client, length);
1259 break;
1260#ifdef HAVE_IPV6
1261 case ZEBRA_IPV6_ROUTE_ADD:
1262 zread_ipv6_add (client, length);
1263 break;
1264 case ZEBRA_IPV6_ROUTE_DELETE:
1265 zread_ipv6_delete (client, length);
1266 break;
1267#endif /* HAVE_IPV6 */
1268 case ZEBRA_REDISTRIBUTE_ADD:
1269 zebra_redistribute_add (command, client, length);
1270 break;
1271 case ZEBRA_REDISTRIBUTE_DELETE:
1272 zebra_redistribute_delete (command, client, length);
1273 break;
1274 case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
1275 zebra_redistribute_default_add (command, client, length);
1276 break;
1277 case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
1278 zebra_redistribute_default_delete (command, client, length);
1279 break;
1280 case ZEBRA_IPV4_NEXTHOP_LOOKUP:
1281 zread_ipv4_nexthop_lookup (client, length);
1282 break;
1283#ifdef HAVE_IPV6
1284 case ZEBRA_IPV6_NEXTHOP_LOOKUP:
1285 zread_ipv6_nexthop_lookup (client, length);
1286 break;
1287#endif /* HAVE_IPV6 */
1288 case ZEBRA_IPV4_IMPORT_LOOKUP:
1289 zread_ipv4_import_lookup (client, length);
1290 break;
1291 default:
1292 zlog_info ("Zebra received unknown command %d", command);
1293 break;
1294 }
1295
ajs719e9742005-02-28 20:52:15 +00001296 if (client->t_suicide)
1297 {
1298 /* No need to wait for thread callback, just kill immediately. */
1299 zebra_client_close(client);
1300 return -1;
1301 }
1302
paul718e3742002-12-13 20:15:29 +00001303 stream_reset (client->ibuf);
1304 zebra_event (ZEBRA_READ, sock, client);
paul718e3742002-12-13 20:15:29 +00001305 return 0;
1306}
1307
paul718e3742002-12-13 20:15:29 +00001308
1309/* Accept code of zebra server socket. */
paulb9df2d22004-05-09 09:09:59 +00001310static int
paul718e3742002-12-13 20:15:29 +00001311zebra_accept (struct thread *thread)
1312{
1313 int accept_sock;
1314 int client_sock;
1315 struct sockaddr_in client;
1316 socklen_t len;
1317
1318 accept_sock = THREAD_FD (thread);
1319
ajs719e9742005-02-28 20:52:15 +00001320 /* Reregister myself. */
1321 zebra_event (ZEBRA_SERV, accept_sock, NULL);
1322
paul718e3742002-12-13 20:15:29 +00001323 len = sizeof (struct sockaddr_in);
1324 client_sock = accept (accept_sock, (struct sockaddr *) &client, &len);
1325
1326 if (client_sock < 0)
1327 {
ajs6099b3b2004-11-20 02:06:59 +00001328 zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001329 return -1;
1330 }
1331
paulccf35572003-03-01 11:42:20 +00001332 /* Make client socket non-blocking. */
ajs719e9742005-02-28 20:52:15 +00001333 set_nonblocking(client_sock);
paul865b8522005-01-05 08:30:35 +00001334
paul718e3742002-12-13 20:15:29 +00001335 /* Create new zebra client. */
1336 zebra_client_create (client_sock);
1337
paul718e3742002-12-13 20:15:29 +00001338 return 0;
1339}
1340
paulb9df2d22004-05-09 09:09:59 +00001341#ifdef HAVE_TCP_ZEBRA
paul718e3742002-12-13 20:15:29 +00001342/* Make zebra's server socket. */
paulb9df2d22004-05-09 09:09:59 +00001343static void
paul718e3742002-12-13 20:15:29 +00001344zebra_serv ()
1345{
1346 int ret;
1347 int accept_sock;
1348 struct sockaddr_in addr;
1349
1350 accept_sock = socket (AF_INET, SOCK_STREAM, 0);
1351
1352 if (accept_sock < 0)
1353 {
paul3d1dc852005-04-05 00:45:23 +00001354 zlog_warn ("Can't create zserv stream socket: %s",
1355 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001356 zlog_warn ("zebra can't provice full functionality due to above error");
1357 return;
1358 }
1359
1360 memset (&addr, 0, sizeof (struct sockaddr_in));
1361 addr.sin_family = AF_INET;
1362 addr.sin_port = htons (ZEBRA_PORT);
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001363#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
paul718e3742002-12-13 20:15:29 +00001364 addr.sin_len = sizeof (struct sockaddr_in);
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001365#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
paul718e3742002-12-13 20:15:29 +00001366 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1367
1368 sockopt_reuseaddr (accept_sock);
1369 sockopt_reuseport (accept_sock);
1370
pauledd7c242003-06-04 13:59:38 +00001371 if ( zserv_privs.change(ZPRIVS_RAISE) )
1372 zlog (NULL, LOG_ERR, "Can't raise privileges");
1373
paul718e3742002-12-13 20:15:29 +00001374 ret = bind (accept_sock, (struct sockaddr *)&addr,
1375 sizeof (struct sockaddr_in));
1376 if (ret < 0)
1377 {
paul3d1dc852005-04-05 00:45:23 +00001378 zlog_warn ("Can't bind to stream socket: %s",
1379 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001380 zlog_warn ("zebra can't provice full functionality due to above error");
1381 close (accept_sock); /* Avoid sd leak. */
1382 return;
1383 }
pauledd7c242003-06-04 13:59:38 +00001384
1385 if ( zserv_privs.change(ZPRIVS_LOWER) )
1386 zlog (NULL, LOG_ERR, "Can't lower privileges");
paul718e3742002-12-13 20:15:29 +00001387
1388 ret = listen (accept_sock, 1);
1389 if (ret < 0)
1390 {
paul3d1dc852005-04-05 00:45:23 +00001391 zlog_warn ("Can't listen to stream socket: %s",
1392 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001393 zlog_warn ("zebra can't provice full functionality due to above error");
1394 close (accept_sock); /* Avoid sd leak. */
1395 return;
1396 }
1397
1398 zebra_event (ZEBRA_SERV, accept_sock, NULL);
1399}
paulb9df2d22004-05-09 09:09:59 +00001400#endif /* HAVE_TCP_ZEBRA */
paul718e3742002-12-13 20:15:29 +00001401
1402/* For sockaddr_un. */
1403#include <sys/un.h>
1404
1405/* zebra server UNIX domain socket. */
paulb9df2d22004-05-09 09:09:59 +00001406static void
hassofce954f2004-10-07 20:29:24 +00001407zebra_serv_un (const char *path)
paul718e3742002-12-13 20:15:29 +00001408{
1409 int ret;
1410 int sock, len;
1411 struct sockaddr_un serv;
1412 mode_t old_mask;
1413
1414 /* First of all, unlink existing socket */
1415 unlink (path);
1416
1417 /* Set umask */
1418 old_mask = umask (0077);
1419
1420 /* Make UNIX domain socket. */
1421 sock = socket (AF_UNIX, SOCK_STREAM, 0);
1422 if (sock < 0)
1423 {
paul3d1dc852005-04-05 00:45:23 +00001424 zlog_warn ("Can't create zserv unix socket: %s",
1425 safe_strerror (errno));
1426 zlog_warn ("zebra can't provide full functionality due to above error");
paul718e3742002-12-13 20:15:29 +00001427 return;
1428 }
1429
1430 /* Make server socket. */
1431 memset (&serv, 0, sizeof (struct sockaddr_un));
1432 serv.sun_family = AF_UNIX;
1433 strncpy (serv.sun_path, path, strlen (path));
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001434#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
paul718e3742002-12-13 20:15:29 +00001435 len = serv.sun_len = SUN_LEN(&serv);
1436#else
1437 len = sizeof (serv.sun_family) + strlen (serv.sun_path);
Paul Jakma6f0e3f62007-05-10 02:38:51 +00001438#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
paul718e3742002-12-13 20:15:29 +00001439
1440 ret = bind (sock, (struct sockaddr *) &serv, len);
1441 if (ret < 0)
1442 {
paul3d1dc852005-04-05 00:45:23 +00001443 zlog_warn ("Can't bind to unix socket %s: %s",
1444 path, safe_strerror (errno));
1445 zlog_warn ("zebra can't provide full functionality due to above error");
paul718e3742002-12-13 20:15:29 +00001446 close (sock);
1447 return;
1448 }
1449
1450 ret = listen (sock, 5);
1451 if (ret < 0)
1452 {
paul3d1dc852005-04-05 00:45:23 +00001453 zlog_warn ("Can't listen to unix socket %s: %s",
1454 path, safe_strerror (errno));
1455 zlog_warn ("zebra can't provide full functionality due to above error");
paul718e3742002-12-13 20:15:29 +00001456 close (sock);
1457 return;
1458 }
1459
1460 umask (old_mask);
1461
1462 zebra_event (ZEBRA_SERV, sock, NULL);
1463}
1464
paul718e3742002-12-13 20:15:29 +00001465
paulb9df2d22004-05-09 09:09:59 +00001466static void
paul718e3742002-12-13 20:15:29 +00001467zebra_event (enum event event, int sock, struct zserv *client)
1468{
1469 switch (event)
1470 {
1471 case ZEBRA_SERV:
paulb21b19c2003-06-15 01:28:29 +00001472 thread_add_read (zebrad.master, zebra_accept, client, sock);
paul718e3742002-12-13 20:15:29 +00001473 break;
1474 case ZEBRA_READ:
1475 client->t_read =
paulb21b19c2003-06-15 01:28:29 +00001476 thread_add_read (zebrad.master, zebra_client_read, client, sock);
paul718e3742002-12-13 20:15:29 +00001477 break;
1478 case ZEBRA_WRITE:
1479 /**/
1480 break;
1481 }
1482}
1483
1484/* Display default rtm_table for all clients. */
1485DEFUN (show_table,
1486 show_table_cmd,
1487 "show table",
1488 SHOW_STR
1489 "default routing table to use for all clients\n")
1490{
paulb21b19c2003-06-15 01:28:29 +00001491 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
paul718e3742002-12-13 20:15:29 +00001492 VTY_NEWLINE);
1493 return CMD_SUCCESS;
1494}
1495
1496DEFUN (config_table,
1497 config_table_cmd,
1498 "table TABLENO",
1499 "Configure target kernel routing table\n"
1500 "TABLE integer\n")
1501{
paulb21b19c2003-06-15 01:28:29 +00001502 zebrad.rtm_table_default = strtol (argv[0], (char**)0, 10);
paul718e3742002-12-13 20:15:29 +00001503 return CMD_SUCCESS;
1504}
1505
hasso647e4f12003-05-25 11:43:52 +00001506DEFUN (ip_forwarding,
1507 ip_forwarding_cmd,
1508 "ip forwarding",
1509 IP_STR
1510 "Turn on IP forwarding")
1511{
1512 int ret;
1513
1514 ret = ipforward ();
hassob71f00f2004-10-13 12:20:35 +00001515 if (ret == 0)
1516 ret = ipforward_on ();
hasso647e4f12003-05-25 11:43:52 +00001517
hasso647e4f12003-05-25 11:43:52 +00001518 if (ret == 0)
1519 {
1520 vty_out (vty, "Can't turn on IP forwarding%s", VTY_NEWLINE);
1521 return CMD_WARNING;
1522 }
1523
1524 return CMD_SUCCESS;
1525}
1526
paul718e3742002-12-13 20:15:29 +00001527DEFUN (no_ip_forwarding,
1528 no_ip_forwarding_cmd,
1529 "no ip forwarding",
1530 NO_STR
1531 IP_STR
1532 "Turn off IP forwarding")
1533{
1534 int ret;
1535
1536 ret = ipforward ();
hassob71f00f2004-10-13 12:20:35 +00001537 if (ret != 0)
1538 ret = ipforward_off ();
paul718e3742002-12-13 20:15:29 +00001539
paul718e3742002-12-13 20:15:29 +00001540 if (ret != 0)
1541 {
1542 vty_out (vty, "Can't turn off IP forwarding%s", VTY_NEWLINE);
1543 return CMD_WARNING;
1544 }
1545
1546 return CMD_SUCCESS;
1547}
1548
1549/* This command is for debugging purpose. */
1550DEFUN (show_zebra_client,
1551 show_zebra_client_cmd,
1552 "show zebra client",
1553 SHOW_STR
1554 "Zebra information"
1555 "Client information")
1556{
hasso52dc7ee2004-09-23 19:18:23 +00001557 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001558 struct zserv *client;
1559
paul1eb8ef22005-04-07 07:30:20 +00001560 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
1561 vty_out (vty, "Client fd %d%s", client->sock, VTY_NEWLINE);
1562
paul718e3742002-12-13 20:15:29 +00001563 return CMD_SUCCESS;
1564}
1565
1566/* Table configuration write function. */
paulb9df2d22004-05-09 09:09:59 +00001567static int
paul718e3742002-12-13 20:15:29 +00001568config_write_table (struct vty *vty)
1569{
paulb21b19c2003-06-15 01:28:29 +00001570 if (zebrad.rtm_table_default)
1571 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
paul718e3742002-12-13 20:15:29 +00001572 VTY_NEWLINE);
1573 return 0;
1574}
1575
1576/* table node for routing tables. */
Stephen Hemminger7fc626d2008-12-01 11:10:34 -08001577static struct cmd_node table_node =
paul718e3742002-12-13 20:15:29 +00001578{
1579 TABLE_NODE,
1580 "", /* This node has no interface. */
1581 1
1582};
1583
1584/* Only display ip forwarding is enabled or not. */
1585DEFUN (show_ip_forwarding,
1586 show_ip_forwarding_cmd,
1587 "show ip forwarding",
1588 SHOW_STR
1589 IP_STR
1590 "IP forwarding status\n")
1591{
1592 int ret;
1593
1594 ret = ipforward ();
1595
1596 if (ret == 0)
1597 vty_out (vty, "IP forwarding is off%s", VTY_NEWLINE);
1598 else
1599 vty_out (vty, "IP forwarding is on%s", VTY_NEWLINE);
1600 return CMD_SUCCESS;
1601}
1602
1603#ifdef HAVE_IPV6
1604/* Only display ipv6 forwarding is enabled or not. */
1605DEFUN (show_ipv6_forwarding,
1606 show_ipv6_forwarding_cmd,
1607 "show ipv6 forwarding",
1608 SHOW_STR
1609 "IPv6 information\n"
1610 "Forwarding status\n")
1611{
1612 int ret;
1613
1614 ret = ipforward_ipv6 ();
1615
1616 switch (ret)
1617 {
1618 case -1:
1619 vty_out (vty, "ipv6 forwarding is unknown%s", VTY_NEWLINE);
1620 break;
1621 case 0:
1622 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
1623 break;
1624 case 1:
1625 vty_out (vty, "ipv6 forwarding is %s%s", "on", VTY_NEWLINE);
1626 break;
1627 default:
1628 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
1629 break;
1630 }
1631 return CMD_SUCCESS;
1632}
1633
hasso55906722004-02-11 22:42:16 +00001634DEFUN (ipv6_forwarding,
1635 ipv6_forwarding_cmd,
1636 "ipv6 forwarding",
1637 IPV6_STR
1638 "Turn on IPv6 forwarding")
1639{
1640 int ret;
1641
hasso41d3fc92004-04-06 11:59:00 +00001642 ret = ipforward_ipv6 ();
hassob71f00f2004-10-13 12:20:35 +00001643 if (ret == 0)
1644 ret = ipforward_ipv6_on ();
hasso41d3fc92004-04-06 11:59:00 +00001645
hasso41d3fc92004-04-06 11:59:00 +00001646 if (ret == 0)
1647 {
hasso55906722004-02-11 22:42:16 +00001648 vty_out (vty, "Can't turn on IPv6 forwarding%s", VTY_NEWLINE);
1649 return CMD_WARNING;
1650 }
1651
1652 return CMD_SUCCESS;
1653}
1654
paul718e3742002-12-13 20:15:29 +00001655DEFUN (no_ipv6_forwarding,
1656 no_ipv6_forwarding_cmd,
1657 "no ipv6 forwarding",
1658 NO_STR
hasso55906722004-02-11 22:42:16 +00001659 IPV6_STR
1660 "Turn off IPv6 forwarding")
paul718e3742002-12-13 20:15:29 +00001661{
1662 int ret;
1663
hasso41d3fc92004-04-06 11:59:00 +00001664 ret = ipforward_ipv6 ();
hassob71f00f2004-10-13 12:20:35 +00001665 if (ret != 0)
1666 ret = ipforward_ipv6_off ();
hasso41d3fc92004-04-06 11:59:00 +00001667
paul718e3742002-12-13 20:15:29 +00001668 if (ret != 0)
1669 {
1670 vty_out (vty, "Can't turn off IPv6 forwarding%s", VTY_NEWLINE);
1671 return CMD_WARNING;
1672 }
1673
1674 return CMD_SUCCESS;
1675}
1676
1677#endif /* HAVE_IPV6 */
1678
1679/* IPForwarding configuration write function. */
ajs719e9742005-02-28 20:52:15 +00001680static int
paul718e3742002-12-13 20:15:29 +00001681config_write_forwarding (struct vty *vty)
1682{
hasso18a6dce2004-10-03 18:18:34 +00001683 /* FIXME: Find better place for that. */
1684 router_id_write (vty);
1685
paul3e0b3a52004-08-23 18:58:32 +00001686 if (ipforward ())
1687 vty_out (vty, "ip forwarding%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001688#ifdef HAVE_IPV6
paul3e0b3a52004-08-23 18:58:32 +00001689 if (ipforward_ipv6 ())
1690 vty_out (vty, "ipv6 forwarding%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001691#endif /* HAVE_IPV6 */
1692 vty_out (vty, "!%s", VTY_NEWLINE);
1693 return 0;
1694}
1695
1696/* table node for routing tables. */
Stephen Hemminger7fc626d2008-12-01 11:10:34 -08001697static struct cmd_node forwarding_node =
paul718e3742002-12-13 20:15:29 +00001698{
1699 FORWARDING_NODE,
1700 "", /* This node has no interface. */
1701 1
1702};
1703
1704
1705/* Initialisation of zebra and installation of commands. */
1706void
paula1ac18c2005-06-28 17:17:12 +00001707zebra_init (void)
paul718e3742002-12-13 20:15:29 +00001708{
1709 /* Client list init. */
paulb21b19c2003-06-15 01:28:29 +00001710 zebrad.client_list = list_new ();
paul718e3742002-12-13 20:15:29 +00001711
paul718e3742002-12-13 20:15:29 +00001712 /* Install configuration write function. */
1713 install_node (&table_node, config_write_table);
1714 install_node (&forwarding_node, config_write_forwarding);
1715
1716 install_element (VIEW_NODE, &show_ip_forwarding_cmd);
1717 install_element (ENABLE_NODE, &show_ip_forwarding_cmd);
hasso647e4f12003-05-25 11:43:52 +00001718 install_element (CONFIG_NODE, &ip_forwarding_cmd);
paul718e3742002-12-13 20:15:29 +00001719 install_element (CONFIG_NODE, &no_ip_forwarding_cmd);
1720 install_element (ENABLE_NODE, &show_zebra_client_cmd);
1721
1722#ifdef HAVE_NETLINK
1723 install_element (VIEW_NODE, &show_table_cmd);
1724 install_element (ENABLE_NODE, &show_table_cmd);
1725 install_element (CONFIG_NODE, &config_table_cmd);
1726#endif /* HAVE_NETLINK */
1727
1728#ifdef HAVE_IPV6
1729 install_element (VIEW_NODE, &show_ipv6_forwarding_cmd);
1730 install_element (ENABLE_NODE, &show_ipv6_forwarding_cmd);
hasso55906722004-02-11 22:42:16 +00001731 install_element (CONFIG_NODE, &ipv6_forwarding_cmd);
paul718e3742002-12-13 20:15:29 +00001732 install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
1733#endif /* HAVE_IPV6 */
Paul Jakma7514fb72007-05-02 16:05:35 +00001734
1735 /* Route-map */
1736 zebra_route_map_init ();
paul718e3742002-12-13 20:15:29 +00001737}
Denis Ovsienko97be79f2009-07-24 20:45:31 +04001738
1739/* Make zebra server socket, wiping any existing one (see bug #403). */
1740void
1741zebra_zserv_socket_init (void)
1742{
1743#ifdef HAVE_TCP_ZEBRA
1744 zebra_serv ();
1745#else
1746 zebra_serv_un (ZEBRA_SERV_PATH);
1747#endif /* HAVE_TCP_ZEBRA */
1748}