extern struct zebra_privs_t zserv_privs;
\f
-/* For logging of zebra meesages. */
-static const char *zebra_command_str [] =
-{
- "NULL",
- "ZEBRA_INTERFACE_ADD",
- "ZEBRA_INTERFACE_DELETE",
- "ZEBRA_INTERFACE_ADDRESS_ADD",
- "ZEBRA_INTERFACE_ADDRESS_DELETE",
- "ZEBRA_INTERFACE_UP",
- "ZEBRA_INTERFACE_DOWN",
- "ZEBRA_IPV4_ROUTE_ADD",
- "ZEBRA_IPV4_ROUTE_DELETE",
- "ZEBRA_IPV6_ROUTE_ADD",
- "ZEBRA_IPV6_ROUTE_DELETE",
- "ZEBRA_REDISTRIBUTE_ADD",
- "ZEBRA_REDISTRIBUTE_DELETE",
- "ZEBRA_REDISTRIBUTE_DEFAULT_ADD",
- "ZEBRA_REDISTRIBUTE_DEFAULT_DELETE",
- "ZEBRA_IPV4_NEXTHOP_LOOKUP",
- "ZEBRA_IPV6_NEXTHOP_LOOKUP",
- "ZEBRA_IPV4_IMPORT_LOOKUP",
- "ZEBRA_IPV6_IMPORT_LOOKUP",
- "ZEBRA_ROUTER_ID_ADD",
- "ZEBRA_ROUTER_ID_DELETE",
- "ZEBRA_ROUTER_ID_UPDATE"
-};
-\f
-
static void zebra_client_close (struct zserv *client);
static int
client->t_suicide = thread_add_event(zebrad.master, zserv_delayed_close,
client, 0);
return -1;
- break;
case BUFFER_EMPTY:
THREAD_OFF(client->t_write);
break;
return 0;
}
+static void
+zserv_create_header (struct stream *s, uint16_t cmd)
+{
+ /* length placeholder, caller can update */
+ stream_putw (s, ZEBRA_HEADER_SIZE);
+ stream_putc (s, ZEBRA_HEADER_MARKER);
+ stream_putc (s, ZSERV_VERSION);
+ stream_putw (s, cmd);
+}
+
/* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
/*
* This function is called in the following situations:
s = client->obuf;
stream_reset (s);
- /* Place holder for size. */
- stream_putw (s, 0);
-
/* Message type. */
- stream_putc (s, ZEBRA_INTERFACE_ADD);
+ zserv_create_header (s, ZEBRA_INTERFACE_ADD);
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
stream_putc (s, ifp->status);
- stream_putl (s, ifp->flags);
+ stream_putq (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
stream_putl (s, ifp->mtu6);
stream_putl (s, ifp->bandwidth);
-#ifdef HAVE_SOCKADDR_DL
+#ifdef HAVE_STRUCT_SOCKADDR_DL
stream_put (s, &ifp->sdl, sizeof (ifp->sdl));
#else
stream_putl (s, ifp->hw_addr_len);
if (ifp->hw_addr_len)
stream_put (s, ifp->hw_addr, ifp->hw_addr_len);
-#endif /* HAVE_SOCKADDR_DL */
+#endif /* HAVE_STRUCT_SOCKADDR_DL */
/* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s));
}
/* Interface deletion from zebra daemon. */
-/*
- * This function is only called when support for
- * RTM_IFANNOUNCE or AF_NETLINK sockets (RTM_DELLINK message)
- * is available. It is not called on Solaris.
- */
-#if (defined(RTM_IFANNOUNCE) || defined(HAVE_NETLINK))
int
zsend_interface_delete (struct zserv *client, struct interface *ifp)
{
s = client->obuf;
stream_reset (s);
-
- /* Packet length placeholder. */
- stream_putw (s, 0);
-
+
+ zserv_create_header (s, ZEBRA_INTERFACE_DELETE);
+
/* Interface information. */
- stream_putc (s, ZEBRA_INTERFACE_DELETE);
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
stream_putc (s, ifp->status);
- stream_putl (s, ifp->flags);
+ stream_putq (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
stream_putl (s, ifp->mtu6);
return zebra_server_send_message (client);
}
-#endif /* (defined(RTM_IFANNOUNCE) || defined(HAVE_LINUX_RTNETLINK_H)) */
/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or
* ZEBRA_INTERFACE_ADDRESS_DELETE to the client.
* |
* zebra_interface_address_delete_update
* ^ ^ ^
- * | | if_delete_update (not called on
- * | | Solaris)
+ * | | if_delete_update
+ * | |
* ip_address_uninstall connected_delete_ipv4
* [ipv6_addresss_uninstall] [connected_delete_ipv6]
* ^ ^
s = client->obuf;
stream_reset (s);
-
- /* Place holder for size. */
- stream_putw (s, 0);
-
- stream_putc (s, cmd);
+
+ zserv_create_header (s, cmd);
stream_putl (s, ifp->ifindex);
/* Interface address flag. */
s = client->obuf;
stream_reset (s);
- /* Place holder for size. */
- stream_putw (s, 0);
-
- /* Zebra command. */
- stream_putc (s, cmd);
+ zserv_create_header (s, cmd);
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
stream_putc (s, ifp->status);
- stream_putl (s, ifp->flags);
+ stream_putq (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
stream_putl (s, ifp->mtu6);
int psize;
struct stream *s;
struct nexthop *nexthop;
- unsigned long nhnummark = 0;
+ unsigned long nhnummark = 0, messmark = 0;
int nhnum = 0;
- u_char zapi_flags = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_IFINDEX;
+ u_char zapi_flags = 0;
s = client->obuf;
stream_reset (s);
-
- /* Place holder for size. */
- stream_putw (s, 0);
-
- /* Put command, type and nexthop. */
- stream_putc (s, cmd);
+
+ zserv_create_header (s, cmd);
+
+ /* Put type and nexthop. */
stream_putc (s, rib->type);
stream_putc (s, rib->flags);
-
- /*
- * XXX no need to set ZAPI_MESSAGE_NEXTHOP if we are going to
- * send empty nexthop?
- */
- if (cmd == ZEBRA_IPV4_ROUTE_ADD || ZEBRA_IPV6_ROUTE_ADD)
- zapi_flags |= ZAPI_MESSAGE_METRIC;
-
- stream_putc (s, zapi_flags);
+
+ /* marker for message flags field */
+ messmark = stream_get_endp (s);
+ stream_putc (s, 0);
/* Prefix. */
psize = PSIZE (p->prefixlen);
* is hard-coded.
*/
/* Nexthop */
+
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
{
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
{
- nhnummark = stream_get_endp (s);
- stream_putc (s, 1); /* placeholder */
+ SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP);
+ SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX);
+
+ if (nhnummark == 0)
+ {
+ nhnummark = stream_get_endp (s);
+ stream_putc (s, 1); /* placeholder */
+ }
+
nhnum++;
switch(nexthop->type)
}
/* Metric */
- stream_putl (s, rib->metric);
-
+ if (cmd == ZEBRA_IPV4_ROUTE_ADD || ZEBRA_IPV6_ROUTE_ADD)
+ {
+ SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE);
+ stream_putc (s, rib->distance);
+ SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC);
+ stream_putl (s, rib->metric);
+ }
+
+ /* write real message flags value */
+ stream_putc_at (s, messmark, zapi_flags);
+
/* Write next-hop number */
if (nhnummark)
stream_putc_at (s, nhnummark, nhnum);
stream_reset (s);
/* Fill in result. */
- stream_putw (s, 0);
- stream_putc (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
+ zserv_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
stream_put (s, &addr, 16);
if (rib)
stream_reset (s);
/* Fill in result. */
- stream_putw (s, 0);
- stream_putc (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
+ zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
stream_put_in_addr (s, &addr);
if (rib)
stream_reset (s);
/* Fill in result. */
- stream_putw (s, 0);
- stream_putc (s, ZEBRA_IPV4_IMPORT_LOOKUP);
+ zserv_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
stream_put_in_addr (s, &p->prefix);
if (rib)
s = client->obuf;
stream_reset (s);
- /* Place holder for size. */
- stream_putw (s, 0);
-
/* Message type. */
- stream_putc (s, ZEBRA_ROUTER_ID_UPDATE);
+ zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE);
/* Prefix information. */
stream_putc (s, p->family);
s = client->ibuf;
/* Allocate new rib. */
- rib = XMALLOC (MTYPE_RIB, sizeof (struct rib));
- memset (rib, 0, sizeof (struct rib));
-
+ rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
+
/* Type, flags, message. */
rib->type = stream_getc (s);
rib->flags = stream_getc (s);
break;
case ZEBRA_NEXTHOP_IPV4:
nexthop.s_addr = stream_get_ipv4 (s);
- nexthop_ipv4_add (rib, &nexthop);
+ nexthop_ipv4_add (rib, &nexthop, NULL);
break;
case ZEBRA_NEXTHOP_IPV6:
stream_forward_getp (s, IPV6_MAX_BYTELEN);
if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
rib->metric = stream_getl (s);
+ /* Table */
+ rib->table=zebrad.rtm_table_default;
rib_add_ipv4_multipath (&p, rib);
return 0;
}
api.metric = 0;
if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
- rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0);
+ rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0, api.metric,
+ api.distance);
else
- rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0);
+ rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0, api.metric,
+ api.distance);
return 0;
}
int sock;
struct zserv *client;
size_t already;
- u_short length;
- u_char command;
+ uint16_t length, command;
+ uint8_t marker, version;
/* Get thread data. Reset reading thread because I'm running. */
sock = THREAD_FD (thread);
/* Reset to read from the beginning of the incoming packet. */
stream_set_getp(client->ibuf, 0);
+ /* Fetch header values */
length = stream_getw (client->ibuf);
- command = stream_getc (client->ibuf);
+ marker = stream_getc (client->ibuf);
+ version = stream_getc (client->ibuf);
+ command = stream_getw (client->ibuf);
+ if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
+ {
+ zlog_err("%s: socket %d version mismatch, marker %d, version %d",
+ __func__, sock, marker, version);
+ zebra_client_close (client);
+ return -1;
+ }
if (length < ZEBRA_HEADER_SIZE)
{
zlog_warn("%s: socket %d message length %u is less than header size %d",
if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
zlog_debug ("zebra message received [%s] %d",
- zebra_command_str[command], length);
+ zserv_command_string (command), length);
switch (command)
{
memset (&addr, 0, sizeof (struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons (ZEBRA_PORT);
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
addr.sin_len = sizeof (struct sockaddr_in);
-#endif /* HAVE_SIN_LEN */
+#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
sockopt_reuseaddr (accept_sock);
memset (&serv, 0, sizeof (struct sockaddr_un));
serv.sun_family = AF_UNIX;
strncpy (serv.sun_path, path, strlen (path));
-#ifdef HAVE_SUN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
len = serv.sun_len = SUN_LEN(&serv);
#else
len = sizeof (serv.sun_family) + strlen (serv.sun_path);
-#endif /* HAVE_SUN_LEN */
+#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
ret = bind (sock, (struct sockaddr *) &serv, len);
if (ret < 0)
\f
/* Initialisation of zebra and installation of commands. */
void
-zebra_init ()
+zebra_init (void)
{
/* Client list init. */
zebrad.client_list = list_new ();
install_element (CONFIG_NODE, &ipv6_forwarding_cmd);
install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
#endif /* HAVE_IPV6 */
+
+ /* Route-map */
+ zebra_route_map_init ();
}