|
version 1.1, 2012/02/21 17:26:12
|
version 1.1.1.4, 2016/11/02 10:09:10
|
|
Line 32
|
Line 32
|
| #include "zclient.h" |
#include "zclient.h" |
| #include "memory.h" |
#include "memory.h" |
| #include "table.h" |
#include "table.h" |
| |
| /* Zebra client events. */ |
/* Zebra client events. */ |
| enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; |
enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; |
| |
|
| /* Prototype for event manager. */ |
/* Prototype for event manager. */ |
| static void zclient_event (enum event, struct zclient *); |
static void zclient_event (enum event, struct zclient *); |
| |
|
| extern struct thread_master *master; | const char *zclient_serv_path = NULL; |
| |
|
| /* This file local debug flag. */ |
/* This file local debug flag. */ |
| int zclient_debug = 0; |
int zclient_debug = 0; |
| |
| /* Allocate zclient structure. */ |
/* Allocate zclient structure. */ |
| struct zclient * |
struct zclient * |
| zclient_new () | zclient_new (struct thread_master *master) |
| { |
{ |
| struct zclient *zclient; |
struct zclient *zclient; |
| zclient = XCALLOC (MTYPE_ZCLIENT, sizeof (struct zclient)); |
zclient = XCALLOC (MTYPE_ZCLIENT, sizeof (struct zclient)); |
|
Line 54 zclient_new ()
|
Line 54 zclient_new ()
|
| zclient->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ); |
zclient->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ); |
| zclient->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ); |
zclient->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ); |
| zclient->wb = buffer_new(0); |
zclient->wb = buffer_new(0); |
| |
zclient->master = master; |
| |
|
| return zclient; |
return zclient; |
| } |
} |
|
Line 91 zclient_init (struct zclient *zclient, int redist_defa
|
Line 92 zclient_init (struct zclient *zclient, int redist_defa
|
| |
|
| /* Clear redistribution flags. */ |
/* Clear redistribution flags. */ |
| for (i = 0; i < ZEBRA_ROUTE_MAX; i++) |
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) |
| zclient->redist[i] = 0; | zclient->redist[i] = vrf_bitmap_init (); |
| |
|
| /* Set unwanted redistribute route. bgpd does not need BGP route |
/* Set unwanted redistribute route. bgpd does not need BGP route |
| redistribution. */ |
redistribution. */ |
| zclient->redist_default = redist_default; |
zclient->redist_default = redist_default; |
| zclient->redist[redist_default] = 1; |
|
| |
|
| /* Set default-information redistribute to zero. */ |
/* Set default-information redistribute to zero. */ |
| zclient->default_information = 0; | zclient->default_information = vrf_bitmap_init (); |
| |
|
| /* Schedule first zclient connection. */ |
/* Schedule first zclient connection. */ |
| if (zclient_debug) |
if (zclient_debug) |
|
Line 112 zclient_init (struct zclient *zclient, int redist_defa
|
Line 112 zclient_init (struct zclient *zclient, int redist_defa
|
| void |
void |
| zclient_stop (struct zclient *zclient) |
zclient_stop (struct zclient *zclient) |
| { |
{ |
| |
int i; |
| |
|
| if (zclient_debug) |
if (zclient_debug) |
| zlog_debug ("zclient stopped"); |
zlog_debug ("zclient stopped"); |
| |
|
|
Line 134 zclient_stop (struct zclient *zclient)
|
Line 136 zclient_stop (struct zclient *zclient)
|
| zclient->sock = -1; |
zclient->sock = -1; |
| } |
} |
| zclient->fail = 0; |
zclient->fail = 0; |
| |
|
| |
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) |
| |
{ |
| |
vrf_bitmap_free(zclient->redist[i]); |
| |
zclient->redist[i] = VRF_BITMAP_NULL; |
| |
} |
| |
vrf_bitmap_free(zclient->default_information); |
| |
zclient->default_information = VRF_BITMAP_NULL; |
| } |
} |
| |
|
| void |
void |
|
Line 143 zclient_reset (struct zclient *zclient)
|
Line 153 zclient_reset (struct zclient *zclient)
|
| zclient_init (zclient, zclient->redist_default); |
zclient_init (zclient, zclient->redist_default); |
| } |
} |
| |
|
| |
#ifdef HAVE_TCP_ZEBRA |
| |
|
| /* Make socket to zebra daemon. Return zebra socket. */ |
/* Make socket to zebra daemon. Return zebra socket. */ |
| int | static int |
| zclient_socket(void) |
zclient_socket(void) |
| { |
{ |
| int sock; |
int sock; |
|
Line 175 zclient_socket(void)
|
Line 187 zclient_socket(void)
|
| return sock; |
return sock; |
| } |
} |
| |
|
| |
#else |
| |
|
| /* For sockaddr_un. */ |
/* For sockaddr_un. */ |
| #include <sys/un.h> |
#include <sys/un.h> |
| |
|
| int | static int |
| zclient_socket_un (const char *path) |
zclient_socket_un (const char *path) |
| { |
{ |
| int ret; |
int ret; |
|
Line 208 zclient_socket_un (const char *path)
|
Line 222 zclient_socket_un (const char *path)
|
| return sock; |
return sock; |
| } |
} |
| |
|
| |
#endif /* HAVE_TCP_ZEBRA */ |
| |
|
| |
/** |
| |
* Connect to zebra daemon. |
| |
* @param zclient a pointer to zclient structure |
| |
* @return socket fd just to make sure that connection established |
| |
* @see zclient_init |
| |
* @see zclient_new |
| |
*/ |
| |
int |
| |
zclient_socket_connect (struct zclient *zclient) |
| |
{ |
| |
#ifdef HAVE_TCP_ZEBRA |
| |
zclient->sock = zclient_socket (); |
| |
#else |
| |
zclient->sock = zclient_socket_un (zclient_serv_path_get()); |
| |
#endif |
| |
return zclient->sock; |
| |
} |
| |
|
| static int |
static int |
| zclient_failed(struct zclient *zclient) |
zclient_failed(struct zclient *zclient) |
| { |
{ |
|
Line 233 zclient_flush_data(struct thread *thread)
|
Line 267 zclient_flush_data(struct thread *thread)
|
| return zclient_failed(zclient); |
return zclient_failed(zclient); |
| break; |
break; |
| case BUFFER_PENDING: |
case BUFFER_PENDING: |
| zclient->t_write = thread_add_write(master, zclient_flush_data, | zclient->t_write = thread_add_write (zclient->master, zclient_flush_data, |
| zclient, zclient->sock); | zclient, zclient->sock); |
| break; |
break; |
| case BUFFER_EMPTY: |
case BUFFER_EMPTY: |
| break; |
break; |
|
Line 259 zclient_send_message(struct zclient *zclient)
|
Line 293 zclient_send_message(struct zclient *zclient)
|
| THREAD_OFF(zclient->t_write); |
THREAD_OFF(zclient->t_write); |
| break; |
break; |
| case BUFFER_PENDING: |
case BUFFER_PENDING: |
| THREAD_WRITE_ON(master, zclient->t_write, | THREAD_WRITE_ON (zclient->master, zclient->t_write, |
| zclient_flush_data, zclient, zclient->sock); | zclient_flush_data, zclient, zclient->sock); |
| break; |
break; |
| } |
} |
| return 0; |
return 0; |
| } |
} |
| |
|
| void |
void |
| zclient_create_header (struct stream *s, uint16_t command) | zclient_create_header (struct stream *s, uint16_t command, vrf_id_t vrf_id) |
| { |
{ |
| /* length placeholder, caller can update */ |
/* length placeholder, caller can update */ |
| stream_putw (s, ZEBRA_HEADER_SIZE); |
stream_putw (s, ZEBRA_HEADER_SIZE); |
| stream_putc (s, ZEBRA_HEADER_MARKER); |
stream_putc (s, ZEBRA_HEADER_MARKER); |
| stream_putc (s, ZSERV_VERSION); |
stream_putc (s, ZSERV_VERSION); |
| |
stream_putw (s, vrf_id); |
| stream_putw (s, command); |
stream_putw (s, command); |
| } |
} |
| |
|
| |
int |
| |
zclient_read_header (struct stream *s, int sock, u_int16_t *size, u_char *marker, |
| |
u_char *version, u_int16_t *vrf_id, u_int16_t *cmd) |
| |
{ |
| |
if (stream_read (s, sock, ZEBRA_HEADER_SIZE) != ZEBRA_HEADER_SIZE) |
| |
return -1; |
| |
|
| |
*size = stream_getw (s) - ZEBRA_HEADER_SIZE; |
| |
*marker = stream_getc (s); |
| |
*version = stream_getc (s); |
| |
*vrf_id = stream_getw (s); |
| |
*cmd = stream_getw (s); |
| |
|
| |
if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) |
| |
{ |
| |
zlog_err("%s: socket %d version mismatch, marker %d, version %d", |
| |
__func__, sock, *marker, *version); |
| |
return -1; |
| |
} |
| |
|
| |
if (*size && stream_read (s, sock, *size) != *size) |
| |
return -1; |
| |
|
| |
return 0; |
| |
} |
| |
|
| /* Send simple Zebra message. */ |
/* Send simple Zebra message. */ |
| static int |
static int |
| zebra_message_send (struct zclient *zclient, int command) | zebra_message_send (struct zclient *zclient, int command, vrf_id_t vrf_id) |
| { |
{ |
| struct stream *s; |
struct stream *s; |
| |
|
|
Line 287 zebra_message_send (struct zclient *zclient, int comma
|
Line 348 zebra_message_send (struct zclient *zclient, int comma
|
| stream_reset (s); |
stream_reset (s); |
| |
|
| /* Send very simple command only Zebra message. */ |
/* Send very simple command only Zebra message. */ |
| zclient_create_header (s, command); | zclient_create_header (s, command, vrf_id); |
| |
|
| return zclient_send_message(zclient); |
return zclient_send_message(zclient); |
| } |
} |
| |
|
| |
static int |
| |
zebra_hello_send (struct zclient *zclient) |
| |
{ |
| |
struct stream *s; |
| |
|
| |
if (zclient->redist_default) |
| |
{ |
| |
s = zclient->obuf; |
| |
stream_reset (s); |
| |
|
| |
/* The VRF ID in the HELLO message is always 0. */ |
| |
zclient_create_header (s, ZEBRA_HELLO, VRF_DEFAULT); |
| |
stream_putc (s, zclient->redist_default); |
| |
stream_putw_at (s, 0, stream_get_endp (s)); |
| |
return zclient_send_message(zclient); |
| |
} |
| |
|
| |
return 0; |
| |
} |
| |
|
| |
/* Send requests to zebra daemon for the information in a VRF. */ |
| |
void |
| |
zclient_send_requests (struct zclient *zclient, vrf_id_t vrf_id) |
| |
{ |
| |
int i; |
| |
|
| |
/* zclient is disabled. */ |
| |
if (! zclient->enable) |
| |
return; |
| |
|
| |
/* If not connected to the zebra yet. */ |
| |
if (zclient->sock < 0) |
| |
return; |
| |
|
| |
if (zclient_debug) |
| |
zlog_debug ("%s: send messages for VRF %u", __func__, vrf_id); |
| |
|
| |
/* We need router-id information. */ |
| |
zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD, vrf_id); |
| |
|
| |
/* We need interface information. */ |
| |
zebra_message_send (zclient, ZEBRA_INTERFACE_ADD, vrf_id); |
| |
|
| |
/* Set unwanted redistribute route. */ |
| |
vrf_bitmap_set (zclient->redist[zclient->redist_default], vrf_id); |
| |
|
| |
/* Flush all redistribute request. */ |
| |
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) |
| |
if (i != zclient->redist_default && |
| |
vrf_bitmap_check (zclient->redist[i], vrf_id)) |
| |
zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, i, vrf_id); |
| |
|
| |
/* If default information is needed. */ |
| |
if (vrf_bitmap_check (zclient->default_information, VRF_DEFAULT)) |
| |
zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, vrf_id); |
| |
} |
| |
|
| /* Make connection to zebra daemon. */ |
/* Make connection to zebra daemon. */ |
| int |
int |
| zclient_start (struct zclient *zclient) |
zclient_start (struct zclient *zclient) |
| { |
{ |
| int i; |
|
| |
|
| if (zclient_debug) |
if (zclient_debug) |
| zlog_debug ("zclient_start is called"); |
zlog_debug ("zclient_start is called"); |
| |
|
|
Line 313 zclient_start (struct zclient *zclient)
|
Line 429 zclient_start (struct zclient *zclient)
|
| if (zclient->t_connect) |
if (zclient->t_connect) |
| return 0; |
return 0; |
| |
|
| /* Make socket. */ | if (zclient_socket_connect(zclient) < 0) |
| #ifdef HAVE_TCP_ZEBRA | |
| zclient->sock = zclient_socket (); | |
| #else | |
| zclient->sock = zclient_socket_un (ZEBRA_SERV_PATH); | |
| #endif /* HAVE_TCP_ZEBRA */ | |
| if (zclient->sock < 0) | |
| { |
{ |
| if (zclient_debug) |
if (zclient_debug) |
| zlog_debug ("zclient connection fail"); |
zlog_debug ("zclient connection fail"); |
|
Line 339 zclient_start (struct zclient *zclient)
|
Line 449 zclient_start (struct zclient *zclient)
|
| /* Create read thread. */ |
/* Create read thread. */ |
| zclient_event (ZCLIENT_READ, zclient); |
zclient_event (ZCLIENT_READ, zclient); |
| |
|
| /* We need router-id information. */ | zebra_hello_send (zclient); |
| zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD); | |
| |
|
| /* We need interface information. */ | /* Inform the successful connection. */ |
| zebra_message_send (zclient, ZEBRA_INTERFACE_ADD); | if (zclient->zebra_connected) |
| | (*zclient->zebra_connected) (zclient); |
| |
|
| /* Flush all redistribute request. */ |
|
| for (i = 0; i < ZEBRA_ROUTE_MAX; i++) |
|
| if (i != zclient->redist_default && zclient->redist[i]) |
|
| zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, i); |
|
| |
|
| /* If default information is needed. */ |
|
| if (zclient->default_information) |
|
| zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD); |
|
| |
|
| return 0; |
return 0; |
| } |
} |
| |
|
|
Line 372 zclient_connect (struct thread *t)
|
Line 473 zclient_connect (struct thread *t)
|
| |
|
| return zclient_start (zclient); |
return zclient_start (zclient); |
| } |
} |
| |
| /* |
/* |
| * "xdr_encode"-like interface that allows daemon (client) to send |
* "xdr_encode"-like interface that allows daemon (client) to send |
| * a message to zebra server for a route that needs to be |
* a message to zebra server for a route that needs to be |
|
Line 428 zapi_ipv4_route (u_char cmd, struct zclient *zclient,
|
Line 529 zapi_ipv4_route (u_char cmd, struct zclient *zclient,
|
| /* Reset stream. */ |
/* Reset stream. */ |
| s = zclient->obuf; |
s = zclient->obuf; |
| stream_reset (s); |
stream_reset (s); |
| |
|
| |
zclient_create_header (s, cmd, api->vrf_id); |
| |
|
| zclient_create_header (s, cmd); |
|
| |
|
| /* Put type and nexthop. */ |
/* Put type and nexthop. */ |
| stream_putc (s, api->type); |
stream_putc (s, api->type); |
| stream_putc (s, api->flags); |
stream_putc (s, api->flags); |
| stream_putc (s, api->message); |
stream_putc (s, api->message); |
| |
stream_putw (s, api->safi); |
| |
|
| /* Put prefix information. */ |
/* Put prefix information. */ |
| psize = PSIZE (p->prefixlen); |
psize = PSIZE (p->prefixlen); |
|
Line 470 zapi_ipv4_route (u_char cmd, struct zclient *zclient,
|
Line 572 zapi_ipv4_route (u_char cmd, struct zclient *zclient,
|
| stream_putc (s, api->distance); |
stream_putc (s, api->distance); |
| if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) |
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) |
| stream_putl (s, api->metric); |
stream_putl (s, api->metric); |
| |
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) |
| |
stream_putl (s, api->mtu); |
| |
|
| /* Put length at the first point of the stream. */ |
/* Put length at the first point of the stream. */ |
| stream_putw_at (s, 0, stream_get_endp (s)); |
stream_putw_at (s, 0, stream_get_endp (s)); |
|
Line 490 zapi_ipv6_route (u_char cmd, struct zclient *zclient,
|
Line 594 zapi_ipv6_route (u_char cmd, struct zclient *zclient,
|
| s = zclient->obuf; |
s = zclient->obuf; |
| stream_reset (s); |
stream_reset (s); |
| |
|
| zclient_create_header (s, cmd); | zclient_create_header (s, cmd, api->vrf_id); |
| |
|
| /* Put type and nexthop. */ |
/* Put type and nexthop. */ |
| stream_putc (s, api->type); |
stream_putc (s, api->type); |
| stream_putc (s, api->flags); |
stream_putc (s, api->flags); |
| stream_putc (s, api->message); |
stream_putc (s, api->message); |
| |
stream_putw (s, api->safi); |
| |
|
| /* Put prefix information. */ |
/* Put prefix information. */ |
| psize = PSIZE (p->prefixlen); |
psize = PSIZE (p->prefixlen); |
|
Line 523 zapi_ipv6_route (u_char cmd, struct zclient *zclient,
|
Line 628 zapi_ipv6_route (u_char cmd, struct zclient *zclient,
|
| stream_putc (s, api->distance); |
stream_putc (s, api->distance); |
| if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) |
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) |
| stream_putl (s, api->metric); |
stream_putl (s, api->metric); |
| |
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) |
| |
stream_putl (s, api->mtu); |
| |
|
| /* Put length at the first point of the stream. */ |
/* Put length at the first point of the stream. */ |
| stream_putw_at (s, 0, stream_get_endp (s)); |
stream_putw_at (s, 0, stream_get_endp (s)); |
|
Line 538 zapi_ipv6_route (u_char cmd, struct zclient *zclient,
|
Line 645 zapi_ipv6_route (u_char cmd, struct zclient *zclient,
|
| * sending client |
* sending client |
| */ |
*/ |
| int |
int |
| zebra_redistribute_send (int command, struct zclient *zclient, int type) | zebra_redistribute_send (int command, struct zclient *zclient, int type, |
| | vrf_id_t vrf_id) |
| { |
{ |
| struct stream *s; |
struct stream *s; |
| |
|
| s = zclient->obuf; |
s = zclient->obuf; |
| stream_reset(s); |
stream_reset(s); |
| |
|
| zclient_create_header (s, command); | zclient_create_header (s, command, vrf_id); |
| stream_putc (s, type); |
stream_putc (s, type); |
| |
|
| stream_putw_at (s, 0, stream_get_endp (s)); |
stream_putw_at (s, 0, stream_get_endp (s)); |
|
Line 553 zebra_redistribute_send (int command, struct zclient *
|
Line 661 zebra_redistribute_send (int command, struct zclient *
|
| return zclient_send_message(zclient); |
return zclient_send_message(zclient); |
| } |
} |
| |
|
| |
/* Get prefix in ZServ format; family should be filled in on prefix */ |
| |
static void |
| |
zclient_stream_get_prefix (struct stream *s, struct prefix *p) |
| |
{ |
| |
size_t plen = prefix_blen (p); |
| |
u_char c; |
| |
p->prefixlen = 0; |
| |
|
| |
if (plen == 0) |
| |
return; |
| |
|
| |
stream_get (&p->u.prefix, s, plen); |
| |
c = stream_getc(s); |
| |
p->prefixlen = MIN(plen * 8, c); |
| |
} |
| |
|
| /* Router-id update from zebra daemon. */ |
/* Router-id update from zebra daemon. */ |
| void |
void |
| zebra_router_id_update_read (struct stream *s, struct prefix *rid) |
zebra_router_id_update_read (struct stream *s, struct prefix *rid) |
| { |
{ |
| int plen; |
|
| |
|
| /* Fetch interface address. */ |
/* Fetch interface address. */ |
| rid->family = stream_getc (s); |
rid->family = stream_getc (s); |
| |
| plen = prefix_blen (rid); | zclient_stream_get_prefix (s, rid); |
| stream_get (&rid->u.prefix, s, plen); | |
| rid->prefixlen = stream_getc (s); | |
| } |
} |
| |
|
| /* Interface addition from zebra daemon. */ |
/* Interface addition from zebra daemon. */ |
|
Line 600 zebra_router_id_update_read (struct stream *s, struct
|
Line 720 zebra_router_id_update_read (struct stream *s, struct
|
| */ |
*/ |
| |
|
| struct interface * |
struct interface * |
| zebra_interface_add_read (struct stream *s) | zebra_interface_add_read (struct stream *s, vrf_id_t vrf_id) |
| { |
{ |
| struct interface *ifp; |
struct interface *ifp; |
| char ifname_tmp[INTERFACE_NAMSIZ]; |
char ifname_tmp[INTERFACE_NAMSIZ]; |
|
Line 609 zebra_interface_add_read (struct stream *s)
|
Line 729 zebra_interface_add_read (struct stream *s)
|
| stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); |
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); |
| |
|
| /* Lookup/create interface by name. */ |
/* Lookup/create interface by name. */ |
| ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ)); | ifp = if_get_by_name_len_vrf (ifname_tmp, |
| | strnlen (ifname_tmp, INTERFACE_NAMSIZ), |
| | vrf_id); |
| |
|
| /* Read interface's index. */ | zebra_interface_if_set_value (s, ifp); |
| ifp->ifindex = stream_getl (s); | |
| |
|
| /* Read interface's value. */ |
|
| ifp->status = stream_getc (s); |
|
| ifp->flags = stream_getq (s); |
|
| ifp->metric = stream_getl (s); |
|
| ifp->mtu = stream_getl (s); |
|
| ifp->mtu6 = stream_getl (s); |
|
| ifp->bandwidth = stream_getl (s); |
|
| #ifdef HAVE_STRUCT_SOCKADDR_DL |
|
| stream_get (&ifp->sdl, s, sizeof (ifp->sdl)); |
|
| #else |
|
| ifp->hw_addr_len = stream_getl (s); |
|
| if (ifp->hw_addr_len) |
|
| stream_get (ifp->hw_addr, s, ifp->hw_addr_len); |
|
| #endif /* HAVE_STRUCT_SOCKADDR_DL */ |
|
| |
|
| return ifp; |
return ifp; |
| } |
} |
| |
|
|
Line 640 zebra_interface_add_read (struct stream *s)
|
Line 746 zebra_interface_add_read (struct stream *s)
|
| * is sent at the tail of the message. |
* is sent at the tail of the message. |
| */ |
*/ |
| struct interface * |
struct interface * |
| zebra_interface_state_read (struct stream *s) | zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id) |
| { |
{ |
| struct interface *ifp; |
struct interface *ifp; |
| char ifname_tmp[INTERFACE_NAMSIZ]; |
char ifname_tmp[INTERFACE_NAMSIZ]; |
|
Line 649 zebra_interface_state_read (struct stream *s)
|
Line 755 zebra_interface_state_read (struct stream *s)
|
| stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); |
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); |
| |
|
| /* Lookup this by interface index. */ |
/* Lookup this by interface index. */ |
| ifp = if_lookup_by_name_len (ifname_tmp, | ifp = if_lookup_by_name_len_vrf (ifname_tmp, |
| strnlen(ifname_tmp, INTERFACE_NAMSIZ)); | strnlen (ifname_tmp, INTERFACE_NAMSIZ), |
| | vrf_id); |
| |
|
| /* If such interface does not exist, indicate an error */ |
/* If such interface does not exist, indicate an error */ |
| if (! ifp) |
if (! ifp) |
| return NULL; |
return NULL; |
| |
|
| /* Read interface's index. */ | zebra_interface_if_set_value (s, ifp); |
| ifp->ifindex = stream_getl (s); | |
| |
|
| /* Read interface's value. */ |
|
| ifp->status = stream_getc (s); |
|
| ifp->flags = stream_getq (s); |
|
| ifp->metric = stream_getl (s); |
|
| ifp->mtu = stream_getl (s); |
|
| ifp->mtu6 = stream_getl (s); |
|
| ifp->bandwidth = stream_getl (s); |
|
| |
|
| return ifp; |
return ifp; |
| } |
} |
| |
|
|
Line 715 zebra_interface_if_set_value (struct stream *s, struct
|
Line 813 zebra_interface_if_set_value (struct stream *s, struct
|
| ifp->mtu = stream_getl (s); |
ifp->mtu = stream_getl (s); |
| ifp->mtu6 = stream_getl (s); |
ifp->mtu6 = stream_getl (s); |
| ifp->bandwidth = stream_getl (s); |
ifp->bandwidth = stream_getl (s); |
| |
ifp->ll_type = stream_getl (s); |
| |
ifp->hw_addr_len = stream_getl (s); |
| |
if (ifp->hw_addr_len) |
| |
stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX)); |
| } |
} |
| |
|
| static int |
static int |
|
Line 729 memconstant(const void *s, int c, size_t n)
|
Line 831 memconstant(const void *s, int c, size_t n)
|
| } |
} |
| |
|
| struct connected * |
struct connected * |
| zebra_interface_address_read (int type, struct stream *s) | zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id) |
| { |
{ |
| unsigned int ifindex; | ifindex_t ifindex; |
| struct interface *ifp; |
struct interface *ifp; |
| struct connected *ifc; |
struct connected *ifc; |
| struct prefix p, d; | struct prefix p, d, *dp; |
| int family; | |
| int plen; |
int plen; |
| u_char ifc_flags; |
u_char ifc_flags; |
| |
|
|
Line 746 zebra_interface_address_read (int type, struct stream
|
Line 847 zebra_interface_address_read (int type, struct stream
|
| ifindex = stream_getl (s); |
ifindex = stream_getl (s); |
| |
|
| /* Lookup index. */ |
/* Lookup index. */ |
| ifp = if_lookup_by_index (ifindex); | ifp = if_lookup_by_index_vrf (ifindex, vrf_id); |
| if (ifp == NULL) |
if (ifp == NULL) |
| { |
{ |
| zlog_warn ("zebra_interface_address_read(%s): " |
zlog_warn ("zebra_interface_address_read(%s): " |
|
Line 760 zebra_interface_address_read (int type, struct stream
|
Line 861 zebra_interface_address_read (int type, struct stream
|
| ifc_flags = stream_getc (s); |
ifc_flags = stream_getc (s); |
| |
|
| /* Fetch interface address. */ |
/* Fetch interface address. */ |
| family = p.family = stream_getc (s); | d.family = p.family = stream_getc (s); |
| | plen = prefix_blen (&d); |
| | |
| | zclient_stream_get_prefix (s, &p); |
| |
|
| plen = prefix_blen (&p); |
|
| stream_get (&p.u.prefix, s, plen); |
|
| p.prefixlen = stream_getc (s); |
|
| |
|
| /* Fetch destination address. */ |
/* Fetch destination address. */ |
| stream_get (&d.u.prefix, s, plen); |
stream_get (&d.u.prefix, s, plen); |
| d.family = family; | |
| /* N.B. NULL destination pointers are encoded as all zeroes */ |
| | dp = memconstant(&d.u.prefix,0,plen) ? NULL : &d; |
| | |
| if (type == ZEBRA_INTERFACE_ADDRESS_ADD) |
if (type == ZEBRA_INTERFACE_ADDRESS_ADD) |
| { |
{ |
| /* N.B. NULL destination pointers are encoded as all zeroes */ |
/* N.B. NULL destination pointers are encoded as all zeroes */ |
| ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ? | ifc = connected_add_by_prefix(ifp, &p, dp); |
| NULL : &d)); | |
| if (ifc != NULL) |
if (ifc != NULL) |
| { |
{ |
| ifc->flags = ifc_flags; |
ifc->flags = ifc_flags; |
| if (ifc->destination) |
if (ifc->destination) |
| ifc->destination->prefixlen = ifc->address->prefixlen; |
ifc->destination->prefixlen = ifc->address->prefixlen; |
| |
else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) |
| |
{ |
| |
/* carp interfaces on OpenBSD with 0.0.0.0/0 as "peer" */ |
| |
char buf[PREFIX_STRLEN]; |
| |
zlog_warn("warning: interface %s address %s " |
| |
"with peer flag set, but no peer address!", |
| |
ifp->name, |
| |
prefix2str (ifc->address, buf, sizeof buf)); |
| |
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); |
| |
} |
| } |
} |
| } |
} |
| else |
else |
|
Line 791 zebra_interface_address_read (int type, struct stream
|
Line 902 zebra_interface_address_read (int type, struct stream
|
| return ifc; |
return ifc; |
| } |
} |
| |
|
| |
| /* Zebra client message read function. */ |
/* Zebra client message read function. */ |
| static int |
static int |
| zclient_read (struct thread *thread) |
zclient_read (struct thread *thread) |
| { |
{ |
| int ret; |
|
| size_t already; |
size_t already; |
| uint16_t length, command; |
uint16_t length, command; |
| uint8_t marker, version; |
uint8_t marker, version; |
| |
vrf_id_t vrf_id; |
| struct zclient *zclient; |
struct zclient *zclient; |
| |
|
| /* Get socket to zebra. */ |
/* Get socket to zebra. */ |
|
Line 834 zclient_read (struct thread *thread)
|
Line 945 zclient_read (struct thread *thread)
|
| length = stream_getw (zclient->ibuf); |
length = stream_getw (zclient->ibuf); |
| marker = stream_getc (zclient->ibuf); |
marker = stream_getc (zclient->ibuf); |
| version = stream_getc (zclient->ibuf); |
version = stream_getc (zclient->ibuf); |
| |
vrf_id = stream_getw (zclient->ibuf); |
| command = stream_getw (zclient->ibuf); |
command = stream_getw (zclient->ibuf); |
| |
|
| if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) |
if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) |
|
Line 885 zclient_read (struct thread *thread)
|
Line 997 zclient_read (struct thread *thread)
|
| length -= ZEBRA_HEADER_SIZE; |
length -= ZEBRA_HEADER_SIZE; |
| |
|
| if (zclient_debug) |
if (zclient_debug) |
| zlog_debug("zclient 0x%p command 0x%x \n", zclient, command); | zlog_debug("zclient 0x%p command 0x%x VRF %u\n", (void *)zclient, command, vrf_id); |
| |
|
| switch (command) |
switch (command) |
| { |
{ |
| case ZEBRA_ROUTER_ID_UPDATE: |
case ZEBRA_ROUTER_ID_UPDATE: |
| if (zclient->router_id_update) |
if (zclient->router_id_update) |
| ret = (*zclient->router_id_update) (command, zclient, length); | (*zclient->router_id_update) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_INTERFACE_ADD: |
case ZEBRA_INTERFACE_ADD: |
| if (zclient->interface_add) |
if (zclient->interface_add) |
| ret = (*zclient->interface_add) (command, zclient, length); | (*zclient->interface_add) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_INTERFACE_DELETE: |
case ZEBRA_INTERFACE_DELETE: |
| if (zclient->interface_delete) |
if (zclient->interface_delete) |
| ret = (*zclient->interface_delete) (command, zclient, length); | (*zclient->interface_delete) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_INTERFACE_ADDRESS_ADD: |
case ZEBRA_INTERFACE_ADDRESS_ADD: |
| if (zclient->interface_address_add) |
if (zclient->interface_address_add) |
| ret = (*zclient->interface_address_add) (command, zclient, length); | (*zclient->interface_address_add) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_INTERFACE_ADDRESS_DELETE: |
case ZEBRA_INTERFACE_ADDRESS_DELETE: |
| if (zclient->interface_address_delete) |
if (zclient->interface_address_delete) |
| ret = (*zclient->interface_address_delete) (command, zclient, length); | (*zclient->interface_address_delete) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_INTERFACE_UP: |
case ZEBRA_INTERFACE_UP: |
| if (zclient->interface_up) |
if (zclient->interface_up) |
| ret = (*zclient->interface_up) (command, zclient, length); | (*zclient->interface_up) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_INTERFACE_DOWN: |
case ZEBRA_INTERFACE_DOWN: |
| if (zclient->interface_down) |
if (zclient->interface_down) |
| ret = (*zclient->interface_down) (command, zclient, length); | (*zclient->interface_down) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_IPV4_ROUTE_ADD: |
case ZEBRA_IPV4_ROUTE_ADD: |
| if (zclient->ipv4_route_add) |
if (zclient->ipv4_route_add) |
| ret = (*zclient->ipv4_route_add) (command, zclient, length); | (*zclient->ipv4_route_add) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_IPV4_ROUTE_DELETE: |
case ZEBRA_IPV4_ROUTE_DELETE: |
| if (zclient->ipv4_route_delete) |
if (zclient->ipv4_route_delete) |
| ret = (*zclient->ipv4_route_delete) (command, zclient, length); | (*zclient->ipv4_route_delete) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_IPV6_ROUTE_ADD: |
case ZEBRA_IPV6_ROUTE_ADD: |
| if (zclient->ipv6_route_add) |
if (zclient->ipv6_route_add) |
| ret = (*zclient->ipv6_route_add) (command, zclient, length); | (*zclient->ipv6_route_add) (command, zclient, length, vrf_id); |
| break; |
break; |
| case ZEBRA_IPV6_ROUTE_DELETE: |
case ZEBRA_IPV6_ROUTE_DELETE: |
| if (zclient->ipv6_route_delete) |
if (zclient->ipv6_route_delete) |
| ret = (*zclient->ipv6_route_delete) (command, zclient, length); | (*zclient->ipv6_route_delete) (command, zclient, length, vrf_id); |
| break; |
break; |
| default: |
default: |
| break; |
break; |
|
Line 949 zclient_read (struct thread *thread)
|
Line 1061 zclient_read (struct thread *thread)
|
| } |
} |
| |
|
| void |
void |
| zclient_redistribute (int command, struct zclient *zclient, int type) | zclient_redistribute (int command, struct zclient *zclient, int type, |
| | vrf_id_t vrf_id) |
| { |
{ |
| |
|
| if (command == ZEBRA_REDISTRIBUTE_ADD) |
if (command == ZEBRA_REDISTRIBUTE_ADD) |
| { |
{ |
| if (zclient->redist[type]) | if (vrf_bitmap_check (zclient->redist[type], vrf_id)) |
| return; |
return; |
| zclient->redist[type] = 1; | vrf_bitmap_set (zclient->redist[type], vrf_id); |
| } |
} |
| else |
else |
| { |
{ |
| if (!zclient->redist[type]) | if (!vrf_bitmap_check (zclient->redist[type], vrf_id)) |
| return; |
return; |
| zclient->redist[type] = 0; | vrf_bitmap_unset (zclient->redist[type], vrf_id); |
| } |
} |
| |
|
| if (zclient->sock > 0) |
if (zclient->sock > 0) |
| zebra_redistribute_send (command, zclient, type); | zebra_redistribute_send (command, zclient, type, vrf_id); |
| } |
} |
| |
|
| |
|
| void |
void |
| zclient_redistribute_default (int command, struct zclient *zclient) | zclient_redistribute_default (int command, struct zclient *zclient, |
| | vrf_id_t vrf_id) |
| { |
{ |
| |
|
| if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) |
if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) |
| { |
{ |
| if (zclient->default_information) | if (vrf_bitmap_check (zclient->default_information, vrf_id)) |
| return; |
return; |
| zclient->default_information = 1; | vrf_bitmap_set (zclient->default_information, vrf_id); |
| } |
} |
| else |
else |
| { |
{ |
| if (!zclient->default_information) | if (!vrf_bitmap_check (zclient->default_information, vrf_id)) |
| return; |
return; |
| zclient->default_information = 0; | vrf_bitmap_unset (zclient->default_information, vrf_id); |
| } |
} |
| |
|
| if (zclient->sock > 0) |
if (zclient->sock > 0) |
| zebra_message_send (zclient, command); | zebra_message_send (zclient, command, vrf_id); |
| } |
} |
| |
|
| static void |
static void |
|
Line 999 zclient_event (enum event event, struct zclient *zclie
|
Line 1113 zclient_event (enum event event, struct zclient *zclie
|
| case ZCLIENT_SCHEDULE: |
case ZCLIENT_SCHEDULE: |
| if (! zclient->t_connect) |
if (! zclient->t_connect) |
| zclient->t_connect = |
zclient->t_connect = |
| thread_add_event (master, zclient_connect, zclient, 0); | thread_add_event (zclient->master, zclient_connect, zclient, 0); |
| break; |
break; |
| case ZCLIENT_CONNECT: |
case ZCLIENT_CONNECT: |
| if (zclient->fail >= 10) |
if (zclient->fail >= 10) |
|
Line 1009 zclient_event (enum event event, struct zclient *zclie
|
Line 1123 zclient_event (enum event event, struct zclient *zclie
|
| zclient->fail < 3 ? 10 : 60); |
zclient->fail < 3 ? 10 : 60); |
| if (! zclient->t_connect) |
if (! zclient->t_connect) |
| zclient->t_connect = |
zclient->t_connect = |
| thread_add_timer (master, zclient_connect, zclient, | thread_add_timer (zclient->master, zclient_connect, zclient, |
| zclient->fail < 3 ? 10 : 60); |
zclient->fail < 3 ? 10 : 60); |
| break; |
break; |
| case ZCLIENT_READ: |
case ZCLIENT_READ: |
| zclient->t_read = |
zclient->t_read = |
| thread_add_read (master, zclient_read, zclient, zclient->sock); | thread_add_read (zclient->master, zclient_read, zclient, zclient->sock); |
| break; |
break; |
| } |
} |
| } |
} |
| |
|
| |
const char *zclient_serv_path_get() |
| |
{ |
| |
return zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH; |
| |
} |
| |
|
| |
void |
| |
zclient_serv_path_set (char *path) |
| |
{ |
| |
struct stat sb; |
| |
|
| |
/* reset */ |
| |
zclient_serv_path = NULL; |
| |
|
| |
/* test if `path' is socket. don't set it otherwise. */ |
| |
if (stat(path, &sb) == -1) |
| |
{ |
| |
zlog_warn ("%s: zebra socket `%s' does not exist", __func__, path); |
| |
return; |
| |
} |
| |
|
| |
if ((sb.st_mode & S_IFMT) != S_IFSOCK) |
| |
{ |
| |
zlog_warn ("%s: `%s' is not unix socket, sir", __func__, path); |
| |
return; |
| |
} |
| |
|
| |
/* it seems that path is unix socket */ |
| |
zclient_serv_path = path; |
| |
} |
| |
|