blob: f08f7ce8f5f7c513827be4b3d61790efbc1846c8 [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
55/* For logging of zebra meesages. */
hassofce954f2004-10-07 20:29:24 +000056static const char *zebra_command_str [] =
paul718e3742002-12-13 20:15:29 +000057{
58 "NULL",
59 "ZEBRA_INTERFACE_ADD",
60 "ZEBRA_INTERFACE_DELETE",
61 "ZEBRA_INTERFACE_ADDRESS_ADD",
62 "ZEBRA_INTERFACE_ADDRESS_DELETE",
63 "ZEBRA_INTERFACE_UP",
64 "ZEBRA_INTERFACE_DOWN",
65 "ZEBRA_IPV4_ROUTE_ADD",
66 "ZEBRA_IPV4_ROUTE_DELETE",
67 "ZEBRA_IPV6_ROUTE_ADD",
68 "ZEBRA_IPV6_ROUTE_DELETE",
69 "ZEBRA_REDISTRIBUTE_ADD",
70 "ZEBRA_REDISTRIBUTE_DELETE",
71 "ZEBRA_REDISTRIBUTE_DEFAULT_ADD",
72 "ZEBRA_REDISTRIBUTE_DEFAULT_DELETE",
73 "ZEBRA_IPV4_NEXTHOP_LOOKUP",
74 "ZEBRA_IPV6_NEXTHOP_LOOKUP",
75 "ZEBRA_IPV4_IMPORT_LOOKUP",
hasso18a6dce2004-10-03 18:18:34 +000076 "ZEBRA_IPV6_IMPORT_LOOKUP",
77 "ZEBRA_ROUTER_ID_ADD",
78 "ZEBRA_ROUTER_ID_DELETE",
79 "ZEBRA_ROUTER_ID_UPDATE"
paul718e3742002-12-13 20:15:29 +000080};
81
ajs719e9742005-02-28 20:52:15 +000082
83static void zebra_client_close (struct zserv *client);
84
85static int
86zserv_delayed_close(struct thread *thread)
paulccf35572003-03-01 11:42:20 +000087{
ajs719e9742005-02-28 20:52:15 +000088 struct zserv *client = THREAD_ARG(thread);
paulccf35572003-03-01 11:42:20 +000089
ajs719e9742005-02-28 20:52:15 +000090 client->t_suicide = NULL;
91 zebra_client_close(client);
paulccf35572003-03-01 11:42:20 +000092 return 0;
93}
94
ajs719e9742005-02-28 20:52:15 +000095static int
96zserv_flush_data(struct thread *thread)
paulccf35572003-03-01 11:42:20 +000097{
ajs719e9742005-02-28 20:52:15 +000098 struct zserv *client = THREAD_ARG(thread);
paulccf35572003-03-01 11:42:20 +000099
ajs719e9742005-02-28 20:52:15 +0000100 client->t_write = NULL;
101 if (client->t_suicide)
102 {
103 zebra_client_close(client);
104 return -1;
105 }
106 switch (buffer_flush_available(client->wb, client->sock))
107 {
108 case BUFFER_ERROR:
109 zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, "
110 "closing", __func__, client->sock);
111 zebra_client_close(client);
112 break;
113 case BUFFER_PENDING:
114 client->t_write = thread_add_write(zebrad.master, zserv_flush_data,
115 client, client->sock);
116 break;
117 case BUFFER_EMPTY:
118 break;
119 }
120 return 0;
paulccf35572003-03-01 11:42:20 +0000121}
122
ajs719e9742005-02-28 20:52:15 +0000123static int
124zebra_server_send_message(struct zserv *client)
paulccf35572003-03-01 11:42:20 +0000125{
ajs719e9742005-02-28 20:52:15 +0000126 if (client->t_suicide)
127 return -1;
128 switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf),
129 stream_get_endp(client->obuf)))
paulccf35572003-03-01 11:42:20 +0000130 {
ajs719e9742005-02-28 20:52:15 +0000131 case BUFFER_ERROR:
132 zlog_warn("%s: buffer_write failed to zserv client fd %d, closing",
133 __func__, client->sock);
134 /* Schedule a delayed close since many of the functions that call this
135 one do not check the return code. They do not allow for the
136 possibility that an I/O error may have caused the client to be
137 deleted. */
138 client->t_suicide = thread_add_event(zebrad.master, zserv_delayed_close,
139 client, 0);
140 return -1;
141 break;
142 case BUFFER_EMPTY:
143 THREAD_OFF(client->t_write);
144 break;
145 case BUFFER_PENDING:
146 THREAD_WRITE_ON(zebrad.master, client->t_write,
147 zserv_flush_data, client, client->sock);
148 break;
paulccf35572003-03-01 11:42:20 +0000149 }
paulccf35572003-03-01 11:42:20 +0000150 return 0;
151}
152
paul718e3742002-12-13 20:15:29 +0000153/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
paulb9df2d22004-05-09 09:09:59 +0000154/*
155 * This function is called in the following situations:
156 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
157 * from the client.
158 * - at startup, when zebra figures out the available interfaces
159 * - when an interface is added (where support for
160 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
161 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
162 * received)
163 */
paul718e3742002-12-13 20:15:29 +0000164int
165zsend_interface_add (struct zserv *client, struct interface *ifp)
166{
167 struct stream *s;
168
169 /* Check this client need interface information. */
170 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000171 return 0;
paul718e3742002-12-13 20:15:29 +0000172
173 s = client->obuf;
174 stream_reset (s);
175
176 /* Place holder for size. */
177 stream_putw (s, 0);
178
179 /* Message type. */
180 stream_putc (s, ZEBRA_INTERFACE_ADD);
181
182 /* Interface information. */
183 stream_put (s, ifp->name, INTERFACE_NAMSIZ);
184 stream_putl (s, ifp->ifindex);
paul2e3b2e42002-12-13 21:03:13 +0000185 stream_putc (s, ifp->status);
paul718e3742002-12-13 20:15:29 +0000186 stream_putl (s, ifp->flags);
187 stream_putl (s, ifp->metric);
188 stream_putl (s, ifp->mtu);
paulb9df2d22004-05-09 09:09:59 +0000189 stream_putl (s, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000190 stream_putl (s, ifp->bandwidth);
191#ifdef HAVE_SOCKADDR_DL
192 stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
193#else
194 stream_putl (s, ifp->hw_addr_len);
195 if (ifp->hw_addr_len)
196 stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
197#endif /* HAVE_SOCKADDR_DL */
198
199 /* Write packet size. */
200 stream_putw_at (s, 0, stream_get_endp (s));
201
ajs719e9742005-02-28 20:52:15 +0000202 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000203}
204
205/* Interface deletion from zebra daemon. */
paulb9df2d22004-05-09 09:09:59 +0000206/*
207 * This function is only called when support for
208 * RTM_IFANNOUNCE or AF_NETLINK sockets (RTM_DELLINK message)
209 * is available. It is not called on Solaris.
210 */
211#if (defined(RTM_IFANNOUNCE) || defined(HAVE_NETLINK))
paul718e3742002-12-13 20:15:29 +0000212int
213zsend_interface_delete (struct zserv *client, struct interface *ifp)
214{
215 struct stream *s;
216
217 /* Check this client need interface information. */
218 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000219 return 0;
paul718e3742002-12-13 20:15:29 +0000220
221 s = client->obuf;
222 stream_reset (s);
223
224 /* Packet length placeholder. */
225 stream_putw (s, 0);
226
227 /* Interface information. */
228 stream_putc (s, ZEBRA_INTERFACE_DELETE);
229 stream_put (s, ifp->name, INTERFACE_NAMSIZ);
230 stream_putl (s, ifp->ifindex);
paul2e3b2e42002-12-13 21:03:13 +0000231 stream_putc (s, ifp->status);
paul718e3742002-12-13 20:15:29 +0000232 stream_putl (s, ifp->flags);
233 stream_putl (s, ifp->metric);
234 stream_putl (s, ifp->mtu);
paulb9df2d22004-05-09 09:09:59 +0000235 stream_putl (s, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000236 stream_putl (s, ifp->bandwidth);
237
238 /* Write packet length. */
239 stream_putw_at (s, 0, stream_get_endp (s));
240
ajs719e9742005-02-28 20:52:15 +0000241 return zebra_server_send_message (client);
paul718e3742002-12-13 20:15:29 +0000242}
paulb9df2d22004-05-09 09:09:59 +0000243#endif /* (defined(RTM_IFANNOUNCE) || defined(HAVE_LINUX_RTNETLINK_H)) */
paul718e3742002-12-13 20:15:29 +0000244
paulb9df2d22004-05-09 09:09:59 +0000245/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
246 * ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
247 *
248 * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations:
249 * - in response to a 3-byte ZEBRA_INTERFACE_ADD request
250 * from the client, after the ZEBRA_INTERFACE_ADD has been
251 * sent from zebra to the client
252 * - redistribute new address info to all clients in the following situations
253 * - at startup, when zebra figures out the available interfaces
254 * - when an interface is added (where support for
255 * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when
256 * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is
257 * received)
258 * - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]"
259 * and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M"
260 * - when an RTM_NEWADDR message is received from the kernel,
261 *
262 * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE:
263 *
264 * zsend_interface_address(DELETE)
265 * ^
266 * |
267 * zebra_interface_address_delete_update
268 * ^ ^ ^
269 * | | if_delete_update (not called on
270 * | | Solaris)
271 * ip_address_uninstall connected_delete_ipv4
272 * [ipv6_addresss_uninstall] [connected_delete_ipv6]
273 * ^ ^
274 * | |
275 * | RTM_NEWADDR on routing/netlink socket
276 * |
277 * vty commands:
278 * "no ip address A.B.C.D/M [label LINE]"
279 * "no ip address A.B.C.D/M secondary"
280 * ["no ipv6 address X:X::X:X/M"]
281 *
282 */
paul718e3742002-12-13 20:15:29 +0000283int
paulb9df2d22004-05-09 09:09:59 +0000284zsend_interface_address (int cmd, struct zserv *client,
285 struct interface *ifp, struct connected *ifc)
paul718e3742002-12-13 20:15:29 +0000286{
287 int blen;
288 struct stream *s;
289 struct prefix *p;
290
291 /* Check this client need interface information. */
292 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000293 return 0;
paul718e3742002-12-13 20:15:29 +0000294
295 s = client->obuf;
296 stream_reset (s);
297
298 /* Place holder for size. */
299 stream_putw (s, 0);
300
paulb9df2d22004-05-09 09:09:59 +0000301 stream_putc (s, cmd);
paul718e3742002-12-13 20:15:29 +0000302 stream_putl (s, ifp->ifindex);
303
304 /* Interface address flag. */
305 stream_putc (s, ifc->flags);
306
307 /* Prefix information. */
308 p = ifc->address;
309 stream_putc (s, p->family);
310 blen = prefix_blen (p);
311 stream_put (s, &p->u.prefix, blen);
paulb9df2d22004-05-09 09:09:59 +0000312
313 /*
314 * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE
315 * but zebra_interface_address_delete_read() in the gnu version
316 * expects to find it
317 */
paul718e3742002-12-13 20:15:29 +0000318 stream_putc (s, p->prefixlen);
319
320 /* Destination. */
321 p = ifc->destination;
322 if (p)
323 stream_put (s, &p->u.prefix, blen);
324 else
325 stream_put (s, NULL, blen);
326
327 /* Write packet size. */
328 stream_putw_at (s, 0, stream_get_endp (s));
329
ajs719e9742005-02-28 20:52:15 +0000330 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000331}
332
paulb9df2d22004-05-09 09:09:59 +0000333/*
334 * The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or
335 * ZEBRA_INTERFACE_DOWN.
336 *
337 * The ZEBRA_INTERFACE_UP message is sent from the zebra server to
338 * the clients in one of 2 situations:
339 * - an if_up is detected e.g., as a result of an RTM_IFINFO message
340 * - a vty command modifying the bandwidth of an interface is received.
341 * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected.
342 */
paul718e3742002-12-13 20:15:29 +0000343int
paulb9df2d22004-05-09 09:09:59 +0000344zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000345{
346 struct stream *s;
347
348 /* Check this client need interface information. */
349 if (! client->ifinfo)
ajs719e9742005-02-28 20:52:15 +0000350 return 0;
paul718e3742002-12-13 20:15:29 +0000351
352 s = client->obuf;
353 stream_reset (s);
354
355 /* Place holder for size. */
356 stream_putw (s, 0);
357
358 /* Zebra command. */
paulb9df2d22004-05-09 09:09:59 +0000359 stream_putc (s, cmd);
paul718e3742002-12-13 20:15:29 +0000360
361 /* Interface information. */
362 stream_put (s, ifp->name, INTERFACE_NAMSIZ);
363 stream_putl (s, ifp->ifindex);
paul2e3b2e42002-12-13 21:03:13 +0000364 stream_putc (s, ifp->status);
paul718e3742002-12-13 20:15:29 +0000365 stream_putl (s, ifp->flags);
366 stream_putl (s, ifp->metric);
367 stream_putl (s, ifp->mtu);
paulb9df2d22004-05-09 09:09:59 +0000368 stream_putl (s, ifp->mtu6);
paul718e3742002-12-13 20:15:29 +0000369 stream_putl (s, ifp->bandwidth);
370
371 /* Write packet size. */
372 stream_putw_at (s, 0, stream_get_endp (s));
373
ajs719e9742005-02-28 20:52:15 +0000374 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000375}
376
paulb9df2d22004-05-09 09:09:59 +0000377/*
378 * The zebra server sends the clients a ZEBRA_IPV4_ROUTE_ADD or a
379 * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following
380 * situations:
381 * - when the client starts up, and requests default information
382 * by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the
383 * - case of rip, ripngd, ospfd and ospf6d, when the client sends a
384 * ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd,
385 * - when the zebra server redistributes routes after it updates its rib
386 *
387 * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a
388 * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when:
389 * - a "ip route" or "ipv6 route" vty command is issued, a prefix is
390 * - deleted from zebra's rib, and this info
391 * has to be redistributed to the clients
392 *
393 * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the
394 * zebra server when the client wants to tell the zebra server to add a
395 * route to the kernel (zapi_ipv4_add etc. ). Since it's essentially the
396 * same message being sent back and forth, this function and
397 * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code
398 * duplication.
399 */
paul718e3742002-12-13 20:15:29 +0000400int
paulb9df2d22004-05-09 09:09:59 +0000401zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p,
402 struct rib *rib)
paul718e3742002-12-13 20:15:29 +0000403{
404 int psize;
405 struct stream *s;
406 struct nexthop *nexthop;
paul1dcb5172005-05-31 08:38:50 +0000407 unsigned long nhnummark = 0, messmark = 0;
paulb9df2d22004-05-09 09:09:59 +0000408 int nhnum = 0;
paul1dcb5172005-05-31 08:38:50 +0000409 u_char zapi_flags = 0;
paulb9df2d22004-05-09 09:09:59 +0000410
paul718e3742002-12-13 20:15:29 +0000411 s = client->obuf;
412 stream_reset (s);
413
414 /* Place holder for size. */
415 stream_putw (s, 0);
416
417 /* Put command, type and nexthop. */
paulb9df2d22004-05-09 09:09:59 +0000418 stream_putc (s, cmd);
paul718e3742002-12-13 20:15:29 +0000419 stream_putc (s, rib->type);
420 stream_putc (s, rib->flags);
paul1dcb5172005-05-31 08:38:50 +0000421
422 /* marker for message flags field */
423 messmark = stream_get_endp (s);
424 stream_putc (s, 0);
paul718e3742002-12-13 20:15:29 +0000425
426 /* Prefix. */
427 psize = PSIZE (p->prefixlen);
428 stream_putc (s, p->prefixlen);
paulb9df2d22004-05-09 09:09:59 +0000429 stream_write (s, (u_char *) & p->u.prefix, psize);
paul718e3742002-12-13 20:15:29 +0000430
paulb9df2d22004-05-09 09:09:59 +0000431 /*
432 * XXX The message format sent by zebra below does not match the format
433 * of the corresponding message expected by the zebra server
434 * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly,
435 * (is there a bug on the client side if more than one segment is sent?)
436 * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX
437 * is hard-coded.
438 */
paul718e3742002-12-13 20:15:29 +0000439 /* Nexthop */
paul1dcb5172005-05-31 08:38:50 +0000440
paul718e3742002-12-13 20:15:29 +0000441 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
442 {
443 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
paulb9df2d22004-05-09 09:09:59 +0000444 {
paul1dcb5172005-05-31 08:38:50 +0000445 SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
446 SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
447
448 if (nhnummark == 0)
449 {
450 nhnummark = stream_get_endp (s);
451 stream_putc (s, 1); /* placeholder */
452 }
453
paulb9df2d22004-05-09 09:09:59 +0000454 nhnum++;
paul718e3742002-12-13 20:15:29 +0000455
paulb9df2d22004-05-09 09:09:59 +0000456 switch(nexthop->type)
457 {
458 case NEXTHOP_TYPE_IPV4:
459 case NEXTHOP_TYPE_IPV4_IFINDEX:
460 stream_put_in_addr (s, &nexthop->gate.ipv4);
461 break;
462#ifdef HAVE_IPV6
463 case NEXTHOP_TYPE_IPV6:
464 case NEXTHOP_TYPE_IPV6_IFINDEX:
465 case NEXTHOP_TYPE_IPV6_IFNAME:
466 stream_write (s, (u_char *) &nexthop->gate.ipv6, 16);
467 break;
468#endif
469 default:
470 if (cmd == ZEBRA_IPV4_ROUTE_ADD
471 || cmd == ZEBRA_IPV4_ROUTE_DELETE)
472 {
473 struct in_addr empty;
paul44983cf2004-09-22 13:15:58 +0000474 memset (&empty, 0, sizeof (struct in_addr));
paulb9df2d22004-05-09 09:09:59 +0000475 stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN);
476 }
477 else
478 {
479 struct in6_addr empty;
480 memset (&empty, 0, sizeof (struct in6_addr));
481 stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN);
482 }
483 }
paul718e3742002-12-13 20:15:29 +0000484
paulb9df2d22004-05-09 09:09:59 +0000485 /* Interface index. */
486 stream_putc (s, 1);
487 stream_putl (s, nexthop->ifindex);
paul718e3742002-12-13 20:15:29 +0000488
paulb9df2d22004-05-09 09:09:59 +0000489 break;
490 }
paul718e3742002-12-13 20:15:29 +0000491 }
492
493 /* Metric */
paul1dcb5172005-05-31 08:38:50 +0000494 if (cmd == ZEBRA_IPV4_ROUTE_ADD || ZEBRA_IPV6_ROUTE_ADD)
495 {
496 SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC);
497 stream_putl (s, rib->metric);
498 }
499
500 /* write real message flags value */
501 stream_putc_at (s, messmark, zapi_flags);
502
paulb9df2d22004-05-09 09:09:59 +0000503 /* Write next-hop number */
504 if (nhnummark)
hassoc1eaa442004-10-19 06:26:01 +0000505 stream_putc_at (s, nhnummark, nhnum);
paulb9df2d22004-05-09 09:09:59 +0000506
paul718e3742002-12-13 20:15:29 +0000507 /* Write packet size. */
508 stream_putw_at (s, 0, stream_get_endp (s));
509
ajs719e9742005-02-28 20:52:15 +0000510 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000511}
512
paul718e3742002-12-13 20:15:29 +0000513#ifdef HAVE_IPV6
ajs719e9742005-02-28 20:52:15 +0000514static int
paul718e3742002-12-13 20:15:29 +0000515zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr)
516{
517 struct stream *s;
518 struct rib *rib;
519 unsigned long nump;
520 u_char num;
521 struct nexthop *nexthop;
522
523 /* Lookup nexthop. */
524 rib = rib_match_ipv6 (addr);
525
526 /* Get output stream. */
527 s = client->obuf;
528 stream_reset (s);
529
530 /* Fill in result. */
531 stream_putw (s, 0);
532 stream_putc (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
533 stream_put (s, &addr, 16);
534
535 if (rib)
536 {
537 stream_putl (s, rib->metric);
538 num = 0;
paul9985f832005-02-09 15:51:56 +0000539 nump = stream_get_endp(s);
paul718e3742002-12-13 20:15:29 +0000540 stream_putc (s, 0);
541 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
542 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
543 {
544 stream_putc (s, nexthop->type);
545 switch (nexthop->type)
546 {
547 case ZEBRA_NEXTHOP_IPV6:
548 stream_put (s, &nexthop->gate.ipv6, 16);
549 break;
550 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
551 case ZEBRA_NEXTHOP_IPV6_IFNAME:
552 stream_put (s, &nexthop->gate.ipv6, 16);
553 stream_putl (s, nexthop->ifindex);
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#endif /* HAVE_IPV6 */
578
paulb9df2d22004-05-09 09:09:59 +0000579static int
paul718e3742002-12-13 20:15:29 +0000580zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
581{
582 struct stream *s;
583 struct rib *rib;
584 unsigned long nump;
585 u_char num;
586 struct nexthop *nexthop;
587
588 /* Lookup nexthop. */
589 rib = rib_match_ipv4 (addr);
590
591 /* Get output stream. */
592 s = client->obuf;
593 stream_reset (s);
594
595 /* Fill in result. */
596 stream_putw (s, 0);
597 stream_putc (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
598 stream_put_in_addr (s, &addr);
599
600 if (rib)
601 {
602 stream_putl (s, rib->metric);
603 num = 0;
paul9985f832005-02-09 15:51:56 +0000604 nump = stream_get_endp(s);
paul718e3742002-12-13 20:15:29 +0000605 stream_putc (s, 0);
606 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
607 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
608 {
609 stream_putc (s, nexthop->type);
610 switch (nexthop->type)
611 {
612 case ZEBRA_NEXTHOP_IPV4:
613 stream_put_in_addr (s, &nexthop->gate.ipv4);
614 break;
615 case ZEBRA_NEXTHOP_IFINDEX:
616 case ZEBRA_NEXTHOP_IFNAME:
617 stream_putl (s, nexthop->ifindex);
618 break;
hassofa2b17e2004-03-04 17:45:00 +0000619 default:
620 /* do nothing */
621 break;
paul718e3742002-12-13 20:15:29 +0000622 }
623 num++;
624 }
625 stream_putc_at (s, nump, num);
626 }
627 else
628 {
629 stream_putl (s, 0);
630 stream_putc (s, 0);
631 }
632
633 stream_putw_at (s, 0, stream_get_endp (s));
634
ajs719e9742005-02-28 20:52:15 +0000635 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000636}
637
paulb9df2d22004-05-09 09:09:59 +0000638static int
paul718e3742002-12-13 20:15:29 +0000639zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
640{
641 struct stream *s;
642 struct rib *rib;
643 unsigned long nump;
644 u_char num;
645 struct nexthop *nexthop;
646
647 /* Lookup nexthop. */
648 rib = rib_lookup_ipv4 (p);
649
650 /* Get output stream. */
651 s = client->obuf;
652 stream_reset (s);
653
654 /* Fill in result. */
655 stream_putw (s, 0);
656 stream_putc (s, ZEBRA_IPV4_IMPORT_LOOKUP);
657 stream_put_in_addr (s, &p->prefix);
658
659 if (rib)
660 {
661 stream_putl (s, rib->metric);
662 num = 0;
paul9985f832005-02-09 15:51:56 +0000663 nump = stream_get_endp(s);
paul718e3742002-12-13 20:15:29 +0000664 stream_putc (s, 0);
665 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
666 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
667 {
668 stream_putc (s, nexthop->type);
669 switch (nexthop->type)
670 {
671 case ZEBRA_NEXTHOP_IPV4:
672 stream_put_in_addr (s, &nexthop->gate.ipv4);
673 break;
674 case ZEBRA_NEXTHOP_IFINDEX:
675 case ZEBRA_NEXTHOP_IFNAME:
676 stream_putl (s, nexthop->ifindex);
677 break;
hassofa2b17e2004-03-04 17:45:00 +0000678 default:
679 /* do nothing */
680 break;
paul718e3742002-12-13 20:15:29 +0000681 }
682 num++;
683 }
684 stream_putc_at (s, nump, num);
685 }
686 else
687 {
688 stream_putl (s, 0);
689 stream_putc (s, 0);
690 }
691
692 stream_putw_at (s, 0, stream_get_endp (s));
693
ajs719e9742005-02-28 20:52:15 +0000694 return zebra_server_send_message(client);
paul718e3742002-12-13 20:15:29 +0000695}
696
hasso18a6dce2004-10-03 18:18:34 +0000697/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
698int
699zsend_router_id_update (struct zserv *client, struct prefix *p)
700{
701 struct stream *s;
702 int blen;
703
704 /* Check this client need interface information. */
705 if (!client->ridinfo)
ajs719e9742005-02-28 20:52:15 +0000706 return 0;
hasso18a6dce2004-10-03 18:18:34 +0000707
708 s = client->obuf;
709 stream_reset (s);
710
711 /* Place holder for size. */
712 stream_putw (s, 0);
713
714 /* Message type. */
715 stream_putc (s, ZEBRA_ROUTER_ID_UPDATE);
716
717 /* Prefix information. */
718 stream_putc (s, p->family);
719 blen = prefix_blen (p);
720 stream_put (s, &p->u.prefix, blen);
721 stream_putc (s, p->prefixlen);
722
723 /* Write packet size. */
724 stream_putw_at (s, 0, stream_get_endp (s));
725
ajs719e9742005-02-28 20:52:15 +0000726 return zebra_server_send_message(client);
hasso18a6dce2004-10-03 18:18:34 +0000727}
728
paul718e3742002-12-13 20:15:29 +0000729/* Register zebra server interface information. Send current all
730 interface and address information. */
ajs719e9742005-02-28 20:52:15 +0000731static int
paul718e3742002-12-13 20:15:29 +0000732zread_interface_add (struct zserv *client, u_short length)
733{
paul1eb8ef22005-04-07 07:30:20 +0000734 struct listnode *ifnode, *ifnnode;
735 struct listnode *cnode, *cnnode;
paul718e3742002-12-13 20:15:29 +0000736 struct interface *ifp;
737 struct connected *c;
738
739 /* Interface information is needed. */
740 client->ifinfo = 1;
741
paul1eb8ef22005-04-07 07:30:20 +0000742 for (ALL_LIST_ELEMENTS (iflist, ifnode, ifnnode, ifp))
paul718e3742002-12-13 20:15:29 +0000743 {
paul718e3742002-12-13 20:15:29 +0000744 /* Skip pseudo interface. */
745 if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
746 continue;
747
ajs719e9742005-02-28 20:52:15 +0000748 if (zsend_interface_add (client, ifp) < 0)
749 return -1;
paul718e3742002-12-13 20:15:29 +0000750
paul1eb8ef22005-04-07 07:30:20 +0000751 for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
paul718e3742002-12-13 20:15:29 +0000752 {
ajs719e9742005-02-28 20:52:15 +0000753 if (CHECK_FLAG (c->conf, ZEBRA_IFC_REAL) &&
754 (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client,
755 ifp, c) < 0))
756 return -1;
paul718e3742002-12-13 20:15:29 +0000757 }
758 }
ajs719e9742005-02-28 20:52:15 +0000759 return 0;
paul718e3742002-12-13 20:15:29 +0000760}
761
762/* Unregister zebra server interface information. */
ajs719e9742005-02-28 20:52:15 +0000763static int
paul718e3742002-12-13 20:15:29 +0000764zread_interface_delete (struct zserv *client, u_short length)
765{
766 client->ifinfo = 0;
ajs719e9742005-02-28 20:52:15 +0000767 return 0;
paul718e3742002-12-13 20:15:29 +0000768}
769
770/* This function support multiple nexthop. */
paulb9df2d22004-05-09 09:09:59 +0000771/*
772 * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update rib and
773 * add kernel route.
774 */
ajs719e9742005-02-28 20:52:15 +0000775static int
paul718e3742002-12-13 20:15:29 +0000776zread_ipv4_add (struct zserv *client, u_short length)
777{
778 int i;
779 struct rib *rib;
780 struct prefix_ipv4 p;
781 u_char message;
782 struct in_addr nexthop;
783 u_char nexthop_num;
784 u_char nexthop_type;
785 struct stream *s;
786 unsigned int ifindex;
787 u_char ifname_len;
788
789 /* Get input stream. */
790 s = client->ibuf;
791
792 /* Allocate new rib. */
paul4d38fdb2005-04-28 17:35:14 +0000793 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
794
paul718e3742002-12-13 20:15:29 +0000795 /* Type, flags, message. */
796 rib->type = stream_getc (s);
797 rib->flags = stream_getc (s);
paulb9df2d22004-05-09 09:09:59 +0000798 message = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000799 rib->uptime = time (NULL);
800
801 /* IPv4 prefix. */
802 memset (&p, 0, sizeof (struct prefix_ipv4));
803 p.family = AF_INET;
804 p.prefixlen = stream_getc (s);
805 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
806
807 /* Nexthop parse. */
808 if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
809 {
810 nexthop_num = stream_getc (s);
811
812 for (i = 0; i < nexthop_num; i++)
813 {
814 nexthop_type = stream_getc (s);
815
816 switch (nexthop_type)
817 {
818 case ZEBRA_NEXTHOP_IFINDEX:
819 ifindex = stream_getl (s);
820 nexthop_ifindex_add (rib, ifindex);
821 break;
822 case ZEBRA_NEXTHOP_IFNAME:
823 ifname_len = stream_getc (s);
paul9985f832005-02-09 15:51:56 +0000824 stream_forward_getp (s, ifname_len);
paul718e3742002-12-13 20:15:29 +0000825 break;
826 case ZEBRA_NEXTHOP_IPV4:
827 nexthop.s_addr = stream_get_ipv4 (s);
828 nexthop_ipv4_add (rib, &nexthop);
829 break;
830 case ZEBRA_NEXTHOP_IPV6:
paul9985f832005-02-09 15:51:56 +0000831 stream_forward_getp (s, IPV6_MAX_BYTELEN);
paul718e3742002-12-13 20:15:29 +0000832 break;
paul595db7f2003-05-25 21:35:06 +0000833 case ZEBRA_NEXTHOP_BLACKHOLE:
834 nexthop_blackhole_add (rib);
835 break;
paul718e3742002-12-13 20:15:29 +0000836 }
837 }
838 }
839
840 /* Distance. */
841 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
842 rib->distance = stream_getc (s);
843
844 /* Metric. */
845 if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
846 rib->metric = stream_getl (s);
847
848 rib_add_ipv4_multipath (&p, rib);
ajs719e9742005-02-28 20:52:15 +0000849 return 0;
paul718e3742002-12-13 20:15:29 +0000850}
851
852/* Zebra server IPv4 prefix delete function. */
ajs719e9742005-02-28 20:52:15 +0000853static int
paul718e3742002-12-13 20:15:29 +0000854zread_ipv4_delete (struct zserv *client, u_short length)
855{
856 int i;
857 struct stream *s;
858 struct zapi_ipv4 api;
859 struct in_addr nexthop;
860 unsigned long ifindex;
861 struct prefix_ipv4 p;
862 u_char nexthop_num;
863 u_char nexthop_type;
864 u_char ifname_len;
865
866 s = client->ibuf;
867 ifindex = 0;
868 nexthop.s_addr = 0;
869
870 /* Type, flags, message. */
871 api.type = stream_getc (s);
872 api.flags = stream_getc (s);
873 api.message = stream_getc (s);
874
875 /* IPv4 prefix. */
876 memset (&p, 0, sizeof (struct prefix_ipv4));
877 p.family = AF_INET;
878 p.prefixlen = stream_getc (s);
879 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
880
881 /* Nexthop, ifindex, distance, metric. */
882 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
883 {
884 nexthop_num = stream_getc (s);
885
886 for (i = 0; i < nexthop_num; i++)
887 {
888 nexthop_type = stream_getc (s);
889
890 switch (nexthop_type)
891 {
892 case ZEBRA_NEXTHOP_IFINDEX:
893 ifindex = stream_getl (s);
894 break;
895 case ZEBRA_NEXTHOP_IFNAME:
896 ifname_len = stream_getc (s);
paul9985f832005-02-09 15:51:56 +0000897 stream_forward_getp (s, ifname_len);
paul718e3742002-12-13 20:15:29 +0000898 break;
899 case ZEBRA_NEXTHOP_IPV4:
900 nexthop.s_addr = stream_get_ipv4 (s);
901 break;
902 case ZEBRA_NEXTHOP_IPV6:
paul9985f832005-02-09 15:51:56 +0000903 stream_forward_getp (s, IPV6_MAX_BYTELEN);
paul718e3742002-12-13 20:15:29 +0000904 break;
905 }
906 }
907 }
908
909 /* Distance. */
910 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
911 api.distance = stream_getc (s);
912 else
913 api.distance = 0;
914
915 /* Metric. */
916 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
917 api.metric = stream_getl (s);
918 else
919 api.metric = 0;
920
921 rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex,
922 client->rtm_table);
ajs719e9742005-02-28 20:52:15 +0000923 return 0;
paul718e3742002-12-13 20:15:29 +0000924}
925
926/* Nexthop lookup for IPv4. */
ajs719e9742005-02-28 20:52:15 +0000927static int
paul718e3742002-12-13 20:15:29 +0000928zread_ipv4_nexthop_lookup (struct zserv *client, u_short length)
929{
930 struct in_addr addr;
931
932 addr.s_addr = stream_get_ipv4 (client->ibuf);
ajs719e9742005-02-28 20:52:15 +0000933 return zsend_ipv4_nexthop_lookup (client, addr);
paul718e3742002-12-13 20:15:29 +0000934}
935
936/* Nexthop lookup for IPv4. */
ajs719e9742005-02-28 20:52:15 +0000937static int
paul718e3742002-12-13 20:15:29 +0000938zread_ipv4_import_lookup (struct zserv *client, u_short length)
939{
940 struct prefix_ipv4 p;
941
942 p.family = AF_INET;
943 p.prefixlen = stream_getc (client->ibuf);
944 p.prefix.s_addr = stream_get_ipv4 (client->ibuf);
945
ajs719e9742005-02-28 20:52:15 +0000946 return zsend_ipv4_import_lookup (client, &p);
paul718e3742002-12-13 20:15:29 +0000947}
948
949#ifdef HAVE_IPV6
950/* Zebra server IPv6 prefix add function. */
ajs719e9742005-02-28 20:52:15 +0000951static int
paul718e3742002-12-13 20:15:29 +0000952zread_ipv6_add (struct zserv *client, u_short length)
953{
954 int i;
955 struct stream *s;
956 struct zapi_ipv6 api;
957 struct in6_addr nexthop;
958 unsigned long ifindex;
959 struct prefix_ipv6 p;
960
961 s = client->ibuf;
962 ifindex = 0;
963 memset (&nexthop, 0, sizeof (struct in6_addr));
964
965 /* Type, flags, message. */
966 api.type = stream_getc (s);
967 api.flags = stream_getc (s);
968 api.message = stream_getc (s);
969
970 /* IPv4 prefix. */
971 memset (&p, 0, sizeof (struct prefix_ipv6));
972 p.family = AF_INET6;
973 p.prefixlen = stream_getc (s);
974 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
975
976 /* Nexthop, ifindex, distance, metric. */
977 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
978 {
979 u_char nexthop_type;
980
981 api.nexthop_num = stream_getc (s);
982 for (i = 0; i < api.nexthop_num; i++)
983 {
984 nexthop_type = stream_getc (s);
985
986 switch (nexthop_type)
987 {
988 case ZEBRA_NEXTHOP_IPV6:
989 stream_get (&nexthop, s, 16);
990 break;
991 case ZEBRA_NEXTHOP_IFINDEX:
992 ifindex = stream_getl (s);
993 break;
994 }
995 }
996 }
997
998 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
999 api.distance = stream_getc (s);
1000 else
1001 api.distance = 0;
1002
1003 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
1004 api.metric = stream_getl (s);
1005 else
1006 api.metric = 0;
1007
1008 if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
1009 rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0);
1010 else
1011 rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0);
ajs719e9742005-02-28 20:52:15 +00001012 return 0;
paul718e3742002-12-13 20:15:29 +00001013}
1014
1015/* Zebra server IPv6 prefix delete function. */
ajs719e9742005-02-28 20:52:15 +00001016static int
paul718e3742002-12-13 20:15:29 +00001017zread_ipv6_delete (struct zserv *client, u_short length)
1018{
1019 int i;
1020 struct stream *s;
1021 struct zapi_ipv6 api;
1022 struct in6_addr nexthop;
1023 unsigned long ifindex;
1024 struct prefix_ipv6 p;
1025
1026 s = client->ibuf;
1027 ifindex = 0;
1028 memset (&nexthop, 0, sizeof (struct in6_addr));
1029
1030 /* Type, flags, message. */
1031 api.type = stream_getc (s);
1032 api.flags = stream_getc (s);
1033 api.message = stream_getc (s);
1034
1035 /* IPv4 prefix. */
1036 memset (&p, 0, sizeof (struct prefix_ipv6));
1037 p.family = AF_INET6;
1038 p.prefixlen = stream_getc (s);
1039 stream_get (&p.prefix, s, PSIZE (p.prefixlen));
1040
1041 /* Nexthop, ifindex, distance, metric. */
1042 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
1043 {
1044 u_char nexthop_type;
1045
1046 api.nexthop_num = stream_getc (s);
1047 for (i = 0; i < api.nexthop_num; i++)
1048 {
1049 nexthop_type = stream_getc (s);
1050
1051 switch (nexthop_type)
1052 {
1053 case ZEBRA_NEXTHOP_IPV6:
1054 stream_get (&nexthop, s, 16);
1055 break;
1056 case ZEBRA_NEXTHOP_IFINDEX:
1057 ifindex = stream_getl (s);
1058 break;
1059 }
1060 }
1061 }
1062
1063 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
1064 api.distance = stream_getc (s);
1065 else
1066 api.distance = 0;
1067 if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
1068 api.metric = stream_getl (s);
1069 else
1070 api.metric = 0;
1071
1072 if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
1073 rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0);
1074 else
1075 rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0);
ajs719e9742005-02-28 20:52:15 +00001076 return 0;
paul718e3742002-12-13 20:15:29 +00001077}
1078
ajs719e9742005-02-28 20:52:15 +00001079static int
paul718e3742002-12-13 20:15:29 +00001080zread_ipv6_nexthop_lookup (struct zserv *client, u_short length)
1081{
1082 struct in6_addr addr;
1083 char buf[BUFSIZ];
1084
1085 stream_get (&addr, client->ibuf, 16);
1086 printf ("DEBUG %s\n", inet_ntop (AF_INET6, &addr, buf, BUFSIZ));
1087
ajs719e9742005-02-28 20:52:15 +00001088 return zsend_ipv6_nexthop_lookup (client, &addr);
paul718e3742002-12-13 20:15:29 +00001089}
1090#endif /* HAVE_IPV6 */
1091
hasso18a6dce2004-10-03 18:18:34 +00001092/* Register zebra server router-id information. Send current router-id */
ajs719e9742005-02-28 20:52:15 +00001093static int
hasso18a6dce2004-10-03 18:18:34 +00001094zread_router_id_add (struct zserv *client, u_short length)
1095{
1096 struct prefix p;
1097
1098 /* Router-id information is needed. */
1099 client->ridinfo = 1;
1100
1101 router_id_get (&p);
1102
ajs719e9742005-02-28 20:52:15 +00001103 return zsend_router_id_update (client,&p);
hasso18a6dce2004-10-03 18:18:34 +00001104}
1105
1106/* Unregister zebra server router-id information. */
ajs719e9742005-02-28 20:52:15 +00001107static int
hasso18a6dce2004-10-03 18:18:34 +00001108zread_router_id_delete (struct zserv *client, u_short length)
1109{
1110 client->ridinfo = 0;
ajs719e9742005-02-28 20:52:15 +00001111 return 0;
hasso18a6dce2004-10-03 18:18:34 +00001112}
1113
paul718e3742002-12-13 20:15:29 +00001114/* Close zebra client. */
paulb9df2d22004-05-09 09:09:59 +00001115static void
paul718e3742002-12-13 20:15:29 +00001116zebra_client_close (struct zserv *client)
1117{
1118 /* Close file descriptor. */
1119 if (client->sock)
1120 {
1121 close (client->sock);
1122 client->sock = -1;
1123 }
1124
1125 /* Free stream buffers. */
1126 if (client->ibuf)
1127 stream_free (client->ibuf);
1128 if (client->obuf)
1129 stream_free (client->obuf);
ajs719e9742005-02-28 20:52:15 +00001130 if (client->wb)
1131 buffer_free(client->wb);
paul718e3742002-12-13 20:15:29 +00001132
1133 /* Release threads. */
1134 if (client->t_read)
1135 thread_cancel (client->t_read);
1136 if (client->t_write)
1137 thread_cancel (client->t_write);
ajs719e9742005-02-28 20:52:15 +00001138 if (client->t_suicide)
1139 thread_cancel (client->t_suicide);
paul718e3742002-12-13 20:15:29 +00001140
1141 /* Free client structure. */
paulb21b19c2003-06-15 01:28:29 +00001142 listnode_delete (zebrad.client_list, client);
paul718e3742002-12-13 20:15:29 +00001143 XFREE (0, client);
1144}
1145
1146/* Make new client. */
paulb9df2d22004-05-09 09:09:59 +00001147static void
paul718e3742002-12-13 20:15:29 +00001148zebra_client_create (int sock)
1149{
1150 struct zserv *client;
1151
1152 client = XCALLOC (0, sizeof (struct zserv));
1153
1154 /* Make client input/output buffer. */
1155 client->sock = sock;
1156 client->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
1157 client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
ajs719e9742005-02-28 20:52:15 +00001158 client->wb = buffer_new(0);
paul718e3742002-12-13 20:15:29 +00001159
1160 /* Set table number. */
paulb21b19c2003-06-15 01:28:29 +00001161 client->rtm_table = zebrad.rtm_table_default;
paul718e3742002-12-13 20:15:29 +00001162
1163 /* Add this client to linked list. */
paulb21b19c2003-06-15 01:28:29 +00001164 listnode_add (zebrad.client_list, client);
paul718e3742002-12-13 20:15:29 +00001165
1166 /* Make new read thread. */
1167 zebra_event (ZEBRA_READ, sock, client);
1168}
1169
1170/* Handler of zebra service request. */
paulb9df2d22004-05-09 09:09:59 +00001171static int
paul718e3742002-12-13 20:15:29 +00001172zebra_client_read (struct thread *thread)
1173{
1174 int sock;
1175 struct zserv *client;
ajs57a14772005-04-10 15:01:56 +00001176 size_t already;
paul718e3742002-12-13 20:15:29 +00001177 u_short length;
1178 u_char command;
1179
1180 /* Get thread data. Reset reading thread because I'm running. */
1181 sock = THREAD_FD (thread);
1182 client = THREAD_ARG (thread);
1183 client->t_read = NULL;
1184
ajs719e9742005-02-28 20:52:15 +00001185 if (client->t_suicide)
paul718e3742002-12-13 20:15:29 +00001186 {
ajs719e9742005-02-28 20:52:15 +00001187 zebra_client_close(client);
paul718e3742002-12-13 20:15:29 +00001188 return -1;
1189 }
ajs719e9742005-02-28 20:52:15 +00001190
1191 /* Read length and command (if we don't have it already). */
ajs57a14772005-04-10 15:01:56 +00001192 if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE)
ajs719e9742005-02-28 20:52:15 +00001193 {
ajs57a14772005-04-10 15:01:56 +00001194 ssize_t nbyte;
ajs719e9742005-02-28 20:52:15 +00001195 if (((nbyte = stream_read_try (client->ibuf, sock,
ajs57a14772005-04-10 15:01:56 +00001196 ZEBRA_HEADER_SIZE-already)) == 0) ||
ajs719e9742005-02-28 20:52:15 +00001197 (nbyte == -1))
1198 {
1199 if (IS_ZEBRA_DEBUG_EVENT)
1200 zlog_debug ("connection closed socket [%d]", sock);
1201 zebra_client_close (client);
1202 return -1;
1203 }
ajs57a14772005-04-10 15:01:56 +00001204 if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
ajs719e9742005-02-28 20:52:15 +00001205 {
1206 /* Try again later. */
1207 zebra_event (ZEBRA_READ, sock, client);
1208 return 0;
1209 }
ajs57a14772005-04-10 15:01:56 +00001210 already = ZEBRA_HEADER_SIZE;
ajs719e9742005-02-28 20:52:15 +00001211 }
1212
1213 /* Reset to read from the beginning of the incoming packet. */
1214 stream_set_getp(client->ibuf, 0);
1215
paul718e3742002-12-13 20:15:29 +00001216 length = stream_getw (client->ibuf);
1217 command = stream_getc (client->ibuf);
1218
ajs719e9742005-02-28 20:52:15 +00001219 if (length < ZEBRA_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00001220 {
ajs57a14772005-04-10 15:01:56 +00001221 zlog_warn("%s: socket %d message length %u is less than header size %d",
1222 __func__, sock, length, ZEBRA_HEADER_SIZE);
1223 zebra_client_close (client);
1224 return -1;
1225 }
1226 if (length > STREAM_SIZE(client->ibuf))
1227 {
1228 zlog_warn("%s: socket %d message length %u exceeds buffer size %lu",
1229 __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf));
paul718e3742002-12-13 20:15:29 +00001230 zebra_client_close (client);
1231 return -1;
1232 }
1233
paul718e3742002-12-13 20:15:29 +00001234 /* Read rest of data. */
ajs57a14772005-04-10 15:01:56 +00001235 if (already < length)
paul718e3742002-12-13 20:15:29 +00001236 {
ajs57a14772005-04-10 15:01:56 +00001237 ssize_t nbyte;
1238 if (((nbyte = stream_read_try (client->ibuf, sock,
1239 length-already)) == 0) ||
1240 (nbyte == -1))
paul718e3742002-12-13 20:15:29 +00001241 {
1242 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +00001243 zlog_debug ("connection closed [%d] when reading zebra data", sock);
paul718e3742002-12-13 20:15:29 +00001244 zebra_client_close (client);
1245 return -1;
1246 }
ajs57a14772005-04-10 15:01:56 +00001247 if (nbyte != (ssize_t)(length-already))
ajs719e9742005-02-28 20:52:15 +00001248 {
1249 /* Try again later. */
1250 zebra_event (ZEBRA_READ, sock, client);
1251 return 0;
1252 }
paul718e3742002-12-13 20:15:29 +00001253 }
1254
ajs719e9742005-02-28 20:52:15 +00001255 length -= ZEBRA_HEADER_SIZE;
1256
paul718e3742002-12-13 20:15:29 +00001257 /* Debug packet information. */
1258 if (IS_ZEBRA_DEBUG_EVENT)
ajsb6178002004-12-07 21:12:56 +00001259 zlog_debug ("zebra message comes from socket [%d]", sock);
paul718e3742002-12-13 20:15:29 +00001260
1261 if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
ajsb6178002004-12-07 21:12:56 +00001262 zlog_debug ("zebra message received [%s] %d",
paul718e3742002-12-13 20:15:29 +00001263 zebra_command_str[command], length);
1264
1265 switch (command)
1266 {
hasso18a6dce2004-10-03 18:18:34 +00001267 case ZEBRA_ROUTER_ID_ADD:
1268 zread_router_id_add (client, length);
1269 break;
1270 case ZEBRA_ROUTER_ID_DELETE:
1271 zread_router_id_delete (client, length);
1272 break;
paul718e3742002-12-13 20:15:29 +00001273 case ZEBRA_INTERFACE_ADD:
1274 zread_interface_add (client, length);
1275 break;
1276 case ZEBRA_INTERFACE_DELETE:
1277 zread_interface_delete (client, length);
1278 break;
1279 case ZEBRA_IPV4_ROUTE_ADD:
1280 zread_ipv4_add (client, length);
1281 break;
1282 case ZEBRA_IPV4_ROUTE_DELETE:
1283 zread_ipv4_delete (client, length);
1284 break;
1285#ifdef HAVE_IPV6
1286 case ZEBRA_IPV6_ROUTE_ADD:
1287 zread_ipv6_add (client, length);
1288 break;
1289 case ZEBRA_IPV6_ROUTE_DELETE:
1290 zread_ipv6_delete (client, length);
1291 break;
1292#endif /* HAVE_IPV6 */
1293 case ZEBRA_REDISTRIBUTE_ADD:
1294 zebra_redistribute_add (command, client, length);
1295 break;
1296 case ZEBRA_REDISTRIBUTE_DELETE:
1297 zebra_redistribute_delete (command, client, length);
1298 break;
1299 case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
1300 zebra_redistribute_default_add (command, client, length);
1301 break;
1302 case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
1303 zebra_redistribute_default_delete (command, client, length);
1304 break;
1305 case ZEBRA_IPV4_NEXTHOP_LOOKUP:
1306 zread_ipv4_nexthop_lookup (client, length);
1307 break;
1308#ifdef HAVE_IPV6
1309 case ZEBRA_IPV6_NEXTHOP_LOOKUP:
1310 zread_ipv6_nexthop_lookup (client, length);
1311 break;
1312#endif /* HAVE_IPV6 */
1313 case ZEBRA_IPV4_IMPORT_LOOKUP:
1314 zread_ipv4_import_lookup (client, length);
1315 break;
1316 default:
1317 zlog_info ("Zebra received unknown command %d", command);
1318 break;
1319 }
1320
ajs719e9742005-02-28 20:52:15 +00001321 if (client->t_suicide)
1322 {
1323 /* No need to wait for thread callback, just kill immediately. */
1324 zebra_client_close(client);
1325 return -1;
1326 }
1327
paul718e3742002-12-13 20:15:29 +00001328 stream_reset (client->ibuf);
1329 zebra_event (ZEBRA_READ, sock, client);
paul718e3742002-12-13 20:15:29 +00001330 return 0;
1331}
1332
paul718e3742002-12-13 20:15:29 +00001333
1334/* Accept code of zebra server socket. */
paulb9df2d22004-05-09 09:09:59 +00001335static int
paul718e3742002-12-13 20:15:29 +00001336zebra_accept (struct thread *thread)
1337{
1338 int accept_sock;
1339 int client_sock;
1340 struct sockaddr_in client;
1341 socklen_t len;
1342
1343 accept_sock = THREAD_FD (thread);
1344
ajs719e9742005-02-28 20:52:15 +00001345 /* Reregister myself. */
1346 zebra_event (ZEBRA_SERV, accept_sock, NULL);
1347
paul718e3742002-12-13 20:15:29 +00001348 len = sizeof (struct sockaddr_in);
1349 client_sock = accept (accept_sock, (struct sockaddr *) &client, &len);
1350
1351 if (client_sock < 0)
1352 {
ajs6099b3b2004-11-20 02:06:59 +00001353 zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001354 return -1;
1355 }
1356
paulccf35572003-03-01 11:42:20 +00001357 /* Make client socket non-blocking. */
ajs719e9742005-02-28 20:52:15 +00001358 set_nonblocking(client_sock);
paul865b8522005-01-05 08:30:35 +00001359
paul718e3742002-12-13 20:15:29 +00001360 /* Create new zebra client. */
1361 zebra_client_create (client_sock);
1362
paul718e3742002-12-13 20:15:29 +00001363 return 0;
1364}
1365
paulb9df2d22004-05-09 09:09:59 +00001366#ifdef HAVE_TCP_ZEBRA
paul718e3742002-12-13 20:15:29 +00001367/* Make zebra's server socket. */
paulb9df2d22004-05-09 09:09:59 +00001368static void
paul718e3742002-12-13 20:15:29 +00001369zebra_serv ()
1370{
1371 int ret;
1372 int accept_sock;
1373 struct sockaddr_in addr;
1374
1375 accept_sock = socket (AF_INET, SOCK_STREAM, 0);
1376
1377 if (accept_sock < 0)
1378 {
paul3d1dc852005-04-05 00:45:23 +00001379 zlog_warn ("Can't create zserv stream socket: %s",
1380 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001381 zlog_warn ("zebra can't provice full functionality due to above error");
1382 return;
1383 }
1384
1385 memset (&addr, 0, sizeof (struct sockaddr_in));
1386 addr.sin_family = AF_INET;
1387 addr.sin_port = htons (ZEBRA_PORT);
1388#ifdef HAVE_SIN_LEN
1389 addr.sin_len = sizeof (struct sockaddr_in);
1390#endif /* HAVE_SIN_LEN */
1391 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1392
1393 sockopt_reuseaddr (accept_sock);
1394 sockopt_reuseport (accept_sock);
1395
pauledd7c242003-06-04 13:59:38 +00001396 if ( zserv_privs.change(ZPRIVS_RAISE) )
1397 zlog (NULL, LOG_ERR, "Can't raise privileges");
1398
paul718e3742002-12-13 20:15:29 +00001399 ret = bind (accept_sock, (struct sockaddr *)&addr,
1400 sizeof (struct sockaddr_in));
1401 if (ret < 0)
1402 {
paul3d1dc852005-04-05 00:45:23 +00001403 zlog_warn ("Can't bind to stream socket: %s",
1404 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001405 zlog_warn ("zebra can't provice full functionality due to above error");
1406 close (accept_sock); /* Avoid sd leak. */
1407 return;
1408 }
pauledd7c242003-06-04 13:59:38 +00001409
1410 if ( zserv_privs.change(ZPRIVS_LOWER) )
1411 zlog (NULL, LOG_ERR, "Can't lower privileges");
paul718e3742002-12-13 20:15:29 +00001412
1413 ret = listen (accept_sock, 1);
1414 if (ret < 0)
1415 {
paul3d1dc852005-04-05 00:45:23 +00001416 zlog_warn ("Can't listen to stream socket: %s",
1417 safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001418 zlog_warn ("zebra can't provice full functionality due to above error");
1419 close (accept_sock); /* Avoid sd leak. */
1420 return;
1421 }
1422
1423 zebra_event (ZEBRA_SERV, accept_sock, NULL);
1424}
paulb9df2d22004-05-09 09:09:59 +00001425#endif /* HAVE_TCP_ZEBRA */
paul718e3742002-12-13 20:15:29 +00001426
1427/* For sockaddr_un. */
1428#include <sys/un.h>
1429
1430/* zebra server UNIX domain socket. */
paulb9df2d22004-05-09 09:09:59 +00001431static void
hassofce954f2004-10-07 20:29:24 +00001432zebra_serv_un (const char *path)
paul718e3742002-12-13 20:15:29 +00001433{
1434 int ret;
1435 int sock, len;
1436 struct sockaddr_un serv;
1437 mode_t old_mask;
1438
1439 /* First of all, unlink existing socket */
1440 unlink (path);
1441
1442 /* Set umask */
1443 old_mask = umask (0077);
1444
1445 /* Make UNIX domain socket. */
1446 sock = socket (AF_UNIX, SOCK_STREAM, 0);
1447 if (sock < 0)
1448 {
paul3d1dc852005-04-05 00:45:23 +00001449 zlog_warn ("Can't create zserv unix socket: %s",
1450 safe_strerror (errno));
1451 zlog_warn ("zebra can't provide full functionality due to above error");
paul718e3742002-12-13 20:15:29 +00001452 return;
1453 }
1454
1455 /* Make server socket. */
1456 memset (&serv, 0, sizeof (struct sockaddr_un));
1457 serv.sun_family = AF_UNIX;
1458 strncpy (serv.sun_path, path, strlen (path));
1459#ifdef HAVE_SUN_LEN
1460 len = serv.sun_len = SUN_LEN(&serv);
1461#else
1462 len = sizeof (serv.sun_family) + strlen (serv.sun_path);
1463#endif /* HAVE_SUN_LEN */
1464
1465 ret = bind (sock, (struct sockaddr *) &serv, len);
1466 if (ret < 0)
1467 {
paul3d1dc852005-04-05 00:45:23 +00001468 zlog_warn ("Can't bind to unix socket %s: %s",
1469 path, safe_strerror (errno));
1470 zlog_warn ("zebra can't provide full functionality due to above error");
paul718e3742002-12-13 20:15:29 +00001471 close (sock);
1472 return;
1473 }
1474
1475 ret = listen (sock, 5);
1476 if (ret < 0)
1477 {
paul3d1dc852005-04-05 00:45:23 +00001478 zlog_warn ("Can't listen to unix socket %s: %s",
1479 path, safe_strerror (errno));
1480 zlog_warn ("zebra can't provide full functionality due to above error");
paul718e3742002-12-13 20:15:29 +00001481 close (sock);
1482 return;
1483 }
1484
1485 umask (old_mask);
1486
1487 zebra_event (ZEBRA_SERV, sock, NULL);
1488}
1489
paul718e3742002-12-13 20:15:29 +00001490
paulb9df2d22004-05-09 09:09:59 +00001491static void
paul718e3742002-12-13 20:15:29 +00001492zebra_event (enum event event, int sock, struct zserv *client)
1493{
1494 switch (event)
1495 {
1496 case ZEBRA_SERV:
paulb21b19c2003-06-15 01:28:29 +00001497 thread_add_read (zebrad.master, zebra_accept, client, sock);
paul718e3742002-12-13 20:15:29 +00001498 break;
1499 case ZEBRA_READ:
1500 client->t_read =
paulb21b19c2003-06-15 01:28:29 +00001501 thread_add_read (zebrad.master, zebra_client_read, client, sock);
paul718e3742002-12-13 20:15:29 +00001502 break;
1503 case ZEBRA_WRITE:
1504 /**/
1505 break;
1506 }
1507}
1508
1509/* Display default rtm_table for all clients. */
1510DEFUN (show_table,
1511 show_table_cmd,
1512 "show table",
1513 SHOW_STR
1514 "default routing table to use for all clients\n")
1515{
paulb21b19c2003-06-15 01:28:29 +00001516 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
paul718e3742002-12-13 20:15:29 +00001517 VTY_NEWLINE);
1518 return CMD_SUCCESS;
1519}
1520
1521DEFUN (config_table,
1522 config_table_cmd,
1523 "table TABLENO",
1524 "Configure target kernel routing table\n"
1525 "TABLE integer\n")
1526{
paulb21b19c2003-06-15 01:28:29 +00001527 zebrad.rtm_table_default = strtol (argv[0], (char**)0, 10);
paul718e3742002-12-13 20:15:29 +00001528 return CMD_SUCCESS;
1529}
1530
hasso647e4f12003-05-25 11:43:52 +00001531DEFUN (ip_forwarding,
1532 ip_forwarding_cmd,
1533 "ip forwarding",
1534 IP_STR
1535 "Turn on IP forwarding")
1536{
1537 int ret;
1538
1539 ret = ipforward ();
hassob71f00f2004-10-13 12:20:35 +00001540 if (ret == 0)
1541 ret = ipforward_on ();
hasso647e4f12003-05-25 11:43:52 +00001542
hasso647e4f12003-05-25 11:43:52 +00001543 if (ret == 0)
1544 {
1545 vty_out (vty, "Can't turn on IP forwarding%s", VTY_NEWLINE);
1546 return CMD_WARNING;
1547 }
1548
1549 return CMD_SUCCESS;
1550}
1551
paul718e3742002-12-13 20:15:29 +00001552DEFUN (no_ip_forwarding,
1553 no_ip_forwarding_cmd,
1554 "no ip forwarding",
1555 NO_STR
1556 IP_STR
1557 "Turn off IP forwarding")
1558{
1559 int ret;
1560
1561 ret = ipforward ();
hassob71f00f2004-10-13 12:20:35 +00001562 if (ret != 0)
1563 ret = ipforward_off ();
paul718e3742002-12-13 20:15:29 +00001564
paul718e3742002-12-13 20:15:29 +00001565 if (ret != 0)
1566 {
1567 vty_out (vty, "Can't turn off IP forwarding%s", VTY_NEWLINE);
1568 return CMD_WARNING;
1569 }
1570
1571 return CMD_SUCCESS;
1572}
1573
1574/* This command is for debugging purpose. */
1575DEFUN (show_zebra_client,
1576 show_zebra_client_cmd,
1577 "show zebra client",
1578 SHOW_STR
1579 "Zebra information"
1580 "Client information")
1581{
hasso52dc7ee2004-09-23 19:18:23 +00001582 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001583 struct zserv *client;
1584
paul1eb8ef22005-04-07 07:30:20 +00001585 for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
1586 vty_out (vty, "Client fd %d%s", client->sock, VTY_NEWLINE);
1587
paul718e3742002-12-13 20:15:29 +00001588 return CMD_SUCCESS;
1589}
1590
1591/* Table configuration write function. */
paulb9df2d22004-05-09 09:09:59 +00001592static int
paul718e3742002-12-13 20:15:29 +00001593config_write_table (struct vty *vty)
1594{
paulb21b19c2003-06-15 01:28:29 +00001595 if (zebrad.rtm_table_default)
1596 vty_out (vty, "table %d%s", zebrad.rtm_table_default,
paul718e3742002-12-13 20:15:29 +00001597 VTY_NEWLINE);
1598 return 0;
1599}
1600
1601/* table node for routing tables. */
1602struct cmd_node table_node =
1603{
1604 TABLE_NODE,
1605 "", /* This node has no interface. */
1606 1
1607};
1608
1609/* Only display ip forwarding is enabled or not. */
1610DEFUN (show_ip_forwarding,
1611 show_ip_forwarding_cmd,
1612 "show ip forwarding",
1613 SHOW_STR
1614 IP_STR
1615 "IP forwarding status\n")
1616{
1617 int ret;
1618
1619 ret = ipforward ();
1620
1621 if (ret == 0)
1622 vty_out (vty, "IP forwarding is off%s", VTY_NEWLINE);
1623 else
1624 vty_out (vty, "IP forwarding is on%s", VTY_NEWLINE);
1625 return CMD_SUCCESS;
1626}
1627
1628#ifdef HAVE_IPV6
1629/* Only display ipv6 forwarding is enabled or not. */
1630DEFUN (show_ipv6_forwarding,
1631 show_ipv6_forwarding_cmd,
1632 "show ipv6 forwarding",
1633 SHOW_STR
1634 "IPv6 information\n"
1635 "Forwarding status\n")
1636{
1637 int ret;
1638
1639 ret = ipforward_ipv6 ();
1640
1641 switch (ret)
1642 {
1643 case -1:
1644 vty_out (vty, "ipv6 forwarding is unknown%s", VTY_NEWLINE);
1645 break;
1646 case 0:
1647 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
1648 break;
1649 case 1:
1650 vty_out (vty, "ipv6 forwarding is %s%s", "on", VTY_NEWLINE);
1651 break;
1652 default:
1653 vty_out (vty, "ipv6 forwarding is %s%s", "off", VTY_NEWLINE);
1654 break;
1655 }
1656 return CMD_SUCCESS;
1657}
1658
hasso55906722004-02-11 22:42:16 +00001659DEFUN (ipv6_forwarding,
1660 ipv6_forwarding_cmd,
1661 "ipv6 forwarding",
1662 IPV6_STR
1663 "Turn on IPv6 forwarding")
1664{
1665 int ret;
1666
hasso41d3fc92004-04-06 11:59:00 +00001667 ret = ipforward_ipv6 ();
hassob71f00f2004-10-13 12:20:35 +00001668 if (ret == 0)
1669 ret = ipforward_ipv6_on ();
hasso41d3fc92004-04-06 11:59:00 +00001670
hasso41d3fc92004-04-06 11:59:00 +00001671 if (ret == 0)
1672 {
hasso55906722004-02-11 22:42:16 +00001673 vty_out (vty, "Can't turn on IPv6 forwarding%s", VTY_NEWLINE);
1674 return CMD_WARNING;
1675 }
1676
1677 return CMD_SUCCESS;
1678}
1679
paul718e3742002-12-13 20:15:29 +00001680DEFUN (no_ipv6_forwarding,
1681 no_ipv6_forwarding_cmd,
1682 "no ipv6 forwarding",
1683 NO_STR
hasso55906722004-02-11 22:42:16 +00001684 IPV6_STR
1685 "Turn off IPv6 forwarding")
paul718e3742002-12-13 20:15:29 +00001686{
1687 int ret;
1688
hasso41d3fc92004-04-06 11:59:00 +00001689 ret = ipforward_ipv6 ();
hassob71f00f2004-10-13 12:20:35 +00001690 if (ret != 0)
1691 ret = ipforward_ipv6_off ();
hasso41d3fc92004-04-06 11:59:00 +00001692
paul718e3742002-12-13 20:15:29 +00001693 if (ret != 0)
1694 {
1695 vty_out (vty, "Can't turn off IPv6 forwarding%s", VTY_NEWLINE);
1696 return CMD_WARNING;
1697 }
1698
1699 return CMD_SUCCESS;
1700}
1701
1702#endif /* HAVE_IPV6 */
1703
1704/* IPForwarding configuration write function. */
ajs719e9742005-02-28 20:52:15 +00001705static int
paul718e3742002-12-13 20:15:29 +00001706config_write_forwarding (struct vty *vty)
1707{
hasso18a6dce2004-10-03 18:18:34 +00001708 /* FIXME: Find better place for that. */
1709 router_id_write (vty);
1710
paul3e0b3a52004-08-23 18:58:32 +00001711 if (ipforward ())
1712 vty_out (vty, "ip forwarding%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001713#ifdef HAVE_IPV6
paul3e0b3a52004-08-23 18:58:32 +00001714 if (ipforward_ipv6 ())
1715 vty_out (vty, "ipv6 forwarding%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001716#endif /* HAVE_IPV6 */
1717 vty_out (vty, "!%s", VTY_NEWLINE);
1718 return 0;
1719}
1720
1721/* table node for routing tables. */
1722struct cmd_node forwarding_node =
1723{
1724 FORWARDING_NODE,
1725 "", /* This node has no interface. */
1726 1
1727};
1728
1729
1730/* Initialisation of zebra and installation of commands. */
1731void
paula1ac18c2005-06-28 17:17:12 +00001732zebra_init (void)
paul718e3742002-12-13 20:15:29 +00001733{
1734 /* Client list init. */
paulb21b19c2003-06-15 01:28:29 +00001735 zebrad.client_list = list_new ();
paul718e3742002-12-13 20:15:29 +00001736
paul718e3742002-12-13 20:15:29 +00001737 /* Make zebra server socket. */
1738#ifdef HAVE_TCP_ZEBRA
1739 zebra_serv ();
1740#else
1741 zebra_serv_un (ZEBRA_SERV_PATH);
1742#endif /* HAVE_TCP_ZEBRA */
1743
1744 /* Install configuration write function. */
1745 install_node (&table_node, config_write_table);
1746 install_node (&forwarding_node, config_write_forwarding);
1747
1748 install_element (VIEW_NODE, &show_ip_forwarding_cmd);
1749 install_element (ENABLE_NODE, &show_ip_forwarding_cmd);
hasso647e4f12003-05-25 11:43:52 +00001750 install_element (CONFIG_NODE, &ip_forwarding_cmd);
paul718e3742002-12-13 20:15:29 +00001751 install_element (CONFIG_NODE, &no_ip_forwarding_cmd);
1752 install_element (ENABLE_NODE, &show_zebra_client_cmd);
1753
1754#ifdef HAVE_NETLINK
1755 install_element (VIEW_NODE, &show_table_cmd);
1756 install_element (ENABLE_NODE, &show_table_cmd);
1757 install_element (CONFIG_NODE, &config_table_cmd);
1758#endif /* HAVE_NETLINK */
1759
1760#ifdef HAVE_IPV6
1761 install_element (VIEW_NODE, &show_ipv6_forwarding_cmd);
1762 install_element (ENABLE_NODE, &show_ipv6_forwarding_cmd);
hasso55906722004-02-11 22:42:16 +00001763 install_element (CONFIG_NODE, &ipv6_forwarding_cmd);
paul718e3742002-12-13 20:15:29 +00001764 install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
1765#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001766}