summaryrefslogtreecommitdiff
path: root/zebra/zserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zserv.c')
-rw-r--r--zebra/zserv.c334
1 files changed, 174 insertions, 160 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c
index cbc9f2bed9..6295de0c2e 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -40,6 +40,7 @@
#include "nexthop.h"
#include "vrf.h"
#include "libfrr.h"
+#include "sockopt.h"
#include "zebra/zserv.h"
#include "zebra/zebra_ns.h"
@@ -693,7 +694,7 @@ static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop)
}
/* Nexthop register */
-static int zserv_rnh_register(struct zserv *client, int sock, u_short length,
+static int zserv_rnh_register(struct zserv *client, u_short length,
rnh_type_t type, struct zebra_vrf *zvrf)
{
struct rnh *rnh;
@@ -754,7 +755,7 @@ static int zserv_rnh_register(struct zserv *client, int sock, u_short length,
}
/* Nexthop register */
-static int zserv_rnh_unregister(struct zserv *client, int sock, u_short length,
+static int zserv_rnh_unregister(struct zserv *client, u_short length,
rnh_type_t type, struct zebra_vrf *zvrf)
{
struct rnh *rnh;
@@ -798,7 +799,7 @@ static int zserv_rnh_unregister(struct zserv *client, int sock, u_short length,
#define ZEBRA_MIN_FEC_LENGTH 5
/* FEC register */
-static int zserv_fec_register(struct zserv *client, int sock, u_short length)
+static int zserv_fec_register(struct zserv *client, u_short length)
{
struct stream *s;
struct zebra_vrf *zvrf;
@@ -849,7 +850,7 @@ static int zserv_fec_register(struct zserv *client, int sock, u_short length)
}
/* FEC unregister */
-static int zserv_fec_unregister(struct zserv *client, int sock, u_short length)
+static int zserv_fec_unregister(struct zserv *client, u_short length)
{
struct stream *s;
struct zebra_vrf *zvrf;
@@ -1763,7 +1764,7 @@ static int zread_vrf_unregister(struct zserv *client, u_short length,
}
static void zread_mpls_labels(int command, struct zserv *client, u_short length,
- vrf_id_t vrf_id)
+ struct zebra_vrf *zvrf)
{
struct stream *s;
enum lsp_types_t type;
@@ -1773,11 +1774,6 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length,
ifindex_t ifindex;
mpls_label_t in_label, out_label;
u_int8_t distance;
- struct zebra_vrf *zvrf;
-
- zvrf = vrf_info_lookup(vrf_id);
- if (!zvrf)
- return;
/* Get input stream. */
s = client->ibuf;
@@ -1959,7 +1955,7 @@ static void zread_release_label_chunk(struct zserv *client)
release_label_chunk(client->proto, client->instance, start, end);
}
static void zread_label_manager_request(int cmd, struct zserv *client,
- vrf_id_t vrf_id)
+ struct zebra_vrf *zvrf)
{
/* to avoid sending other messages like ZERBA_INTERFACE_UP */
if (cmd == ZEBRA_LABEL_MANAGER_CONNECT)
@@ -1967,11 +1963,13 @@ static void zread_label_manager_request(int cmd, struct zserv *client,
/* external label manager */
if (lm_is_external)
- zread_relay_label_manager_request(cmd, client, vrf_id);
+ zread_relay_label_manager_request(cmd, client,
+ zvrf_id(zvrf));
/* this is a label manager */
else {
if (cmd == ZEBRA_LABEL_MANAGER_CONNECT)
- zread_label_manager_connect(client, vrf_id);
+ zread_label_manager_connect(client,
+ zvrf_id(zvrf));
else {
/* Sanity: don't allow 'unidentified' requests */
if (!client->proto) {
@@ -1980,7 +1978,8 @@ static void zread_label_manager_request(int cmd, struct zserv *client,
return;
}
if (cmd == ZEBRA_GET_LABEL_CHUNK)
- zread_get_label_chunk(client, vrf_id);
+ zread_get_label_chunk(client,
+ zvrf_id(zvrf));
else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK)
zread_release_label_chunk(client);
}
@@ -1988,10 +1987,9 @@ static void zread_label_manager_request(int cmd, struct zserv *client,
}
static int zread_pseudowire(int command, struct zserv *client, u_short length,
- vrf_id_t vrf_id)
+ struct zebra_vrf *zvrf)
{
struct stream *s;
- struct zebra_vrf *zvrf;
char ifname[IF_NAMESIZE];
ifindex_t ifindex;
int type;
@@ -2004,10 +2002,6 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length,
uint8_t protocol;
struct zebra_pw *pw;
- zvrf = vrf_info_lookup(vrf_id);
- if (!zvrf)
- return -1;
-
/* Get input stream. */
s = client->ibuf;
@@ -2210,7 +2204,7 @@ static void zebra_client_create(int sock)
zebra_vrf_update_all(client);
}
-static int zread_interface_set_master(struct zserv *client, int sock,
+static int zread_interface_set_master(struct zserv *client,
u_short length)
{
struct interface *master;
@@ -2235,122 +2229,11 @@ static int zread_interface_set_master(struct zserv *client, int sock,
return 1;
}
-/* Handler of zebra service request. */
-static int zebra_client_read(struct thread *thread)
+static inline void zserv_handle_commands(struct zserv *client,
+ uint16_t command,
+ uint16_t length,
+ struct zebra_vrf *zvrf)
{
- int sock;
- struct zserv *client;
- size_t already;
- uint16_t length, command;
- uint8_t marker, version;
- vrf_id_t vrf_id;
- struct zebra_vrf *zvrf;
-
- /* Get thread data. Reset reading thread because I'm running. */
- sock = THREAD_FD(thread);
- client = THREAD_ARG(thread);
- client->t_read = NULL;
-
- if (client->t_suicide) {
- zebra_client_close(client);
- return -1;
- }
-
- /* Read length and command (if we don't have it already). */
- if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) {
- ssize_t nbyte;
- if (((nbyte = stream_read_try(client->ibuf, sock,
- ZEBRA_HEADER_SIZE - already))
- == 0)
- || (nbyte == -1)) {
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("connection closed socket [%d]",
- sock);
- zebra_client_close(client);
- return -1;
- }
- if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
- /* Try again later. */
- zebra_event(ZEBRA_READ, sock, client);
- return 0;
- }
- already = ZEBRA_HEADER_SIZE;
- }
-
- /* Reset to read from the beginning of the incoming packet. */
- stream_set_getp(client->ibuf, 0);
-
- /* Fetch header values */
- length = stream_getw(client->ibuf);
- marker = stream_getc(client->ibuf);
- version = stream_getc(client->ibuf);
- vrf_id = stream_getw(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",
- __func__, sock, length, ZEBRA_HEADER_SIZE);
- zebra_client_close(client);
- return -1;
- }
- if (length > STREAM_SIZE(client->ibuf)) {
- zlog_warn(
- "%s: socket %d message length %u exceeds buffer size %lu",
- __func__, sock, length,
- (u_long)STREAM_SIZE(client->ibuf));
- zebra_client_close(client);
- return -1;
- }
-
- /* Read rest of data. */
- if (already < length) {
- ssize_t nbyte;
- if (((nbyte = stream_read_try(client->ibuf, sock,
- length - already))
- == 0)
- || (nbyte == -1)) {
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "connection closed [%d] when reading zebra data",
- sock);
- zebra_client_close(client);
- return -1;
- }
- if (nbyte != (ssize_t)(length - already)) {
- /* Try again later. */
- zebra_event(ZEBRA_READ, sock, client);
- return 0;
- }
- }
-
- length -= ZEBRA_HEADER_SIZE;
-
- /* Debug packet information. */
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("zebra message comes from socket [%d]", sock);
-
- if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
- zlog_debug("zebra message received [%s] %d in VRF %u",
- zserv_command_string(command), length, vrf_id);
-
- client->last_read_time = monotime(NULL);
- client->last_read_cmd = command;
-
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
- if (!zvrf) {
- if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
- zlog_debug("zebra received unknown VRF[%u]", vrf_id);
- goto zclient_read_out;
- }
-
switch (command) {
case ZEBRA_ROUTER_ID_ADD:
zread_router_id_add(client, length, zvrf);
@@ -2405,101 +2288,227 @@ static int zebra_client_read(struct thread *thread)
zread_hello(client);
break;
case ZEBRA_NEXTHOP_REGISTER:
- zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE,
+ zserv_rnh_register(client, length, RNH_NEXTHOP_TYPE,
zvrf);
break;
case ZEBRA_NEXTHOP_UNREGISTER:
- zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE,
+ zserv_rnh_unregister(client, length, RNH_NEXTHOP_TYPE,
zvrf);
break;
case ZEBRA_IMPORT_ROUTE_REGISTER:
- zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE,
+ zserv_rnh_register(client, length, RNH_IMPORT_CHECK_TYPE,
zvrf);
break;
case ZEBRA_IMPORT_ROUTE_UNREGISTER:
- zserv_rnh_unregister(client, sock, length,
+ zserv_rnh_unregister(client, length,
RNH_IMPORT_CHECK_TYPE, zvrf);
break;
case ZEBRA_BFD_DEST_UPDATE:
case ZEBRA_BFD_DEST_REGISTER:
- zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf);
+ zebra_ptm_bfd_dst_register(client, length, command, zvrf);
break;
case ZEBRA_BFD_DEST_DEREGISTER:
- zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf);
+ zebra_ptm_bfd_dst_deregister(client, length, zvrf);
break;
case ZEBRA_VRF_UNREGISTER:
zread_vrf_unregister(client, length, zvrf);
break;
case ZEBRA_BFD_CLIENT_REGISTER:
- zebra_ptm_bfd_client_register(client, sock, length);
+ zebra_ptm_bfd_client_register(client, length);
break;
case ZEBRA_INTERFACE_ENABLE_RADV:
#if defined(HAVE_RTADV)
- zebra_interface_radv_set(client, sock, length, zvrf, 1);
+ zebra_interface_radv_set(client, length, zvrf, 1);
#endif
break;
case ZEBRA_INTERFACE_DISABLE_RADV:
#if defined(HAVE_RTADV)
- zebra_interface_radv_set(client, sock, length, zvrf, 0);
+ zebra_interface_radv_set(client, length, zvrf, 0);
#endif
break;
case ZEBRA_MPLS_LABELS_ADD:
case ZEBRA_MPLS_LABELS_DELETE:
- zread_mpls_labels(command, client, length, vrf_id);
+ zread_mpls_labels(command, client, length, zvrf);
break;
case ZEBRA_IPMR_ROUTE_STATS:
- zebra_ipmr_route_stats(client, sock, length, zvrf);
+ zebra_ipmr_route_stats(client, length, zvrf);
break;
case ZEBRA_LABEL_MANAGER_CONNECT:
case ZEBRA_GET_LABEL_CHUNK:
case ZEBRA_RELEASE_LABEL_CHUNK:
- zread_label_manager_request(command, client, vrf_id);
+ zread_label_manager_request(command, client, zvrf);
break;
case ZEBRA_FEC_REGISTER:
- zserv_fec_register(client, sock, length);
+ zserv_fec_register(client, length);
break;
case ZEBRA_FEC_UNREGISTER:
- zserv_fec_unregister(client, sock, length);
+ zserv_fec_unregister(client, length);
break;
case ZEBRA_ADVERTISE_DEFAULT_GW:
- zebra_vxlan_advertise_gw_macip(client, sock, length, zvrf);
+ zebra_vxlan_advertise_gw_macip(client, length, zvrf);
break;
case ZEBRA_ADVERTISE_ALL_VNI:
- zebra_vxlan_advertise_all_vni(client, sock, length, zvrf);
+ zebra_vxlan_advertise_all_vni(client, length, zvrf);
break;
case ZEBRA_REMOTE_VTEP_ADD:
- zebra_vxlan_remote_vtep_add(client, sock, length, zvrf);
+ zebra_vxlan_remote_vtep_add(client, length, zvrf);
break;
case ZEBRA_REMOTE_VTEP_DEL:
- zebra_vxlan_remote_vtep_del(client, sock, length, zvrf);
+ zebra_vxlan_remote_vtep_del(client, length, zvrf);
break;
case ZEBRA_REMOTE_MACIP_ADD:
- zebra_vxlan_remote_macip_add(client, sock, length, zvrf);
+ zebra_vxlan_remote_macip_add(client, length, zvrf);
break;
case ZEBRA_REMOTE_MACIP_DEL:
- zebra_vxlan_remote_macip_del(client, sock, length, zvrf);
+ zebra_vxlan_remote_macip_del(client, length, zvrf);
break;
case ZEBRA_INTERFACE_SET_MASTER:
- zread_interface_set_master(client, sock, length);
+ zread_interface_set_master(client, length);
break;
case ZEBRA_PW_ADD:
case ZEBRA_PW_DELETE:
case ZEBRA_PW_SET:
case ZEBRA_PW_UNSET:
- zread_pseudowire(command, client, length, vrf_id);
+ zread_pseudowire(command, client, length, zvrf);
break;
default:
zlog_info("Zebra received unknown command %d", command);
break;
}
+}
+
+/* Handler of zebra service request. */
+static int zebra_client_read(struct thread *thread)
+{
+ int sock;
+ struct zserv *client;
+ size_t already;
+ uint16_t length, command;
+ uint8_t marker, version;
+ vrf_id_t vrf_id;
+ struct zebra_vrf *zvrf;
+ int packets = 10;
+
+ /* Get thread data. Reset reading thread because I'm running. */
+ sock = THREAD_FD(thread);
+ client = THREAD_ARG(thread);
+ client->t_read = NULL;
if (client->t_suicide) {
- /* No need to wait for thread callback, just kill immediately.
- */
zebra_client_close(client);
return -1;
}
+ while (packets) {
+ /* Read length and command (if we don't have it already). */
+ if ((already = stream_get_endp(client->ibuf))
+ < ZEBRA_HEADER_SIZE) {
+ ssize_t nbyte;
+ if (((nbyte =
+ stream_read_try(client->ibuf, sock,
+ ZEBRA_HEADER_SIZE - already))
+ == 0)
+ || (nbyte == -1)) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("connection closed socket [%d]",
+ sock);
+ zebra_client_close(client);
+ return -1;
+ }
+ if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
+ /* Try again later. */
+ zebra_event(ZEBRA_READ, sock, client);
+ return 0;
+ }
+ already = ZEBRA_HEADER_SIZE;
+ }
+
+ /* Reset to read from the beginning of the incoming packet. */
+ stream_set_getp(client->ibuf, 0);
+
+ /* Fetch header values */
+ length = stream_getw(client->ibuf);
+ marker = stream_getc(client->ibuf);
+ version = stream_getc(client->ibuf);
+ vrf_id = stream_getw(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",
+ __func__, sock, length, ZEBRA_HEADER_SIZE);
+ zebra_client_close(client);
+ return -1;
+ }
+ if (length > STREAM_SIZE(client->ibuf)) {
+ zlog_warn(
+ "%s: socket %d message length %u exceeds buffer size %lu",
+ __func__, sock, length,
+ (u_long)STREAM_SIZE(client->ibuf));
+ zebra_client_close(client);
+ return -1;
+ }
+
+ /* Read rest of data. */
+ if (already < length) {
+ ssize_t nbyte;
+ if (((nbyte = stream_read_try(client->ibuf, sock,
+ length - already))
+ == 0)
+ || (nbyte == -1)) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug(
+ "connection closed [%d] when reading zebra data",
+ sock);
+ zebra_client_close(client);
+ return -1;
+ }
+ if (nbyte != (ssize_t)(length - already)) {
+ /* Try again later. */
+ zebra_event(ZEBRA_READ, sock, client);
+ return 0;
+ }
+ }
+
+ length -= ZEBRA_HEADER_SIZE;
+
+ /* Debug packet information. */
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("zebra message comes from socket [%d]", sock);
+
+ if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("zebra message received [%s] %d in VRF %u",
+ zserv_command_string(command), length, vrf_id);
+
+ client->last_read_time = monotime(NULL);
+ client->last_read_cmd = command;
+
+ zvrf = zebra_vrf_lookup_by_id(vrf_id);
+ if (!zvrf) {
+ if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("zebra received unknown VRF[%u]", vrf_id);
+ goto zclient_read_out;
+ }
+
+ zserv_handle_commands(client, command, length, zvrf);
+
+ if (client->t_suicide) {
+ /* No need to wait for thread callback, just kill immediately.
+ */
+ zebra_client_close(client);
+ return -1;
+ }
+ packets -= 1;
+ stream_reset(client->ibuf);
+ }
+
zclient_read_out:
stream_reset(client->ibuf);
zebra_event(ZEBRA_READ, sock, client);
@@ -2573,6 +2582,11 @@ void zebra_zserv_socket_init(char *path)
unlink(suna->sun_path);
}
+ zserv_privs.change(ZPRIVS_RAISE);
+ setsockopt_so_recvbuf(sock, 1048576);
+ setsockopt_so_sendbuf(sock, 1048576);
+ zserv_privs.change(ZPRIVS_LOWER);
+
if (sa.ss_family != AF_UNIX && zserv_privs.change(ZPRIVS_RAISE))
zlog_err("Can't raise privileges");