Skip to content

Commit

Permalink
*: convert zclient callbacks to table
Browse files Browse the repository at this point in the history
This removes a giant `switch { }` block from lib/zclient.c and
harmonizes all zclient callback function types to be the same (some had
a subset of the args, some had a void return, now they all have
ZAPI_CALLBACK_ARGS and int return.)

Apart from getting rid of the giant switch, this is a minor security
benefit since the function pointers are now in a `const` array, so they
can't be overwritten by e.g. heap overflows for code execution anymore.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
  • Loading branch information
eqvinox committed Oct 20, 2021
1 parent bf4af4f commit a243d1d
Show file tree
Hide file tree
Showing 28 changed files with 370 additions and 579 deletions.
14 changes: 9 additions & 5 deletions babeld/babel_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,16 +234,20 @@ babel_zebra_connected (struct zclient *zclient)
zclient_send_reg_requests (zclient, VRF_DEFAULT);
}

static zclient_handler *const babel_handlers[] = {
[ZEBRA_INTERFACE_ADDRESS_ADD] = babel_interface_address_add,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = babel_interface_address_delete,
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = babel_zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = babel_zebra_read_route,
};

void babelz_zebra_init(void)
{
zclient = zclient_new(master, &zclient_options_default);
zclient = zclient_new(master, &zclient_options_default, babel_handlers,
array_size(babel_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs);

zclient->zebra_connected = babel_zebra_connected;
zclient->interface_address_add = babel_interface_address_add;
zclient->interface_address_delete = babel_interface_address_delete;
zclient->redistribute_route_add = babel_zebra_read_route;
zclient->redistribute_route_del = babel_zebra_read_route;

install_element(BABEL_NODE, &babel_redistribute_type_cmd);
install_element(ENABLE_NODE, &debug_babel_cmd);
Expand Down
31 changes: 17 additions & 14 deletions bfdd/ptm_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -844,29 +844,32 @@ static int bfd_ifp_create(struct interface *ifp)
return 0;
}

void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
{
if_zapi_callbacks(bfd_ifp_create, NULL, NULL, bfd_ifp_destroy);
zclient = zclient_new(master, &zclient_options_default);
assert(zclient != NULL);
zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv);

static zclient_handler *const bfd_handlers[] = {
/*
* We'll receive all messages through replay, however it will
* contain a special field with the real command inside so we
* avoid having to create too many handlers.
*/
zclient->bfd_dest_replay = bfdd_replay;

/* Send replay request on zebra connect. */
zclient->zebra_connected = bfdd_zebra_connected;
[ZEBRA_BFD_DEST_REPLAY] = bfdd_replay,

/* Learn about interface VRF. */
zclient->interface_vrf_update = bfdd_interface_vrf_update;
[ZEBRA_INTERFACE_VRF_UPDATE] = bfdd_interface_vrf_update,

/* Learn about new addresses being registered. */
zclient->interface_address_add = bfdd_interface_address_update;
zclient->interface_address_delete = bfdd_interface_address_update;
[ZEBRA_INTERFACE_ADDRESS_ADD] = bfdd_interface_address_update,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = bfdd_interface_address_update,
};

void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
{
if_zapi_callbacks(bfd_ifp_create, NULL, NULL, bfd_ifp_destroy);
zclient = zclient_new(master, &zclient_options_default, bfd_handlers,
array_size(bfd_handlers));
assert(zclient != NULL);
zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv);

/* Send replay request on zebra connect. */
zclient->zebra_connected = bfdd_zebra_connected;
}

void bfdd_zclient_register(vrf_id_t vrf_id)
Expand Down
98 changes: 52 additions & 46 deletions bgpd/bgp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,7 @@ static void bgp_update_interface_nbrs(struct bgp *bgp, struct interface *ifp,
}
}

static int bgp_read_fec_update(int command, struct zclient *zclient,
zebra_size_t length)
static int bgp_read_fec_update(ZAPI_CALLBACK_ARGS)
{
bgp_parse_fec_update();
return 0;
Expand Down Expand Up @@ -3005,7 +3004,7 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)
}
}

static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
static int bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
{
struct stream *s = NULL;
struct bgp *bgp_vrf = NULL;
Expand All @@ -3017,7 +3016,7 @@ static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)

bgp_vrf = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp_vrf)
return;
return 0;

if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Recv prefix %pFX %s on vrf %s", &p,
Expand All @@ -3041,9 +3040,10 @@ static void bgp_zebra_process_local_ip_prefix(ZAPI_CALLBACK_ARGS)
bgp_evpn_withdraw_type5_route(bgp_vrf, &p, AFI_IP6,
SAFI_UNICAST);
}
return 0;
}

static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
static int bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
{
struct stream *s = NULL;
uint8_t response_keep;
Expand All @@ -3062,12 +3062,12 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)
if (zclient->redist_default != proto) {
flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong proto %u",
proto);
return;
return 0;
}
if (zclient->instance != instance) {
flog_err(EC_BGP_LM_ERROR, "Got LM msg with wrong instance %u",
proto);
return;
return 0;
}

if (first > last ||
Expand All @@ -3076,7 +3076,7 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)

flog_err(EC_BGP_LM_ERROR, "%s: Invalid Label chunk: %u - %u",
__func__, first, last);
return;
return 0;
}
if (BGP_DEBUG(zebra, ZEBRA)) {
zlog_debug("Label Chunk assign: %u - %u (%u) ",
Expand All @@ -3085,8 +3085,10 @@ static void bgp_zebra_process_label_chunk(ZAPI_CALLBACK_ARGS)

bgp_lp_event_chunk(response_keep, first, last);

return 0;

stream_failure: /* for STREAM_GETX */
return;
return -1;
}

extern struct zebra_privs_t bgpd_privs;
Expand All @@ -3109,7 +3111,7 @@ static int bgp_ifp_create(struct interface *ifp)
return 0;
}

static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
static int bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
{
struct stream *s = NULL;
struct bgp *bgp = bgp_get_default();
Expand All @@ -3124,18 +3126,19 @@ static void bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
if (strcmp(bgp->srv6_locator_name, s6c.locator_name) != 0) {
zlog_err("%s: Locator name unmatch %s:%s", __func__,
bgp->srv6_locator_name, s6c.locator_name);
return;
return 0;
}

for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, c)) {
if (!prefix_cmp(c, &s6c.prefix))
return;
return 0;
}

chunk = prefix_ipv6_new();
*chunk = s6c.prefix;
listnode_add(bgp->srv6_locator_chunks, chunk);
vpn_leak_postchange_all();
return 0;
}

static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
Expand Down Expand Up @@ -3220,6 +3223,41 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
return 0;
}

static zclient_handler *const bgp_handlers[] = {
[ZEBRA_ROUTER_ID_UPDATE] = bgp_router_id_update,
[ZEBRA_INTERFACE_ADDRESS_ADD] = bgp_interface_address_add,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = bgp_interface_address_delete,
[ZEBRA_INTERFACE_NBR_ADDRESS_ADD] = bgp_interface_nbr_address_add,
[ZEBRA_INTERFACE_NBR_ADDRESS_DELETE] = bgp_interface_nbr_address_delete,
[ZEBRA_INTERFACE_VRF_UPDATE] = bgp_interface_vrf_update,
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = zebra_read_route,
[ZEBRA_NEXTHOP_UPDATE] = bgp_read_nexthop_update,
[ZEBRA_FEC_UPDATE] = bgp_read_fec_update,
[ZEBRA_LOCAL_ES_ADD] = bgp_zebra_process_local_es_add,
[ZEBRA_LOCAL_ES_DEL] = bgp_zebra_process_local_es_del,
[ZEBRA_VNI_ADD] = bgp_zebra_process_local_vni,
[ZEBRA_LOCAL_ES_EVI_ADD] = bgp_zebra_process_local_es_evi,
[ZEBRA_LOCAL_ES_EVI_DEL] = bgp_zebra_process_local_es_evi,
[ZEBRA_VNI_DEL] = bgp_zebra_process_local_vni,
[ZEBRA_MACIP_ADD] = bgp_zebra_process_local_macip,
[ZEBRA_MACIP_DEL] = bgp_zebra_process_local_macip,
[ZEBRA_L3VNI_ADD] = bgp_zebra_process_local_l3vni,
[ZEBRA_L3VNI_DEL] = bgp_zebra_process_local_l3vni,
[ZEBRA_IP_PREFIX_ROUTE_ADD] = bgp_zebra_process_local_ip_prefix,
[ZEBRA_IP_PREFIX_ROUTE_DEL] = bgp_zebra_process_local_ip_prefix,
[ZEBRA_GET_LABEL_CHUNK] = bgp_zebra_process_label_chunk,
[ZEBRA_RULE_NOTIFY_OWNER] = rule_notify_owner,
[ZEBRA_IPSET_NOTIFY_OWNER] = ipset_notify_owner,
[ZEBRA_IPSET_ENTRY_NOTIFY_OWNER] = ipset_entry_notify_owner,
[ZEBRA_IPTABLE_NOTIFY_OWNER] = iptable_notify_owner,
[ZEBRA_ROUTE_NOTIFY_OWNER] = bgp_zebra_route_notify_owner,
[ZEBRA_SRV6_LOCATOR_ADD] = bgp_zebra_process_srv6_locator_add,
[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
bgp_zebra_process_srv6_locator_chunk,
};

void bgp_zebra_init(struct thread_master *master, unsigned short instance)
{
zclient_num_connects = 0;
Expand All @@ -3228,43 +3266,11 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance)
bgp_ifp_down, bgp_ifp_destroy);

/* Set default values. */
zclient = zclient_new(master, &zclient_options_default);
zclient = zclient_new(master, &zclient_options_default, bgp_handlers,
array_size(bgp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
zclient->router_id_update = bgp_router_id_update;
zclient->interface_address_add = bgp_interface_address_add;
zclient->interface_address_delete = bgp_interface_address_delete;
zclient->interface_nbr_address_add = bgp_interface_nbr_address_add;
zclient->interface_nbr_address_delete =
bgp_interface_nbr_address_delete;
zclient->interface_vrf_update = bgp_interface_vrf_update;
zclient->redistribute_route_add = zebra_read_route;
zclient->redistribute_route_del = zebra_read_route;
zclient->nexthop_update = bgp_read_nexthop_update;
zclient->fec_update = bgp_read_fec_update;
zclient->local_es_add = bgp_zebra_process_local_es_add;
zclient->local_es_del = bgp_zebra_process_local_es_del;
zclient->local_vni_add = bgp_zebra_process_local_vni;
zclient->local_es_evi_add = bgp_zebra_process_local_es_evi;
zclient->local_es_evi_del = bgp_zebra_process_local_es_evi;
zclient->local_vni_del = bgp_zebra_process_local_vni;
zclient->local_macip_add = bgp_zebra_process_local_macip;
zclient->local_macip_del = bgp_zebra_process_local_macip;
zclient->local_l3vni_add = bgp_zebra_process_local_l3vni;
zclient->local_l3vni_del = bgp_zebra_process_local_l3vni;
zclient->local_ip_prefix_add = bgp_zebra_process_local_ip_prefix;
zclient->local_ip_prefix_del = bgp_zebra_process_local_ip_prefix;
zclient->label_chunk = bgp_zebra_process_label_chunk;
zclient->rule_notify_owner = rule_notify_owner;
zclient->ipset_notify_owner = ipset_notify_owner;
zclient->ipset_entry_notify_owner = ipset_entry_notify_owner;
zclient->iptable_notify_owner = iptable_notify_owner;
zclient->route_notify_owner = bgp_zebra_route_notify_owner;
zclient->instance = instance;
zclient->srv6_locator_add = bgp_zebra_process_srv6_locator_add;
zclient->srv6_locator_delete = bgp_zebra_process_srv6_locator_delete;
zclient->process_srv6_locator_chunk =
bgp_zebra_process_srv6_locator_chunk;
}

void bgp_zebra_destroy(void)
Expand Down
11 changes: 7 additions & 4 deletions bgpd/rfapi/vnc_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -895,18 +895,21 @@ int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)

extern struct zebra_privs_t bgpd_privs;

static zclient_handler *const vnc_handlers[] = {
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = vnc_zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = vnc_zebra_read_route,
};

/*
* Modeled after bgp_zebra.c'bgp_zebra_init()
* Charriere asks, "Is it possible to carry two?"
*/
void vnc_zebra_init(struct thread_master *master)
{
/* Set default values. */
zclient_vnc = zclient_new(master, &zclient_options_default);
zclient_vnc = zclient_new(master, &zclient_options_default,
vnc_handlers, array_size(vnc_handlers));
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);

zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
zclient_vnc->redistribute_route_del = vnc_zebra_read_route;
}

void vnc_zebra_destroy(void)
Expand Down
18 changes: 11 additions & 7 deletions eigrpd/eigrp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,24 @@ static void eigrp_zebra_connected(struct zclient *zclient)
zclient_send_reg_requests(zclient, VRF_DEFAULT);
}

static zclient_handler *const eigrp_handlers[] = {
[ZEBRA_ROUTER_ID_UPDATE] = eigrp_router_id_update_zebra,
[ZEBRA_INTERFACE_ADDRESS_ADD] = eigrp_interface_address_add,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = eigrp_interface_address_delete,
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = eigrp_zebra_read_route,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = eigrp_zebra_read_route,
[ZEBRA_ROUTE_NOTIFY_OWNER] = eigrp_zebra_route_notify_owner,
};

void eigrp_zebra_init(void)
{
struct zclient_options opt = {.receive_notify = false};

zclient = zclient_new(master, &opt);
zclient = zclient_new(master, &opt, eigrp_handlers,
array_size(eigrp_handlers));

zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
zclient->zebra_connected = eigrp_zebra_connected;
zclient->router_id_update = eigrp_router_id_update_zebra;
zclient->interface_address_add = eigrp_interface_address_add;
zclient->interface_address_delete = eigrp_interface_address_delete;
zclient->redistribute_route_add = eigrp_zebra_read_route;
zclient->redistribute_route_del = eigrp_zebra_read_route;
zclient->route_notify_owner = eigrp_zebra_route_notify_owner;
}


Expand Down
28 changes: 16 additions & 12 deletions isisd/isis_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,23 +800,31 @@ static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
return ret;
}

static zclient_handler *const isis_handlers[] = {
[ZEBRA_ROUTER_ID_UPDATE] = isis_router_id_update_zebra,
[ZEBRA_INTERFACE_ADDRESS_ADD] = isis_zebra_if_address_add,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = isis_zebra_if_address_del,
[ZEBRA_INTERFACE_LINK_PARAMS] = isis_zebra_link_params,
[ZEBRA_REDISTRIBUTE_ROUTE_ADD] = isis_zebra_read,
[ZEBRA_REDISTRIBUTE_ROUTE_DEL] = isis_zebra_read,

[ZEBRA_OPAQUE_MESSAGE] = isis_opaque_msg_handler,

[ZEBRA_CLIENT_CLOSE_NOTIFY] = isis_zebra_client_close_notify,
};

void isis_zebra_init(struct thread_master *master, int instance)
{
/* Initialize asynchronous zclient. */
zclient = zclient_new(master, &zclient_options_default);
zclient = zclient_new(master, &zclient_options_default, isis_handlers,
array_size(isis_handlers));
zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
zclient->zebra_connected = isis_zebra_connected;
zclient->router_id_update = isis_router_id_update_zebra;
zclient->interface_address_add = isis_zebra_if_address_add;
zclient->interface_address_delete = isis_zebra_if_address_del;
zclient->interface_link_params = isis_zebra_link_params;
zclient->redistribute_route_add = isis_zebra_read;
zclient->redistribute_route_del = isis_zebra_read;

/* Initialize special zclient for synchronous message exchanges. */
struct zclient_options options = zclient_options_default;
options.synchronous = true;
zclient_sync = zclient_new(master, &options);
zclient_sync = zclient_new(master, &options, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
zclient_sync->instance = instance;
Expand All @@ -826,10 +834,6 @@ void isis_zebra_init(struct thread_master *master, int instance)
*/
zclient_sync->session_id = 1;
zclient_sync->privs = &isisd_privs;

zclient->opaque_msg_handler = isis_opaque_msg_handler;

zclient->zebra_client_close_notify = isis_zebra_client_close_notify;
}

void isis_zebra_stop(void)
Expand Down
2 changes: 1 addition & 1 deletion ldpd/lde.c
Original file line number Diff line number Diff line change
Expand Up @@ -2192,7 +2192,7 @@ static void zclient_sync_init(void)
options.synchronous = true;

/* Initialize special zclient for synchronous message exchanges. */
zclient_sync = zclient_new(master, &options);
zclient_sync = zclient_new(master, &options, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
zclient_sync->session_id = 1; /* Distinguish from main session */
Expand Down
Loading

0 comments on commit a243d1d

Please sign in to comment.