/* Prototype for event manager. */
static void zclient_event (enum event, struct zclient *);
-char *zclient_serv_path = NULL;
+const char *zclient_serv_path = NULL;
/* This file local debug flag. */
int zclient_debug = 0;
ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv));
if (ret < 0)
{
+ zlog_warn ("%s connect failure: %d", __PRETTY_FUNCTION__, errno);
close (sock);
return -1;
}
ret = connect (sock, (struct sockaddr *) &addr, len);
if (ret < 0)
{
+ zlog_warn ("%s connect failure: %d", __PRETTY_FUNCTION__, errno);
close (sock);
return -1;
}
#ifdef HAVE_TCP_ZEBRA
zclient->sock = zclient_socket ();
#else
- zclient->sock = zclient_socket_un (zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH);
+ zclient->sock = zclient_socket_un (zclient_serv_path_get());
#endif
return zclient->sock;
}
stream_putw (s, command);
}
+int
+zclient_read_header (struct stream *s, int sock, u_int16_t *size, u_char *marker,
+ u_char *version, vrf_id_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. */
static int
zebra_message_send (struct zclient *zclient, int command, vrf_id_t vrf_id)
return 0;
}
-/* Send requests to zebra daemon for the information in a VRF. */
+/* Send register requests to zebra daemon for the information in a VRF. */
void
-zclient_send_requests (struct zclient *zclient, vrf_id_t vrf_id)
+zclient_send_reg_requests (struct zclient *zclient, vrf_id_t vrf_id)
{
int i;
afi_t afi;
return;
if (zclient_debug)
- zlog_debug ("%s: send messages for VRF %u", __func__, vrf_id);
+ zlog_debug ("%s: send register messages for VRF %u", __func__, vrf_id);
/* We need router-id information. */
zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD, vrf_id);
zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, vrf_id);
}
+/* Send unregister requests to zebra daemon for the information in a VRF. */
+void
+zclient_send_dereg_requests (struct zclient *zclient, vrf_id_t vrf_id)
+{
+ int i;
+ afi_t afi;
+
+ /* 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 deregister messages for VRF %u", __func__, vrf_id);
+
+ /* We need router-id information. */
+ zebra_message_send (zclient, ZEBRA_ROUTER_ID_DELETE, vrf_id);
+
+ /* We need interface information. */
+ zebra_message_send (zclient, ZEBRA_INTERFACE_DELETE, vrf_id);
+
+ /* Set unwanted redistribute route. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ vrf_bitmap_set (zclient->redist[afi][zclient->redist_default], vrf_id);
+
+ /* Flush all redistribute request. */
+ if (vrf_id == VRF_DEFAULT)
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (zclient->mi_redist[afi][i].enabled)
+ {
+ struct listnode *node;
+ u_short *id;
+
+ for (ALL_LIST_ELEMENTS_RO(zclient->mi_redist[afi][i].instances, node, id))
+ if (!(i == zclient->redist_default && *id == zclient->instance))
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, i,
+ *id, VRF_DEFAULT);
+ }
+
+ /* Flush all redistribute request. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (i != zclient->redist_default &&
+ vrf_bitmap_check (zclient->redist[afi][i], vrf_id))
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, i, 0, vrf_id);
+
+ /* If default information is needed. */
+ if (vrf_bitmap_check (zclient->default_information, VRF_DEFAULT))
+ zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, vrf_id);
+}
+
+/* Send request to zebra daemon to start or stop RA. */
+void
+zclient_send_interface_radv_req (struct zclient *zclient, vrf_id_t vrf_id,
+ struct interface *ifp, int enable, int ra_interval)
+{
+ struct stream *s;
+
+ /* zclient is disabled. */
+ if (!zclient->enable)
+ return;
+
+ /* If not connected to the zebra yet. */
+ if (zclient->sock < 0)
+ return;
+
+ /* Form and send message. */
+ s = zclient->obuf;
+ stream_reset (s);
+
+ if (enable)
+ zclient_create_header (s, ZEBRA_INTERFACE_ENABLE_RADV, vrf_id);
+ else
+ zclient_create_header (s, ZEBRA_INTERFACE_DISABLE_RADV, vrf_id);
+
+ stream_putl (s, ifp->ifindex);
+ stream_putl (s, ra_interval);
+
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ zclient_send_message(zclient);
+}
+
/* Make connection to zebra daemon. */
int
zclient_start (struct zclient *zclient)
if (zclient->t_connect)
return 0;
- if (zclient_socket_connect(zclient) < 0)
+ /*
+ * If we fail to connect to the socket on initialization,
+ * Let's wait a second and see if we can reconnect.
+ * Cause if we don't connect, we never attempt to
+ * reconnect. On startup if zebra is slow we
+ * can get into this situation.
+ */
+ while (zclient_socket_connect(zclient) < 0 && zclient->fail < 5)
{
if (zclient_debug)
zlog_debug ("zclient connection fail");
zclient->fail++;
+ sleep (1);
+ }
+
+ if (zclient->sock < 0)
+ {
zclient_event (ZCLIENT_CONNECT, zclient);
return -1;
}
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
+static void
+zclient_vrf_add (struct zclient *zclient, vrf_id_t vrf_id)
+{
+ struct vrf *vrf;
+ char vrfname_tmp[VRF_NAMSIZ];
+
+ /* Read interface name. */
+ stream_get (vrfname_tmp, zclient->ibuf, VRF_NAMSIZ);
+
+ /* Lookup/create vrf by vrf_id. */
+ vrf = vrf_get (vrf_id, vrfname_tmp);
+
+ vrf_enable (vrf);
+}
+
+static void
+zclient_vrf_delete (struct zclient *zclient, vrf_id_t vrf_id)
+{
+ struct vrf *vrf;
+
+ /* Lookup vrf by vrf_id. */
+ vrf = vrf_lookup (vrf_id);
+
+ /*
+ * If a routing protocol doesn't know about a
+ * vrf that is about to be deleted. There is
+ * no point in attempting to delete it.
+ */
+ if (!vrf)
+ return;
+
+ vrf_delete (vrf);
+}
+
struct interface *
zebra_interface_add_read (struct stream *s, vrf_id_t vrf_id)
{
/* Lookup/create interface by name. */
ifp = if_get_by_name_len_vrf (ifname_tmp,
strnlen (ifname_tmp, INTERFACE_NAMSIZ),
- vrf_id);
+ vrf_id, 0);
zebra_interface_if_set_value (s, ifp);
ifp = if_lookup_by_name_len_vrf (ifname_tmp,
strnlen (ifname_tmp, INTERFACE_NAMSIZ),
vrf_id);
-
- /* If such interface does not exist, indicate an error */
- if (! ifp)
- return NULL;
+ if (ifp == NULL)
+ {
+ zlog_warn ("INTERFACE_STATE: Cannot find IF %s in VRF %d",
+ ifname_tmp, vrf_id);
+ return NULL;
+ }
zebra_interface_if_set_value (s, ifp);
#else
ifp->hw_addr_len = stream_getl (s);
if (ifp->hw_addr_len)
- stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
+ stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX));
#endif /* HAVE_STRUCT_SOCKADDR_DL */
}
struct connected *
zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id)
{
- unsigned int ifindex;
+ ifindex_t ifindex;
struct interface *ifp;
struct connected *ifc;
struct prefix p, d;
ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
if (ifp == NULL)
{
- zlog_warn ("zebra_interface_address_read(%s): "
- "Can't find interface by ifindex: %d ",
- (type == ZEBRA_INTERFACE_ADDRESS_ADD? "ADD" : "DELETE"),
- ifindex);
+ zlog_warn ("INTERFACE_ADDRESS_%s: Cannot find IF %u in VRF %d",
+ (type == ZEBRA_INTERFACE_ADDRESS_ADD) ? "ADD" : "DEL",
+ ifindex, vrf_id);
return NULL;
}
if (type == ZEBRA_INTERFACE_ADDRESS_ADD)
{
- /* N.B. NULL destination pointers are encoded as all zeroes */
- ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
- NULL : &d));
- if (ifc != NULL)
+ ifc = connected_lookup_prefix_exact (ifp, &p);
+ if (!ifc)
+ {
+ /* N.B. NULL destination pointers are encoded as all zeroes */
+ ifc = connected_add_by_prefix(ifp, &p, (memconstant(&d.u.prefix,0,plen) ?
+ NULL : &d));
+ }
+ if (ifc)
{
ifc->flags = ifc_flags;
if (ifc->destination)
else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
{
/* carp interfaces on OpenBSD with 0.0.0.0/0 as "peer" */
- char buf[BUFSIZ];
- prefix2str (ifc->address, buf, sizeof(buf));
+ char buf[PREFIX_STRLEN];
zlog_warn("warning: interface %s address %s "
"with peer flag set, but no peer address!",
- ifp->name, buf);
+ ifp->name,
+ prefix2str (ifc->address, buf, sizeof buf));
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
}
}
ifindex = stream_getl (s);
/* Lookup index. */
- ifp = if_lookup_by_index (ifindex);
+ ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
if (ifp == NULL)
{
- zlog_warn ("zebra_nbr_interface_address_read(%s): "
- "Can't find interface by ifindex: %d ",
- (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD? "ADD" : "DELETE"),
- ifindex);
+ zlog_warn ("INTERFACE_NBR_%s: Cannot find IF %u in VRF %d",
+ (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) ? "ADD" : "DELETE",
+ ifindex, vrf_id);
return NULL;
}
return ifc;
}
+struct interface *
+zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id,
+ vrf_id_t *new_vrf_id)
+{
+ unsigned int ifindex;
+ struct interface *ifp;
+ vrf_id_t new_id = VRF_DEFAULT;
+
+ /* Get interface index. */
+ ifindex = stream_getl (s);
+
+ /* Lookup interface. */
+ ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
+ if (ifp == NULL)
+ {
+ zlog_warn ("INTERFACE_VRF_UPDATE: Cannot find IF %u in VRF %d",
+ ifindex, vrf_id);
+ return NULL;
+ }
+
+ /* Fetch new VRF Id. */
+ new_id = stream_getw (s);
+
+ *new_vrf_id = new_id;
+ return ifp;
+}
+
/* Zebra client message read function. */
static int
zclient_read (struct thread *thread)
if (zclient->router_id_update)
(*zclient->router_id_update) (command, zclient, length, vrf_id);
break;
+ case ZEBRA_VRF_ADD:
+ zclient_vrf_add (zclient, vrf_id);
+ break;
+ case ZEBRA_VRF_DELETE:
+ zclient_vrf_delete (zclient, vrf_id);
+ break;
case ZEBRA_INTERFACE_ADD:
if (zclient->interface_add)
(*zclient->interface_add) (command, zclient, length, vrf_id);
if (zclient->interface_down)
(*zclient->interface_down) (command, zclient, length, vrf_id);
break;
+ case ZEBRA_INTERFACE_VRF_UPDATE:
+ if (zclient->interface_vrf_update)
+ (*zclient->interface_vrf_update) (command, zclient, length, vrf_id);
+ break;
case ZEBRA_IPV4_ROUTE_ADD:
if (zclient->ipv4_route_add)
(*zclient->ipv4_route_add) (command, zclient, length, vrf_id);
}
}
+const char *zclient_serv_path_get()
+{
+ return zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH;
+}
+
void
zclient_serv_path_set (char *path)
{