From 756d516198a0ec659160ad8ab3d0d19bb416e461 Mon Sep 17 00:00:00 2001 From: Ronan Dalton Date: Mon, 16 Sep 2024 16:59:12 +1200 Subject: [PATCH 1/4] lib/route: add missing entry in libnl-route-3.sym file A corresponding entry for rtnl_link_bridge_set_vlan_default_pvid is missing from the libnl-route-3.sym file, so add it. --- libnl-route-3.sym | 1 + 1 file changed, 1 insertion(+) diff --git a/libnl-route-3.sym b/libnl-route-3.sym index 524e6919..87000f8f 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1340,6 +1340,7 @@ global: rtnl_link_bond_get_miimon; rtnl_link_bond_get_min_links; rtnl_link_bond_get_mode; + rtnl_link_bridge_set_vlan_default_pvid; rtnl_link_get_perm_addr; rtnl_neigh_extflags2str; rtnl_neigh_get_ext_flags; From a43a41cd2b1128a1b0b428b98cc251bff2c24b2f Mon Sep 17 00:00:00 2001 From: Ronan Dalton Date: Wed, 11 Sep 2024 16:30:22 +1200 Subject: [PATCH 2/4] lib/route: add missing bridge info getter functions There are bridge info setter functions for nf_call_iptables, nf_call_ip6tables and nf_call_arptables, but no corresponding getter functions, so add them. --- include/netlink/route/link/bridge_info.h | 9 +++ lib/route/link/bridge_info.c | 95 ++++++++++++++++++++++++ libnl-route-3.sym | 5 +- 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/include/netlink/route/link/bridge_info.h b/include/netlink/route/link/bridge_info.h index bb7bf0b6..ff93c779 100644 --- a/include/netlink/route/link/bridge_info.h +++ b/include/netlink/route/link/bridge_info.h @@ -37,12 +37,21 @@ extern void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link, uint8_t vlan_stats_enabled); extern int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, uint8_t *vlan_stats_enabled); + extern void rtnl_link_bridge_set_nf_call_iptables(struct rtnl_link *link, uint8_t call_enabled); +extern int rtnl_link_bridge_get_nf_call_iptables(struct rtnl_link *link, + uint8_t *call_enabled); + extern void rtnl_link_bridge_set_nf_call_ip6tables(struct rtnl_link *link, uint8_t call_enabled); +extern int rtnl_link_bridge_get_nf_call_ip6tables(struct rtnl_link *link, + uint8_t *call_enabled); + extern void rtnl_link_bridge_set_nf_call_arptables(struct rtnl_link *link, uint8_t call_enabled); +extern int rtnl_link_bridge_get_nf_call_arptables(struct rtnl_link *link, + uint8_t *call_enabled); #ifdef __cplusplus } diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c index 5d69b5ca..7250b437 100644 --- a/lib/route/link/bridge_info.c +++ b/lib/route/link/bridge_info.c @@ -211,6 +211,8 @@ static struct rtnl_link_info_ops bridge_info_ops = { * @arg link Link object of type bridge * @arg ageing_time Interval to set. * + * @see rtnl_link_bridge_get_ageing_time() + * * @return void */ void rtnl_link_bridge_set_ageing_time(struct rtnl_link *link, @@ -458,6 +460,8 @@ int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, * @arg link Link object of type bridge * @arg call_enabled call enabled boolean flag to set. * + * @see rtnl_link_bridge_get_nf_call_iptables() + * * @return void */ void rtnl_link_bridge_set_nf_call_iptables(struct rtnl_link *link, @@ -472,11 +476,42 @@ void rtnl_link_bridge_set_nf_call_iptables(struct rtnl_link *link, bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IPTABLES; } +/** + * Get call enabled flag for passing IPv4 traffic to iptables + * @arg link Link object of type bridge + * @arg call_enabled Output argument. + * + * @see rtnl_link_bridge_set_nf_call_iptables() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_nf_call_iptables(struct rtnl_link *link, + uint8_t *call_enabled) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IPTABLES)) + return -NLE_NOATTR; + + if (!call_enabled) + return -NLE_INVAL; + + *call_enabled = bi->b_nf_call_iptables; + + return 0; +} + /** * Set call enabled flag for passing IPv6 traffic to ip6tables * @arg link Link object of type bridge * @arg call_enabled call enabled boolean flag to set. * + * @see rtnl_link_bridge_get_nf_call_ip6tables() + * * @return void */ void rtnl_link_bridge_set_nf_call_ip6tables(struct rtnl_link *link, @@ -491,11 +526,42 @@ void rtnl_link_bridge_set_nf_call_ip6tables(struct rtnl_link *link, bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IP6TABLES; } +/** + * Get call enabled flag for passing IPv6 traffic to iptables + * @arg link Link object of type bridge + * @arg call_enabled Output argument. + * + * @see rtnl_link_bridge_set_nf_call_ip6tables() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_nf_call_ip6tables(struct rtnl_link *link, + uint8_t *call_enabled) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IP6TABLES)) + return -NLE_NOATTR; + + if (!call_enabled) + return -NLE_INVAL; + + *call_enabled = bi->b_nf_call_ip6tables; + + return 0; +} + /** * Set call enabled flag for passing ARP traffic to arptables * @arg link Link object of type bridge * @arg call_enabled call enabled boolean flag to set. * + * @see rtnl_link_bridge_get_nf_call_arptables() + * * @return void */ void rtnl_link_bridge_set_nf_call_arptables(struct rtnl_link *link, @@ -510,6 +576,35 @@ void rtnl_link_bridge_set_nf_call_arptables(struct rtnl_link *link, bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES; } +/** + * Get call enabled flag for passing ARP traffic to arptables + * @arg link Link object of type bridge + * @arg call_enabled Output argument. + * + * @see rtnl_link_bridge_set_nf_call_arptables() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_nf_call_arptables(struct rtnl_link *link, + uint8_t *call_enabled) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_ARPTABLES)) + return -NLE_NOATTR; + + if (!call_enabled) + return -NLE_INVAL; + + *call_enabled = bi->b_nf_call_arptables; + + return 0; +} + static void _nl_init bridge_info_init(void) { rtnl_link_register_info(&bridge_info_ops); diff --git a/libnl-route-3.sym b/libnl-route-3.sym index 87000f8f..f42a2d2e 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1323,8 +1323,8 @@ global: rtnl_link_bridge_set_ageing_time; rtnl_link_bridge_set_master; rtnl_link_bridge_set_nf_call_arptables; - rtnl_link_bridge_set_nf_call_iptables; rtnl_link_bridge_set_nf_call_ip6tables; + rtnl_link_bridge_set_nf_call_iptables; rtnl_link_bridge_set_port_vlan_map_range; rtnl_link_bridge_set_port_vlan_pvid; rtnl_link_bridge_unset_port_vlan_map_range; @@ -1340,6 +1340,9 @@ global: rtnl_link_bond_get_miimon; rtnl_link_bond_get_min_links; rtnl_link_bond_get_mode; + rtnl_link_bridge_get_nf_call_arptables; + rtnl_link_bridge_get_nf_call_ip6tables; + rtnl_link_bridge_get_nf_call_iptables; rtnl_link_bridge_set_vlan_default_pvid; rtnl_link_get_perm_addr; rtnl_neigh_extflags2str; From 3b284a118daf7989cfc53eee6c20a960019b3a1e Mon Sep 17 00:00:00 2001 From: Ronan Dalton Date: Fri, 13 Sep 2024 10:46:54 +1200 Subject: [PATCH 3/4] lib/route: extend bridge info support Add support for the following attributes for bridge links: IFLA_BR_STP_STATE IFLA_BR_MCAST_ROUTER IFLA_BR_MCAST_SNOOPING --- include/netlink/route/link/bridge_info.h | 15 ++ lib/route/link/bridge_info.c | 174 +++++++++++++++++++++++ libnl-route-3.sym | 6 + 3 files changed, 195 insertions(+) diff --git a/include/netlink/route/link/bridge_info.h b/include/netlink/route/link/bridge_info.h index ff93c779..b7485ac8 100644 --- a/include/netlink/route/link/bridge_info.h +++ b/include/netlink/route/link/bridge_info.h @@ -53,6 +53,21 @@ extern void rtnl_link_bridge_set_nf_call_arptables(struct rtnl_link *link, extern int rtnl_link_bridge_get_nf_call_arptables(struct rtnl_link *link, uint8_t *call_enabled); +extern void rtnl_link_bridge_set_stp_state(struct rtnl_link *link, + uint32_t stp_state); +extern int rtnl_link_bridge_get_stp_state(struct rtnl_link *link, + uint32_t *stp_state); + +extern void rtnl_link_bridge_set_mcast_router(struct rtnl_link *link, + uint8_t type); +extern int rtnl_link_bridge_get_mcast_router(struct rtnl_link *link, + uint8_t *type); + +extern void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, + uint8_t value); +extern int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, + uint8_t *value); + #ifdef __cplusplus } #endif diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c index 7250b437..0e4fdea6 100644 --- a/lib/route/link/bridge_info.c +++ b/lib/route/link/bridge_info.c @@ -26,6 +26,9 @@ #define BRIDGE_ATTR_NF_CALL_IPTABLES (1 << 5) #define BRIDGE_ATTR_NF_CALL_IP6TABLES (1 << 6) #define BRIDGE_ATTR_NF_CALL_ARPTABLES (1 << 7) +#define BRIDGE_ATTR_STP_STATE (1 << 8) +#define BRIDGE_ATTR_MCAST_ROUTER (1 << 9) +#define BRIDGE_ATTR_MCAST_SNOOPING (1 << 10) struct bridge_info { uint32_t ce_mask; /* to support attr macros */ @@ -37,6 +40,9 @@ struct bridge_info { uint8_t b_nf_call_iptables; uint8_t b_nf_call_ip6tables; uint8_t b_nf_call_arptables; + uint32_t b_stp_state; + uint8_t b_mcast_router; + uint8_t b_mcast_snooping; }; static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = { @@ -48,6 +54,9 @@ static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = { [IFLA_BR_NF_CALL_IPTABLES] = { .type = NLA_U8 }, [IFLA_BR_NF_CALL_IP6TABLES] = { .type = NLA_U8 }, [IFLA_BR_NF_CALL_ARPTABLES] = { .type = NLA_U8 }, + [IFLA_BR_STP_STATE] = { .type = NLA_U32 }, + [IFLA_BR_MCAST_ROUTER] = { .type = NLA_U8 }, + [IFLA_BR_MCAST_SNOOPING] = { .type = NLA_U8 }, }; static inline struct bridge_info *bridge_info(struct rtnl_link *link) @@ -136,6 +145,21 @@ static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data, bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES; } + if (tb[IFLA_BR_STP_STATE]) { + bi->b_stp_state = nla_get_u32(tb[IFLA_BR_STP_STATE]); + bi->ce_mask |= BRIDGE_ATTR_STP_STATE; + } + + if (tb[IFLA_BR_MCAST_ROUTER]) { + bi->b_mcast_router = nla_get_u8(tb[IFLA_BR_MCAST_ROUTER]); + bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER; + } + + if (tb[IFLA_BR_MCAST_SNOOPING]) { + bi->b_mcast_snooping = nla_get_u8(tb[IFLA_BR_MCAST_SNOOPING]); + bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING; + } + return 0; } @@ -178,6 +202,15 @@ static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link) NLA_PUT_U8(msg, IFLA_BR_NF_CALL_ARPTABLES, bi->b_nf_call_arptables); + if (bi->ce_mask & BRIDGE_ATTR_STP_STATE) + NLA_PUT_U32(msg, IFLA_BR_STP_STATE, bi->b_stp_state); + + if (bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER) + NLA_PUT_U8(msg, IFLA_BR_MCAST_ROUTER, bi->b_mcast_router); + + if (bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING) + NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, bi->b_mcast_snooping); + nla_nest_end(msg, data); return 0; @@ -605,6 +638,147 @@ int rtnl_link_bridge_get_nf_call_arptables(struct rtnl_link *link, return 0; } +/** + * Set STP state + * @arg link Link object of type bridge + * @arg stp_state STP state to set. Typically 0 or 1. + * + * @see rtnl_link_bridge_get_stp_state() + * + * @return void + */ +void rtnl_link_bridge_set_stp_state(struct rtnl_link *link, uint32_t stp_state) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_stp_state = stp_state; + + bi->ce_mask |= BRIDGE_ATTR_STP_STATE; +} + +/** + * Get STP state + * @arg link Link object of type bridge + * @arg stp_state Output argument. + * + * @see rtnl_link_bridge_set_stp_state() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_stp_state(struct rtnl_link *link, uint32_t *stp_state) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_STP_STATE)) + return -NLE_NOATTR; + + if (!stp_state) + return -NLE_INVAL; + + *stp_state = bi->b_stp_state; + return 0; +} + +/** + * Set multicast router type + * @arg link Link object of type bridge + * @arg type Multicast router type (MDB_RTR_TYPE_*) + * + * @see rtnl_link_bridge_get_mcast_router() + * + * @return void + */ +void rtnl_link_bridge_set_mcast_router(struct rtnl_link *link, uint8_t type) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_mcast_router = type; + + bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER; +} + +/** + * Get multicast router type + * @arg link Link object of type bridge + * @arg type Output argument. + * + * @see rtnl_link_bridge_set_mcast_router() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_mcast_router(struct rtnl_link *link, uint8_t *type) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER)) + return -NLE_NOATTR; + + if (!type) + return -NLE_INVAL; + + *type = bi->b_mcast_router; + return 0; +} + +/** + * Set multicast snooping + * @arg link Link object of type bridge + * @arg value Value to set. Typically 0 or 1. + * + * @see rtnl_link_bridge_get_mcast_snooping() + * + * @return void + */ +void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, uint8_t value) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_mcast_snooping = value; + + bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING; +} + +/** + * Get multicast snooping value + * @arg link Link object of type bridge + * @arg value Output argument. + * + * @see rtnl_link_bridge_set_mcast_snooping() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING)) + return -NLE_NOATTR; + + if (!value) + return -NLE_INVAL; + + *value = bi->b_mcast_snooping; + return 0; +} + static void _nl_init bridge_info_init(void) { rtnl_link_register_info(&bridge_info_ops); diff --git a/libnl-route-3.sym b/libnl-route-3.sym index f42a2d2e..3ab53b47 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1340,9 +1340,15 @@ global: rtnl_link_bond_get_miimon; rtnl_link_bond_get_min_links; rtnl_link_bond_get_mode; + rtnl_link_bridge_get_mcast_router; + rtnl_link_bridge_get_mcast_snooping; rtnl_link_bridge_get_nf_call_arptables; rtnl_link_bridge_get_nf_call_ip6tables; rtnl_link_bridge_get_nf_call_iptables; + rtnl_link_bridge_get_stp_state; + rtnl_link_bridge_set_mcast_router; + rtnl_link_bridge_set_mcast_snooping; + rtnl_link_bridge_set_stp_state; rtnl_link_bridge_set_vlan_default_pvid; rtnl_link_get_perm_addr; rtnl_neigh_extflags2str; From 8a73b2450433fdbe36ca5d90852f693c904b5da3 Mon Sep 17 00:00:00 2001 From: Ronan Dalton Date: Fri, 13 Sep 2024 10:47:02 +1200 Subject: [PATCH 4/4] lib/route: add support for bridge info boolopts Add support for the IFLA_BR_MULTI_BOOLOPT bridge link attribute. --- include/netlink/route/link/bridge_info.h | 5 ++ lib/route/link/bridge_info.c | 81 ++++++++++++++++++++++++ libnl-route-3.sym | 2 + 3 files changed, 88 insertions(+) diff --git a/include/netlink/route/link/bridge_info.h b/include/netlink/route/link/bridge_info.h index b7485ac8..560a7c0a 100644 --- a/include/netlink/route/link/bridge_info.h +++ b/include/netlink/route/link/bridge_info.h @@ -68,6 +68,11 @@ extern void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, extern int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value); +extern int rtnl_link_bridge_set_boolopt(struct rtnl_link *link, int opt, + int value); + +extern int rtnl_link_bridge_get_boolopt(struct rtnl_link *link, int opt); + #ifdef __cplusplus } #endif diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c index 0e4fdea6..c078de5c 100644 --- a/lib/route/link/bridge_info.c +++ b/lib/route/link/bridge_info.c @@ -13,6 +13,8 @@ #include "nl-default.h" +#include + #include #include "nl-route.h" @@ -29,6 +31,7 @@ #define BRIDGE_ATTR_STP_STATE (1 << 8) #define BRIDGE_ATTR_MCAST_ROUTER (1 << 9) #define BRIDGE_ATTR_MCAST_SNOOPING (1 << 10) +#define BRIDGE_ATTR_BOOLOPT (1 << 11) struct bridge_info { uint32_t ce_mask; /* to support attr macros */ @@ -43,6 +46,7 @@ struct bridge_info { uint32_t b_stp_state; uint8_t b_mcast_router; uint8_t b_mcast_snooping; + struct br_boolopt_multi b_boolopts; }; static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = { @@ -57,6 +61,9 @@ static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = { [IFLA_BR_STP_STATE] = { .type = NLA_U32 }, [IFLA_BR_MCAST_ROUTER] = { .type = NLA_U8 }, [IFLA_BR_MCAST_SNOOPING] = { .type = NLA_U8 }, + [IFLA_BR_MULTI_BOOLOPT] = { .type = NLA_BINARY, + .minlen = sizeof(struct br_boolopt_multi), + .maxlen = sizeof(struct br_boolopt_multi) }, }; static inline struct bridge_info *bridge_info(struct rtnl_link *link) @@ -160,6 +167,12 @@ static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data, bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING; } + if (tb[IFLA_BR_MULTI_BOOLOPT]) { + nla_memcpy(&bi->b_boolopts, tb[IFLA_BR_MULTI_BOOLOPT], + sizeof(bi->b_boolopts)); + bi->ce_mask |= BRIDGE_ATTR_BOOLOPT; + } + return 0; } @@ -211,6 +224,10 @@ static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link) if (bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING) NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, bi->b_mcast_snooping); + if (bi->ce_mask & BRIDGE_ATTR_BOOLOPT) + NLA_PUT(msg, IFLA_BR_MULTI_BOOLOPT, sizeof(bi->b_boolopts), + &bi->b_boolopts); + nla_nest_end(msg, data); return 0; @@ -779,6 +796,70 @@ int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value) return 0; } +/** + * Set a the value of a boolopt + * @arg link Link object of type bridge + * @arg opt Option to modify (BR_BOOLOPT_*) + * @arg value Value to set the option to. 0 or 1. + * + * @see rtnl_link_bridge_get_boolopt() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_set_boolopt(struct rtnl_link *link, int opt, int value) +{ + struct bridge_info *bi = bridge_info(link); + uint32_t mask; + + IS_BRIDGE_INFO_ASSERT(link); + + if (opt < 0 || opt >= 32 || !(value == 0 || value == 1)) + return -NLE_INVAL; + + mask = 1ul << opt; + + if (value) + bi->b_boolopts.optval |= mask; + else + bi->b_boolopts.optval &= ~mask; + + bi->b_boolopts.optmask |= mask; + bi->ce_mask |= BRIDGE_ATTR_BOOLOPT; + + return 0; +} + +/** + * Get the value of a boolopt + * @arg link Link object of type bridge + * @arg opt Option to get (BR_BOOLOPT_*). + * + * @see rtnl_link_bridge_set_boolopt() + * + * @return The value of the boolopt (0 or 1), otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_boolopt(struct rtnl_link *link, int opt) +{ + struct bridge_info *bi = bridge_info(link); + uint32_t mask; + + IS_BRIDGE_INFO_ASSERT(link); + + if (opt < 0 || opt >= 32) + return -NLE_INVAL; + + mask = 1ul << opt; + + if (!(bi->ce_mask & BRIDGE_ATTR_BOOLOPT) || + !(bi->b_boolopts.optmask & mask)) + return -NLE_NOATTR; + + return !!(bi->b_boolopts.optval & mask); +} + static void _nl_init bridge_info_init(void) { rtnl_link_register_info(&bridge_info_ops); diff --git a/libnl-route-3.sym b/libnl-route-3.sym index 3ab53b47..d8e3e0c0 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1340,12 +1340,14 @@ global: rtnl_link_bond_get_miimon; rtnl_link_bond_get_min_links; rtnl_link_bond_get_mode; + rtnl_link_bridge_get_boolopt; rtnl_link_bridge_get_mcast_router; rtnl_link_bridge_get_mcast_snooping; rtnl_link_bridge_get_nf_call_arptables; rtnl_link_bridge_get_nf_call_ip6tables; rtnl_link_bridge_get_nf_call_iptables; rtnl_link_bridge_get_stp_state; + rtnl_link_bridge_set_boolopt; rtnl_link_bridge_set_mcast_router; rtnl_link_bridge_set_mcast_snooping; rtnl_link_bridge_set_stp_state;