1 /* Zebra's client library.
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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.
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.
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,
34 #include "zebra/rib.h"
35 #include "zebra/zserv.h"
37 /* Zebra client events. */
38 enum event
{ZCLIENT_SCHEDULE
, ZCLIENT_READ
, ZCLIENT_CONNECT
};
40 /* Prototype for event manager. */
41 static void zclient_event (enum event
, struct zclient
*);
43 /* This file local debug flag. */
44 int zclient_debug
= 0;
46 /* Allocate zclient structure. */
50 struct zclient
*zclient
;
51 zclient
= XMALLOC (MTYPE_ZCLIENT
, sizeof (struct zclient
));
52 memset (zclient
, 0, sizeof (struct zclient
));
54 zclient
->ibuf
= stream_new (ZEBRA_MAX_PACKET_SIZ
);
55 zclient
->obuf
= stream_new (ZEBRA_MAX_PACKET_SIZ
);
60 /* Free zclient structure. */
62 zclient_free (struct zclient
*zclient
)
64 XFREE (MTYPE_ZCLIENT
, zclient
);
67 /* Initialize zebra client. Argument redist_default is unwanted
68 redistribute route type. */
70 zclient_init (struct zclient
*zclient
, int redist_default
)
74 /* Enable zebra client connection by default. */
77 /* Set -1 to the default socket value. */
80 /* Clear redistribution flags. */
81 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++)
82 zclient
->redist
[i
] = 0;
84 /* Set unwanted redistribute route. bgpd does not need BGP route
86 zclient
->redist_default
= redist_default
;
87 zclient
->redist
[redist_default
] = 1;
89 /* Set default-information redistribute to zero. */
90 zclient
->default_information
= 0;
92 /* Schedule first zclient connection. */
94 zlog_info ("zclient start scheduled");
96 zclient_event (ZCLIENT_SCHEDULE
, zclient
);
99 /* Stop zebra client services. */
101 zclient_stop (struct zclient
*zclient
)
104 zlog_info ("zclient stopped");
109 thread_cancel (zclient
->t_read
);
110 zclient
->t_read
= NULL
;
112 if (zclient
->t_connect
)
114 thread_cancel (zclient
->t_connect
);
115 zclient
->t_connect
= NULL
;
119 if (zclient
->sock
>= 0)
121 close (zclient
->sock
);
128 zclient_reset (struct zclient
*zclient
)
130 zclient_stop (zclient
);
131 zclient_init (zclient
, zclient
->redist_default
);
134 /* Make socket to zebra daemon. Return zebra socket. */
140 struct sockaddr_in serv
;
142 /* We should think about IPv6 connection. */
143 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
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
);
152 serv
.sin_len
= sizeof (struct sockaddr_in
);
153 #endif /* HAVE_SIN_LEN */
154 serv
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
156 /* Connect to zebra. */
157 ret
= connect (sock
, (struct sockaddr
*) &serv
, sizeof (serv
));
166 /* For sockaddr_un. */
170 zclient_socket_un (char *path
)
174 struct sockaddr_un addr
;
176 sock
= socket (AF_UNIX
, SOCK_STREAM
, 0);
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
));
185 len
= addr
.sun_len
= SUN_LEN(&addr
);
187 len
= sizeof (addr
.sun_family
) + strlen (addr
.sun_path
);
188 #endif /* HAVE_SUN_LEN */
190 ret
= connect (sock
, (struct sockaddr
*) &addr
, len
);
199 /* Send simple Zebra message. */
201 zebra_message_send (struct zclient
*zclient
, int command
)
205 /* Get zclient output buffer. */
209 /* Send very simple command only Zebra message. */
211 stream_putc (s
, command
);
213 return writen (zclient
->sock
, s
->data
, 3);
216 /* Make connection to zebra daemon. */
218 zclient_start (struct zclient
*zclient
)
223 zlog_info ("zclient_start is called");
225 /* zclient is disabled. */
226 if (! zclient
->enable
)
229 /* If already connected to the zebra. */
230 if (zclient
->sock
>= 0)
233 /* Check connect thread. */
234 if (zclient
->t_connect
)
238 #ifdef HAVE_TCP_ZEBRA
239 zclient
->sock
= zclient_socket ();
241 zclient
->sock
= zclient_socket_un (ZEBRA_SERV_PATH
);
242 #endif /* HAVE_TCP_ZEBRA */
243 if (zclient
->sock
< 0)
246 zlog_info ("zclient connection fail");
248 zclient_event (ZCLIENT_CONNECT
, zclient
);
252 /* Clear fail count. */
255 zlog_info ("zclient connect success with socket [%d]", zclient
->sock
);
257 /* Create read thread. */
258 zclient_event (ZCLIENT_READ
, zclient
);
260 /* We need interface information. */
261 zebra_message_send (zclient
, ZEBRA_INTERFACE_ADD
);
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
);
268 /* If default information is needed. */
269 if (zclient
->default_information
)
270 zebra_message_send (zclient
, ZEBRA_REDISTRIBUTE_DEFAULT_ADD
);
275 /* This function is a wrapper function for calling zclient_start from
276 timer or event thread. */
278 zclient_connect (struct thread
*t
)
280 struct zclient
*zclient
;
282 zclient
= THREAD_ARG (t
);
283 zclient
->t_connect
= NULL
;
286 zlog_info ("zclient_connect is called");
288 return zclient_start (zclient
);
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.
298 * The corresponding read ("xdr_decode") function on the server
299 * side is zread_ipv4_add()/zread_ipv4_delete().
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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:
317 * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_*
318 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
319 * | IPv4 Nexthop address or Interface Index number |
320 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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.
327 * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
330 * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8
333 * XXX: No attention paid to alignment.
336 zapi_ipv4_route (u_char cmd
, struct zclient
*zclient
, struct prefix_ipv4
*p
,
337 struct zapi_ipv4
*api
)
347 /* Length place holder. */
350 /* Put command, type and nexthop. */
351 stream_putc (s
, cmd
);
352 stream_putc (s
, api
->type
);
353 stream_putc (s
, api
->flags
);
354 stream_putc (s
, api
->message
);
356 /* Put prefix information. */
357 psize
= PSIZE (p
->prefixlen
);
358 stream_putc (s
, p
->prefixlen
);
359 stream_write (s
, (u_char
*) & p
->prefix
, psize
);
361 /* Nexthop, ifindex, distance and metric information. */
362 if (CHECK_FLAG (api
->message
, ZAPI_MESSAGE_NEXTHOP
))
364 if (CHECK_FLAG (api
->flags
, ZEBRA_FLAG_BLACKHOLE
))
367 stream_putc (s
, ZEBRA_NEXTHOP_BLACKHOLE
);
368 /* XXX assert(api->nexthop_num == 0); */
369 /* XXX assert(api->ifindex_num == 0); */
372 stream_putc (s
, api
->nexthop_num
+ api
->ifindex_num
);
374 for (i
= 0; i
< api
->nexthop_num
; i
++)
376 stream_putc (s
, ZEBRA_NEXTHOP_IPV4
);
377 stream_put_in_addr (s
, api
->nexthop
[i
]);
379 for (i
= 0; i
< api
->ifindex_num
; i
++)
381 stream_putc (s
, ZEBRA_NEXTHOP_IFINDEX
);
382 stream_putl (s
, api
->ifindex
[i
]);
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
);
391 /* Put length at the first point of the stream. */
392 stream_putw_at (s
, 0, stream_get_endp (s
));
394 return writen (zclient
->sock
, s
->data
, stream_get_endp (s
));
399 zapi_ipv6_route (u_char cmd
, struct zclient
*zclient
, struct prefix_ipv6
*p
,
400 struct zapi_ipv6
*api
)
410 /* Length place holder. */
413 /* Put command, type and nexthop. */
414 stream_putc (s
, cmd
);
415 stream_putc (s
, api
->type
);
416 stream_putc (s
, api
->flags
);
417 stream_putc (s
, api
->message
);
419 /* Put prefix information. */
420 psize
= PSIZE (p
->prefixlen
);
421 stream_putc (s
, p
->prefixlen
);
422 stream_write (s
, (u_char
*)&p
->prefix
, psize
);
424 /* Nexthop, ifindex, distance and metric information. */
425 if (CHECK_FLAG (api
->message
, ZAPI_MESSAGE_NEXTHOP
))
427 stream_putc (s
, api
->nexthop_num
+ api
->ifindex_num
);
429 for (i
= 0; i
< api
->nexthop_num
; i
++)
431 stream_putc (s
, ZEBRA_NEXTHOP_IPV6
);
432 stream_write (s
, (u_char
*)api
->nexthop
[i
], 16);
434 for (i
= 0; i
< api
->ifindex_num
; i
++)
436 stream_putc (s
, ZEBRA_NEXTHOP_IFINDEX
);
437 stream_putl (s
, api
->ifindex
[i
]);
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
);
446 /* Put length at the first point of the stream. */
447 stream_putw_at (s
, 0, stream_get_endp (s
));
449 return writen (zclient
->sock
, s
->data
, stream_get_endp (s
));
451 #endif /* HAVE_IPV6 */
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
460 zebra_redistribute_send (int command
, int sock
, int type
)
465 s
= stream_new (ZEBRA_MAX_PACKET_SIZ
);
467 /* Total length of the messages. */
470 stream_putc (s
, command
);
471 stream_putc (s
, type
);
473 ret
= writen (sock
, s
->data
, 4);
480 /* Interface addition from zebra daemon. */
482 * The format of the message sent with type ZEBRA_INTERFACE_ADD or
483 * ZEBRA_INTERFACE_DELETE from zebra to the client is:
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
488 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
494 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
496 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
498 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
500 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
502 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
504 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
506 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
508 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
512 zebra_interface_add_read (struct stream
*s
)
514 struct interface
*ifp
;
515 char ifname_tmp
[INTERFACE_NAMSIZ
];
517 /* Read interface name. */
518 stream_get (ifname_tmp
, s
, INTERFACE_NAMSIZ
);
520 /* Lookup this by interface name. */
521 ifp
= if_lookup_by_name (ifname_tmp
);
523 /* If such interface does not exist, make new one. */
525 ifp
= if_create (ifname_tmp
, INTERFACE_NAMSIZ
);
527 /* Read interface's index. */
528 ifp
->ifindex
= stream_getl (s
);
530 /* Read interface's value. */
531 ifp
->status
= stream_getc (s
);
532 ifp
->flags
= stream_getl (s
);
533 ifp
->metric
= stream_getl (s
);
534 ifp
->mtu
= stream_getl (s
);
535 ifp
->mtu6
= stream_getl (s
);
536 ifp
->bandwidth
= stream_getl (s
);
537 #ifdef HAVE_SOCKADDR_DL
538 stream_get (&ifp
->sdl
, s
, sizeof (ifp
->sdl
));
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 */
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.
556 zebra_interface_state_read (struct stream
*s
)
558 struct interface
*ifp
;
559 char ifname_tmp
[INTERFACE_NAMSIZ
];
561 /* Read interface name. */
562 stream_get (ifname_tmp
, s
, INTERFACE_NAMSIZ
);
564 /* Lookup this by interface index. */
565 ifp
= if_lookup_by_name (ifname_tmp
);
567 /* If such interface does not exist, indicate an error */
571 /* Read interface's index. */
572 ifp
->ifindex
= stream_getl (s
);
574 /* Read interface's value. */
575 ifp
->status
= stream_getc (s
);
576 ifp
->flags
= stream_getl (s
);
577 ifp
->metric
= stream_getl (s
);
578 ifp
->mtu
= stream_getl (s
);
579 ifp
->mtu6
= stream_getl (s
);
580 ifp
->bandwidth
= stream_getl (s
);
586 * format of message for address additon is:
590 * | type | ZEBRA_INTERFACE_ADDRESS_ADD or
591 * +-+-+-+-+-+-+-+-+ ZEBRA_INTERFACE_ADDRES_DELETE
600 * | ifc_flags | flags for connected address
608 * | addr_len | len of addr. E.g., addr_len = 4 for ipv4 addrs.
618 zebra_interface_address_read (int type
, struct stream
*s
)
620 unsigned int ifindex
;
621 struct interface
*ifp
;
622 struct connected
*ifc
;
628 memset (&p
, 0, sizeof(p
));
629 memset (&d
, 0, sizeof(d
));
631 /* Get interface index. */
632 ifindex
= stream_getl (s
);
635 ifp
= if_lookup_by_index (ifindex
);
638 zlog_warn ("zebra_interface_address_read(%s): "
639 "Can't find interface by ifindex: %d ",
640 (type
== ZEBRA_INTERFACE_ADDRESS_ADD
? "ADD" : "DELETE"),
646 ifc_flags
= stream_getc (s
);
648 /* Fetch interface address. */
649 family
= p
.family
= stream_getc (s
);
651 plen
= prefix_blen (&p
);
652 stream_get (&p
.u
.prefix
, s
, plen
);
653 p
.prefixlen
= stream_getc (s
);
655 /* Fetch destination address. */
656 stream_get (&d
.u
.prefix
, s
, plen
);
659 if (type
== ZEBRA_INTERFACE_ADDRESS_ADD
)
661 ifc
= connected_add_by_prefix(ifp
, &p
, &d
);
663 ifc
->flags
= ifc_flags
;
667 assert (type
== ZEBRA_INTERFACE_ADDRESS_DELETE
);
668 ifc
= connected_delete_by_prefix(ifp
, &p
);
675 /* Zebra client message read function. */
677 zclient_read (struct thread
*thread
)
683 zebra_command_t command
;
684 struct zclient
*zclient
;
686 /* Get socket to zebra. */
687 sock
= THREAD_FD (thread
);
688 zclient
= THREAD_ARG (thread
);
689 zclient
->t_read
= NULL
;
691 /* Clear input buffer. */
692 stream_reset (zclient
->ibuf
);
694 /* Read zebra header. */
695 nbytes
= stream_read (zclient
->ibuf
, sock
, ZEBRA_HEADER_SIZE
);
697 /* zebra socket is closed. */
701 zlog_info ("zclient connection closed socket [%d].", sock
);
703 zclient_stop (zclient
);
704 zclient_event (ZCLIENT_CONNECT
, zclient
);
708 /* zebra read error. */
709 if (nbytes
< 0 || nbytes
!= ZEBRA_HEADER_SIZE
)
712 zlog_info ("Can't read all packet (length %d).", nbytes
);
714 zclient_stop (zclient
);
715 zclient_event (ZCLIENT_CONNECT
, zclient
);
719 /* Fetch length and command. */
720 length
= stream_getw (zclient
->ibuf
);
721 command
= stream_getc (zclient
->ibuf
);
724 if (length
>= zclient
->ibuf
->size
)
726 stream_free (zclient
->ibuf
);
727 zclient
->ibuf
= stream_new (length
+ 1);
729 length
-= ZEBRA_HEADER_SIZE
;
731 /* Read rest of zebra packet. */
732 nbytes
= stream_read (zclient
->ibuf
, sock
, length
);
733 if (nbytes
!= length
)
736 zlog_info ("zclient connection closed socket [%d].", sock
);
738 zclient_stop (zclient
);
739 zclient_event (ZCLIENT_CONNECT
, zclient
);
744 zlog_info("zclient 0x%p command 0x%x \n", zclient
, command
);
748 case ZEBRA_INTERFACE_ADD
:
749 if (zclient
->interface_add
)
750 ret
= (*zclient
->interface_add
) (command
, zclient
, length
);
752 case ZEBRA_INTERFACE_DELETE
:
753 if (zclient
->interface_delete
)
754 ret
= (*zclient
->interface_delete
) (command
, zclient
, length
);
756 case ZEBRA_INTERFACE_ADDRESS_ADD
:
757 if (zclient
->interface_address_add
)
758 ret
= (*zclient
->interface_address_add
) (command
, zclient
, length
);
760 case ZEBRA_INTERFACE_ADDRESS_DELETE
:
761 if (zclient
->interface_address_delete
)
762 ret
= (*zclient
->interface_address_delete
) (command
, zclient
, length
);
764 case ZEBRA_INTERFACE_UP
:
765 if (zclient
->interface_up
)
766 ret
= (*zclient
->interface_up
) (command
, zclient
, length
);
768 case ZEBRA_INTERFACE_DOWN
:
769 if (zclient
->interface_down
)
770 ret
= (*zclient
->interface_down
) (command
, zclient
, length
);
772 case ZEBRA_IPV4_ROUTE_ADD
:
773 if (zclient
->ipv4_route_add
)
774 ret
= (*zclient
->ipv4_route_add
) (command
, zclient
, length
);
776 case ZEBRA_IPV4_ROUTE_DELETE
:
777 if (zclient
->ipv4_route_delete
)
778 ret
= (*zclient
->ipv4_route_delete
) (command
, zclient
, length
);
780 case ZEBRA_IPV6_ROUTE_ADD
:
781 if (zclient
->ipv6_route_add
)
782 ret
= (*zclient
->ipv6_route_add
) (command
, zclient
, length
);
784 case ZEBRA_IPV6_ROUTE_DELETE
:
785 if (zclient
->ipv6_route_delete
)
786 ret
= (*zclient
->ipv6_route_delete
) (command
, zclient
, length
);
792 /* Register read thread. */
793 zclient_event (ZCLIENT_READ
, zclient
);
799 zclient_redistribute (int command
, struct zclient
*zclient
, int type
)
802 if (command
== ZEBRA_REDISTRIBUTE_ADD
)
804 if (zclient
->redist
[type
])
806 zclient
->redist
[type
] = 1;
810 if (!zclient
->redist
[type
])
812 zclient
->redist
[type
] = 0;
815 if (zclient
->sock
> 0)
816 zebra_redistribute_send (command
, zclient
->sock
, type
);
821 zclient_redistribute_default (int command
, struct zclient
*zclient
)
824 if (command
== ZEBRA_REDISTRIBUTE_DEFAULT_ADD
)
826 if (zclient
->default_information
)
828 zclient
->default_information
= 1;
832 if (!zclient
->default_information
)
834 zclient
->default_information
= 0;
837 if (zclient
->sock
> 0)
838 zebra_message_send (zclient
, command
);
842 extern struct thread_master
*master
;
845 zclient_event (enum event event
, struct zclient
*zclient
)
849 case ZCLIENT_SCHEDULE
:
850 if (! zclient
->t_connect
)
852 thread_add_event (master
, zclient_connect
, zclient
, 0);
854 case ZCLIENT_CONNECT
:
855 if (zclient
->fail
>= 10)
858 zlog_info ("zclient connect schedule interval is %d",
859 zclient
->fail
< 3 ? 10 : 60);
860 if (! zclient
->t_connect
)
862 thread_add_timer (master
, zclient_connect
, zclient
,
863 zclient
->fail
< 3 ? 10 : 60);
867 thread_add_read (master
, zclient_read
, zclient
, zclient
->sock
);