]> git.proxmox.com Git - mirror_frr.git/blame - lib/zclient.c
2004-09-30 Paul Jakma <paul@dishone.st>
[mirror_frr.git] / lib / zclient.c
CommitLineData
718e3744 1/* Zebra's client library.
2 * Copyright (C) 1999 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
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any 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, Boston,
19 * MA 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "stream.h"
26#include "network.h"
27#include "if.h"
28#include "log.h"
29#include "thread.h"
30#include "zclient.h"
31#include "memory.h"
32#include "table.h"
33
34#include "zebra/rib.h"
35#include "zebra/zserv.h"
36\f
37/* Zebra client events. */
38enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT};
39
40/* Prototype for event manager. */
41static void zclient_event (enum event, struct zclient *);
42
43/* This file local debug flag. */
44int zclient_debug = 0;
45\f
46/* Allocate zclient structure. */
47struct zclient *
48zclient_new ()
49{
50 struct zclient *zclient;
51 zclient = XMALLOC (MTYPE_ZCLIENT, sizeof (struct zclient));
52 memset (zclient, 0, sizeof (struct zclient));
53
54 zclient->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
55 zclient->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
56
57 return zclient;
58}
59
60/* Free zclient structure. */
61void
62zclient_free (struct zclient *zclient)
63{
64 XFREE (MTYPE_ZCLIENT, zclient);
65}
66
67/* Initialize zebra client. Argument redist_default is unwanted
68 redistribute route type. */
69void
70zclient_init (struct zclient *zclient, int redist_default)
71{
72 int i;
73
74 /* Enable zebra client connection by default. */
75 zclient->enable = 1;
76
77 /* Set -1 to the default socket value. */
78 zclient->sock = -1;
79
80 /* Clear redistribution flags. */
81 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
82 zclient->redist[i] = 0;
83
84 /* Set unwanted redistribute route. bgpd does not need BGP route
85 redistribution. */
86 zclient->redist_default = redist_default;
87 zclient->redist[redist_default] = 1;
88
89 /* Set default-information redistribute to zero. */
90 zclient->default_information = 0;
91
92 /* Schedule first zclient connection. */
93 if (zclient_debug)
94 zlog_info ("zclient start scheduled");
95
96 zclient_event (ZCLIENT_SCHEDULE, zclient);
97}
98
99/* Stop zebra client services. */
100void
101zclient_stop (struct zclient *zclient)
102{
103 if (zclient_debug)
104 zlog_info ("zclient stopped");
105
106 /* Stop threads. */
107 if (zclient->t_read)
108 {
109 thread_cancel (zclient->t_read);
110 zclient->t_read = NULL;
111 }
112 if (zclient->t_connect)
113 {
114 thread_cancel (zclient->t_connect);
115 zclient->t_connect = NULL;
116 }
117
118 /* Close socket. */
119 if (zclient->sock >= 0)
120 {
121 close (zclient->sock);
122 zclient->sock = -1;
123 }
124 zclient->fail = 0;
125}
126
127void
128zclient_reset (struct zclient *zclient)
129{
130 zclient_stop (zclient);
131 zclient_init (zclient, zclient->redist_default);
132}
133
134/* Make socket to zebra daemon. Return zebra socket. */
135int
136zclient_socket ()
137{
138 int sock;
139 int ret;
140 struct sockaddr_in serv;
141
142 /* We should think about IPv6 connection. */
143 sock = socket (AF_INET, SOCK_STREAM, 0);
144 if (sock < 0)
145 return -1;
146
147 /* Make server socket. */
148 memset (&serv, 0, sizeof (struct sockaddr_in));
149 serv.sin_family = AF_INET;
150 serv.sin_port = htons (ZEBRA_PORT);
151#ifdef HAVE_SIN_LEN
152 serv.sin_len = sizeof (struct sockaddr_in);
153#endif /* HAVE_SIN_LEN */
154 serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
155
156 /* Connect to zebra. */
157 ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv));
158 if (ret < 0)
159 {
160 close (sock);
161 return -1;
162 }
163 return sock;
164}
165
166/* For sockaddr_un. */
167#include <sys/un.h>
168
169int
170zclient_socket_un (char *path)
171{
172 int ret;
173 int sock, len;
174 struct sockaddr_un addr;
175
176 sock = socket (AF_UNIX, SOCK_STREAM, 0);
177 if (sock < 0)
178 return -1;
179
180 /* Make server socket. */
181 memset (&addr, 0, sizeof (struct sockaddr_un));
182 addr.sun_family = AF_UNIX;
183 strncpy (addr.sun_path, path, strlen (path));
184#ifdef HAVE_SUN_LEN
185 len = addr.sun_len = SUN_LEN(&addr);
186#else
187 len = sizeof (addr.sun_family) + strlen (addr.sun_path);
188#endif /* HAVE_SUN_LEN */
189
190 ret = connect (sock, (struct sockaddr *) &addr, len);
191 if (ret < 0)
192 {
193 close (sock);
194 return -1;
195 }
196 return sock;
197}
198
199/* Send simple Zebra message. */
200int
201zebra_message_send (struct zclient *zclient, int command)
202{
203 struct stream *s;
204
205 /* Get zclient output buffer. */
206 s = zclient->obuf;
207 stream_reset (s);
208
209 /* Send very simple command only Zebra message. */
210 stream_putw (s, 3);
211 stream_putc (s, command);
212
213 return writen (zclient->sock, s->data, 3);
214}
215
216/* Make connection to zebra daemon. */
217int
218zclient_start (struct zclient *zclient)
219{
220 int i;
221
222 if (zclient_debug)
223 zlog_info ("zclient_start is called");
224
225 /* zclient is disabled. */
226 if (! zclient->enable)
227 return 0;
228
229 /* If already connected to the zebra. */
230 if (zclient->sock >= 0)
231 return 0;
232
233 /* Check connect thread. */
234 if (zclient->t_connect)
235 return 0;
236
237 /* Make socket. */
238#ifdef HAVE_TCP_ZEBRA
239 zclient->sock = zclient_socket ();
240#else
241 zclient->sock = zclient_socket_un (ZEBRA_SERV_PATH);
242#endif /* HAVE_TCP_ZEBRA */
243 if (zclient->sock < 0)
244 {
245 if (zclient_debug)
246 zlog_info ("zclient connection fail");
247 zclient->fail++;
248 zclient_event (ZCLIENT_CONNECT, zclient);
249 return -1;
250 }
251
252 /* Clear fail count. */
253 zclient->fail = 0;
254 if (zclient_debug)
255 zlog_info ("zclient connect success with socket [%d]", zclient->sock);
256
257 /* Create read thread. */
258 zclient_event (ZCLIENT_READ, zclient);
259
260 /* We need interface information. */
261 zebra_message_send (zclient, ZEBRA_INTERFACE_ADD);
262
263 /* Flush all redistribute request. */
264 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
265 if (i != zclient->redist_default && zclient->redist[i])
266 zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, i);
267
268 /* If default information is needed. */
269 if (zclient->default_information)
270 zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD);
271
272 return 0;
273}
274
275/* This function is a wrapper function for calling zclient_start from
276 timer or event thread. */
277int
278zclient_connect (struct thread *t)
279{
280 struct zclient *zclient;
281
282 zclient = THREAD_ARG (t);
283 zclient->t_connect = NULL;
284
285 if (zclient_debug)
286 zlog_info ("zclient_connect is called");
287
288 return zclient_start (zclient);
289}
290\f
0a589359 291 /*
292 * "xdr_encode"-like interface that allows daemon (client) to send
293 * a message to zebra server for a route that needs to be
294 * added/deleted to the kernel. Info about the route is specified
295 * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes
296 * the info down the zclient socket using the stream_* functions.
297 *
298 * The corresponding read ("xdr_decode") function on the server
299 * side is zread_ipv4_add()/zread_ipv4_delete().
300 *
301 * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
302 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
303 * | Length (2) | Command | Route Type |
304 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305 * | ZEBRA Flags | Message Flags | Prefix length |
306 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307 * | Destination IPv4 Prefix for route |
308 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
309 * | Nexthop count |
310 * +-+-+-+-+-+-+-+-+
311 *
312 *
313 * A number of IPv4 nexthop(s) or nexthop interface index(es) are then
314 * described, as per the Nexthop count. Each nexthop described as:
315 *
316 * +-+-+-+-+-+-+-+-+
317 * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_*
318 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
319 * | IPv4 Nexthop address or Interface Index number |
320 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
321 *
322 * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or
323 * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_
324 * nexthop information is provided, and the message describes a prefix
325 * to blackhole or reject route.
326 *
327 * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
328 * byte value.
329 *
330 * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8
331 * byte value.
332 *
333 * XXX: No attention paid to alignment.
334 */
718e3744 335int
0a589359 336zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
337 struct zapi_ipv4 *api)
718e3744 338{
339 int i;
340 int psize;
341 struct stream *s;
342
343 /* Reset stream. */
344 s = zclient->obuf;
345 stream_reset (s);
346
347 /* Length place holder. */
348 stream_putw (s, 0);
349
350 /* Put command, type and nexthop. */
0a589359 351 stream_putc (s, cmd);
718e3744 352 stream_putc (s, api->type);
353 stream_putc (s, api->flags);
354 stream_putc (s, api->message);
718e3744 355
718e3744 356 /* Put prefix information. */
357 psize = PSIZE (p->prefixlen);
358 stream_putc (s, p->prefixlen);
0a589359 359 stream_write (s, (u_char *) & p->prefix, psize);
718e3744 360
361 /* Nexthop, ifindex, distance and metric information. */
362 if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
363 {
595db7f1 364 if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
365 {
366 stream_putc (s, 1);
367 stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE);
0a589359 368 /* XXX assert(api->nexthop_num == 0); */
369 /* XXX assert(api->ifindex_num == 0); */
595db7f1 370 }
371 else
372 stream_putc (s, api->nexthop_num + api->ifindex_num);
718e3744 373
374 for (i = 0; i < api->nexthop_num; i++)
595db7f1 375 {
376 stream_putc (s, ZEBRA_NEXTHOP_IPV4);
377 stream_put_in_addr (s, api->nexthop[i]);
378 }
718e3744 379 for (i = 0; i < api->ifindex_num; i++)
595db7f1 380 {
381 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
382 stream_putl (s, api->ifindex[i]);
383 }
718e3744 384 }
385
386 if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE))
387 stream_putc (s, api->distance);
388 if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
389 stream_putl (s, api->metric);
390
391 /* Put length at the first point of the stream. */
392 stream_putw_at (s, 0, stream_get_endp (s));
393
394 return writen (zclient->sock, s->data, stream_get_endp (s));
395}
396
397#ifdef HAVE_IPV6
398int
0a589359 399zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
718e3744 400 struct zapi_ipv6 *api)
401{
402 int i;
403 int psize;
404 struct stream *s;
405
406 /* Reset stream. */
407 s = zclient->obuf;
408 stream_reset (s);
409
410 /* Length place holder. */
411 stream_putw (s, 0);
412
413 /* Put command, type and nexthop. */
0a589359 414 stream_putc (s, cmd);
718e3744 415 stream_putc (s, api->type);
416 stream_putc (s, api->flags);
417 stream_putc (s, api->message);
418
419 /* Put prefix information. */
420 psize = PSIZE (p->prefixlen);
421 stream_putc (s, p->prefixlen);
422 stream_write (s, (u_char *)&p->prefix, psize);
423
424 /* Nexthop, ifindex, distance and metric information. */
425 if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
426 {
427 stream_putc (s, api->nexthop_num + api->ifindex_num);
428
429 for (i = 0; i < api->nexthop_num; i++)
430 {
431 stream_putc (s, ZEBRA_NEXTHOP_IPV6);
432 stream_write (s, (u_char *)api->nexthop[i], 16);
433 }
434 for (i = 0; i < api->ifindex_num; i++)
435 {
436 stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
437 stream_putl (s, api->ifindex[i]);
438 }
439 }
440
441 if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE))
442 stream_putc (s, api->distance);
443 if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
444 stream_putl (s, api->metric);
445
446 /* Put length at the first point of the stream. */
447 stream_putw_at (s, 0, stream_get_endp (s));
448
449 return writen (zclient->sock, s->data, stream_get_endp (s));
450}
718e3744 451#endif /* HAVE_IPV6 */
452
0a589359 453/*
454 * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
455 * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
456 * then set/unset redist[type] in the client handle (a struct zserv) for the
457 * sending client
458 */
718e3744 459int
460zebra_redistribute_send (int command, int sock, int type)
461{
462 int ret;
463 struct stream *s;
464
465 s = stream_new (ZEBRA_MAX_PACKET_SIZ);
466
467 /* Total length of the messages. */
468 stream_putw (s, 4);
469
470 stream_putc (s, command);
471 stream_putc (s, type);
472
473 ret = writen (sock, s->data, 4);
474
475 stream_free (s);
476
477 return ret;
478}
479
480/* Interface addition from zebra daemon. */
0a589359 481/*
482 * The format of the message sent with type ZEBRA_INTERFACE_ADD or
483 * ZEBRA_INTERFACE_DELETE from zebra to the client is:
484 * 0 1 2 3
485 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
486 * +-+-+-+-+-+-+-+-+
487 * | type |
488 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
489 * | ifname |
490 * | |
491 * | |
492 * | |
493 * | |
494 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
495 * | ifindex |
496 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
497 * | if_flags |
498 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
499 * | metric |
500 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
501 * | ifmtu |
502 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
503 * | ifmtu6 |
504 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
505 * | bandwidth |
506 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
507 * | sockaddr_dl |
508 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
509 */
510
718e3744 511struct interface *
512zebra_interface_add_read (struct stream *s)
513{
514 struct interface *ifp;
02ff83c5 515 char ifname_tmp[INTERFACE_NAMSIZ];
718e3744 516
517 /* Read interface name. */
518 stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
519
520 /* Lookup this by interface name. */
521 ifp = if_lookup_by_name (ifname_tmp);
522
523 /* If such interface does not exist, make new one. */
524 if (! ifp)
106d2fd5 525 ifp = if_create (ifname_tmp, INTERFACE_NAMSIZ);
718e3744 526
527 /* Read interface's index. */
528 ifp->ifindex = stream_getl (s);
529
530 /* Read interface's value. */
2e3b2e47 531 ifp->status = stream_getc (s);
718e3744 532 ifp->flags = stream_getl (s);
533 ifp->metric = stream_getl (s);
534 ifp->mtu = stream_getl (s);
0a589359 535 ifp->mtu6 = stream_getl (s);
718e3744 536 ifp->bandwidth = stream_getl (s);
537#ifdef HAVE_SOCKADDR_DL
538 stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
539#else
540 ifp->hw_addr_len = stream_getl (s);
541 if (ifp->hw_addr_len)
542 stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
543#endif /* HAVE_SOCKADDR_DL */
544
545 return ifp;
546}
547
0a589359 548/*
549 * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN)
550 * from zebra server. The format of this message is the same as
551 * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE (see
552 * comments for zebra_interface_add_read), except that no sockaddr_dl
553 * is sent at the tail of the message.
554 */
718e3744 555struct interface *
556zebra_interface_state_read (struct stream *s)
557{
558 struct interface *ifp;
02ff83c5 559 char ifname_tmp[INTERFACE_NAMSIZ];
718e3744 560
561 /* Read interface name. */
562 stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
563
564 /* Lookup this by interface index. */
565 ifp = if_lookup_by_name (ifname_tmp);
566
567 /* If such interface does not exist, indicate an error */
568 if (! ifp)
569 return NULL;
570
571 /* Read interface's index. */
572 ifp->ifindex = stream_getl (s);
573
574 /* Read interface's value. */
2e3b2e47 575 ifp->status = stream_getc (s);
718e3744 576 ifp->flags = stream_getl (s);
577 ifp->metric = stream_getl (s);
578 ifp->mtu = stream_getl (s);
0a589359 579 ifp->mtu6 = stream_getl (s);
718e3744 580 ifp->bandwidth = stream_getl (s);
581
582 return ifp;
583}
584
0a589359 585/*
586 * format of message for address additon is:
587 * 0
588 * 0 1 2 3 4 5 6 7
589 * +-+-+-+-+-+-+-+-+
590 * | type | ZEBRA_INTERFACE_ADDRESS_ADD or
591 * +-+-+-+-+-+-+-+-+ ZEBRA_INTERFACE_ADDRES_DELETE
592 * | |
593 * + +
594 * | ifindex |
595 * + +
596 * | |
597 * + +
598 * | |
599 * +-+-+-+-+-+-+-+-+
600 * | ifc_flags | flags for connected address
601 * +-+-+-+-+-+-+-+-+
602 * | addr_family |
603 * +-+-+-+-+-+-+-+-+
604 * | addr... |
605 * : :
606 * | |
607 * +-+-+-+-+-+-+-+-+
608 * | addr_len | len of addr. E.g., addr_len = 4 for ipv4 addrs.
609 * +-+-+-+-+-+-+-+-+
610 * | daddr.. |
611 * : :
612 * | |
613 * +-+-+-+-+-+-+-+-+
614 *
615 */
616
718e3744 617struct connected *
0a589359 618zebra_interface_address_read (int type, struct stream *s)
718e3744 619{
620 unsigned int ifindex;
621 struct interface *ifp;
622 struct connected *ifc;
0a589359 623 struct prefix p, d;
718e3744 624 int family;
625 int plen;
0a589359 626 u_char ifc_flags;
718e3744 627
0a589359 628 memset (&p, 0, sizeof(p));
629 memset (&d, 0, sizeof(d));
718e3744 630
631 /* Get interface index. */
632 ifindex = stream_getl (s);
633
634 /* Lookup index. */
635 ifp = if_lookup_by_index (ifindex);
636 if (ifp == NULL)
637 {
0a589359 638 zlog_warn ("zebra_interface_address_read(%s): "
639 "Can't find interface by ifindex: %d ",
640 (type == ZEBRA_INTERFACE_ADDRESS_ADD? "ADD" : "DELETE"),
641 ifindex);
718e3744 642 return NULL;
643 }
644
645 /* Fetch flag. */
0a589359 646 ifc_flags = stream_getc (s);
718e3744 647
648 /* Fetch interface address. */
649 family = p.family = stream_getc (s);
650
0a589359 651 plen = prefix_blen (&p);
652 stream_get (&p.u.prefix, s, plen);
718e3744 653 p.prefixlen = stream_getc (s);
654
655 /* Fetch destination address. */
0a589359 656 stream_get (&d.u.prefix, s, plen);
718e3744 657 d.family = family;
658
0a589359 659 if (type == ZEBRA_INTERFACE_ADDRESS_ADD)
660 {
661 ifc = connected_add_by_prefix(ifp, &p, &d);
662 if (ifc != NULL)
663 ifc->flags = ifc_flags;
664 }
665 else
666 {
667 assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
668 ifc = connected_delete_by_prefix(ifp, &p);
669 }
718e3744 670
671 return ifc;
672}
0a589359 673
718e3744 674\f
675/* Zebra client message read function. */
676int
677zclient_read (struct thread *thread)
678{
679 int ret;
680 int nbytes;
681 int sock;
682 zebra_size_t length;
683 zebra_command_t command;
684 struct zclient *zclient;
685
686 /* Get socket to zebra. */
687 sock = THREAD_FD (thread);
688 zclient = THREAD_ARG (thread);
689 zclient->t_read = NULL;
690
691 /* Clear input buffer. */
692 stream_reset (zclient->ibuf);
693
694 /* Read zebra header. */
695 nbytes = stream_read (zclient->ibuf, sock, ZEBRA_HEADER_SIZE);
696
697 /* zebra socket is closed. */
698 if (nbytes == 0)
699 {
700 if (zclient_debug)
0a589359 701 zlog_info ("zclient connection closed socket [%d].", sock);
718e3744 702 zclient->fail++;
703 zclient_stop (zclient);
704 zclient_event (ZCLIENT_CONNECT, zclient);
705 return -1;
706 }
707
708 /* zebra read error. */
709 if (nbytes < 0 || nbytes != ZEBRA_HEADER_SIZE)
710 {
711 if (zclient_debug)
0a589359 712 zlog_info ("Can't read all packet (length %d).", nbytes);
718e3744 713 zclient->fail++;
714 zclient_stop (zclient);
715 zclient_event (ZCLIENT_CONNECT, zclient);
716 return -1;
717 }
718
719 /* Fetch length and command. */
720 length = stream_getw (zclient->ibuf);
721 command = stream_getc (zclient->ibuf);
722
723 /* Length check. */
724 if (length >= zclient->ibuf->size)
725 {
726 stream_free (zclient->ibuf);
727 zclient->ibuf = stream_new (length + 1);
728 }
729 length -= ZEBRA_HEADER_SIZE;
730
731 /* Read rest of zebra packet. */
732 nbytes = stream_read (zclient->ibuf, sock, length);
733 if (nbytes != length)
734 {
735 if (zclient_debug)
736 zlog_info ("zclient connection closed socket [%d].", sock);
737 zclient->fail++;
738 zclient_stop (zclient);
739 zclient_event (ZCLIENT_CONNECT, zclient);
740 return -1;
741 }
742
0a589359 743 if (zclient_debug)
744 zlog_info("zclient 0x%p command 0x%x \n", zclient, command);
745
718e3744 746 switch (command)
747 {
748 case ZEBRA_INTERFACE_ADD:
749 if (zclient->interface_add)
750 ret = (*zclient->interface_add) (command, zclient, length);
751 break;
752 case ZEBRA_INTERFACE_DELETE:
753 if (zclient->interface_delete)
754 ret = (*zclient->interface_delete) (command, zclient, length);
755 break;
756 case ZEBRA_INTERFACE_ADDRESS_ADD:
757 if (zclient->interface_address_add)
758 ret = (*zclient->interface_address_add) (command, zclient, length);
759 break;
760 case ZEBRA_INTERFACE_ADDRESS_DELETE:
761 if (zclient->interface_address_delete)
762 ret = (*zclient->interface_address_delete) (command, zclient, length);
763 break;
764 case ZEBRA_INTERFACE_UP:
765 if (zclient->interface_up)
766 ret = (*zclient->interface_up) (command, zclient, length);
767 break;
768 case ZEBRA_INTERFACE_DOWN:
769 if (zclient->interface_down)
770 ret = (*zclient->interface_down) (command, zclient, length);
771 break;
772 case ZEBRA_IPV4_ROUTE_ADD:
773 if (zclient->ipv4_route_add)
774 ret = (*zclient->ipv4_route_add) (command, zclient, length);
775 break;
776 case ZEBRA_IPV4_ROUTE_DELETE:
777 if (zclient->ipv4_route_delete)
778 ret = (*zclient->ipv4_route_delete) (command, zclient, length);
779 break;
780 case ZEBRA_IPV6_ROUTE_ADD:
781 if (zclient->ipv6_route_add)
782 ret = (*zclient->ipv6_route_add) (command, zclient, length);
783 break;
784 case ZEBRA_IPV6_ROUTE_DELETE:
785 if (zclient->ipv6_route_delete)
786 ret = (*zclient->ipv6_route_delete) (command, zclient, length);
787 break;
788 default:
789 break;
790 }
791
792 /* Register read thread. */
793 zclient_event (ZCLIENT_READ, zclient);
794
795 return 0;
796}
797
798void
0a589359 799zclient_redistribute (int command, struct zclient *zclient, int type)
718e3744 800{
718e3744 801
0a589359 802 if (command == ZEBRA_REDISTRIBUTE_ADD)
803 {
804 if (zclient->redist[type])
805 return;
806 zclient->redist[type] = 1;
807 }
808 else
809 {
810 if (!zclient->redist[type])
811 return;
812 zclient->redist[type] = 0;
813 }
718e3744 814
815 if (zclient->sock > 0)
0a589359 816 zebra_redistribute_send (command, zclient->sock, type);
718e3744 817}
818
718e3744 819
820void
0a589359 821zclient_redistribute_default (int command, struct zclient *zclient)
718e3744 822{
718e3744 823
0a589359 824 if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD)
825 {
826 if (zclient->default_information)
827 return;
828 zclient->default_information = 1;
829 }
830 else
831 {
832 if (!zclient->default_information)
833 return;
834 zclient->default_information = 0;
835 }
718e3744 836
837 if (zclient->sock > 0)
0a589359 838 zebra_message_send (zclient, command);
718e3744 839}
840
718e3744 841\f
842extern struct thread_master *master;
843
844static void
845zclient_event (enum event event, struct zclient *zclient)
846{
847 switch (event)
848 {
849 case ZCLIENT_SCHEDULE:
850 if (! zclient->t_connect)
851 zclient->t_connect =
852 thread_add_event (master, zclient_connect, zclient, 0);
853 break;
854 case ZCLIENT_CONNECT:
855 if (zclient->fail >= 10)
856 return;
857 if (zclient_debug)
858 zlog_info ("zclient connect schedule interval is %d",
859 zclient->fail < 3 ? 10 : 60);
860 if (! zclient->t_connect)
861 zclient->t_connect =
862 thread_add_timer (master, zclient_connect, zclient,
863 zclient->fail < 3 ? 10 : 60);
864 break;
865 case ZCLIENT_READ:
866 zclient->t_read =
867 thread_add_read (master, zclient_read, zclient, zclient->sock);
868 break;
869 }
870}