diff options
| author | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
| commit | aafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch) | |
| tree | a2a9bb4d007339a0b1304540388230ccedac32bd /src/platform | |
| parent | e7b44ef4c80907346ec7492a09c45277459924fc (diff) | |
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'src/platform')
37 files changed, 37117 insertions, 33377 deletions
diff --git a/src/platform/linux/nl802154.h b/src/platform/linux/nl802154.h index 57646a39..c21bd079 100644 --- a/src/platform/linux/nl802154.h +++ b/src/platform/linux/nl802154.h @@ -22,144 +22,144 @@ #define NL802154_GENL_NAME "nl802154" enum nl802154_commands { -/* don't change the order or add anything between, this is ABI! */ -/* currently we don't shipping this file via uapi, ignore the above one */ - NL802154_CMD_UNSPEC, + /* don't change the order or add anything between, this is ABI! */ + /* currently we don't shipping this file via uapi, ignore the above one */ + NL802154_CMD_UNSPEC, - NL802154_CMD_GET_WPAN_PHY, /* can dump */ - NL802154_CMD_SET_WPAN_PHY, - NL802154_CMD_NEW_WPAN_PHY, - NL802154_CMD_DEL_WPAN_PHY, + NL802154_CMD_GET_WPAN_PHY, /* can dump */ + NL802154_CMD_SET_WPAN_PHY, + NL802154_CMD_NEW_WPAN_PHY, + NL802154_CMD_DEL_WPAN_PHY, - NL802154_CMD_GET_INTERFACE, /* can dump */ - NL802154_CMD_SET_INTERFACE, - NL802154_CMD_NEW_INTERFACE, - NL802154_CMD_DEL_INTERFACE, + NL802154_CMD_GET_INTERFACE, /* can dump */ + NL802154_CMD_SET_INTERFACE, + NL802154_CMD_NEW_INTERFACE, + NL802154_CMD_DEL_INTERFACE, - NL802154_CMD_SET_CHANNEL, + NL802154_CMD_SET_CHANNEL, - NL802154_CMD_SET_PAN_ID, - NL802154_CMD_SET_SHORT_ADDR, + NL802154_CMD_SET_PAN_ID, + NL802154_CMD_SET_SHORT_ADDR, - NL802154_CMD_SET_TX_POWER, - NL802154_CMD_SET_CCA_MODE, - NL802154_CMD_SET_CCA_ED_LEVEL, + NL802154_CMD_SET_TX_POWER, + NL802154_CMD_SET_CCA_MODE, + NL802154_CMD_SET_CCA_ED_LEVEL, - NL802154_CMD_SET_MAX_FRAME_RETRIES, + NL802154_CMD_SET_MAX_FRAME_RETRIES, - NL802154_CMD_SET_BACKOFF_EXPONENT, - NL802154_CMD_SET_MAX_CSMA_BACKOFFS, + NL802154_CMD_SET_BACKOFF_EXPONENT, + NL802154_CMD_SET_MAX_CSMA_BACKOFFS, - NL802154_CMD_SET_LBT_MODE, + NL802154_CMD_SET_LBT_MODE, - NL802154_CMD_SET_ACKREQ_DEFAULT, + NL802154_CMD_SET_ACKREQ_DEFAULT, - NL802154_CMD_SET_WPAN_PHY_NETNS, + NL802154_CMD_SET_WPAN_PHY_NETNS, - /* add new commands above here */ +/* add new commands above here */ #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL - NL802154_CMD_SET_SEC_PARAMS, - NL802154_CMD_GET_SEC_KEY, /* can dump */ - NL802154_CMD_NEW_SEC_KEY, - NL802154_CMD_DEL_SEC_KEY, - NL802154_CMD_GET_SEC_DEV, /* can dump */ - NL802154_CMD_NEW_SEC_DEV, - NL802154_CMD_DEL_SEC_DEV, - NL802154_CMD_GET_SEC_DEVKEY, /* can dump */ - NL802154_CMD_NEW_SEC_DEVKEY, - NL802154_CMD_DEL_SEC_DEVKEY, - NL802154_CMD_GET_SEC_LEVEL, /* can dump */ - NL802154_CMD_NEW_SEC_LEVEL, - NL802154_CMD_DEL_SEC_LEVEL, + NL802154_CMD_SET_SEC_PARAMS, + NL802154_CMD_GET_SEC_KEY, /* can dump */ + NL802154_CMD_NEW_SEC_KEY, + NL802154_CMD_DEL_SEC_KEY, + NL802154_CMD_GET_SEC_DEV, /* can dump */ + NL802154_CMD_NEW_SEC_DEV, + NL802154_CMD_DEL_SEC_DEV, + NL802154_CMD_GET_SEC_DEVKEY, /* can dump */ + NL802154_CMD_NEW_SEC_DEVKEY, + NL802154_CMD_DEL_SEC_DEVKEY, + NL802154_CMD_GET_SEC_LEVEL, /* can dump */ + NL802154_CMD_NEW_SEC_LEVEL, + NL802154_CMD_DEL_SEC_LEVEL, #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ - /* used to define NL802154_CMD_MAX below */ - __NL802154_CMD_AFTER_LAST, - NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1 + /* used to define NL802154_CMD_MAX below */ + __NL802154_CMD_AFTER_LAST, + NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1 }; enum nl802154_attrs { -/* don't change the order or add anything between, this is ABI! */ -/* currently we don't shipping this file via uapi, ignore the above one */ - NL802154_ATTR_UNSPEC, + /* don't change the order or add anything between, this is ABI! */ + /* currently we don't shipping this file via uapi, ignore the above one */ + NL802154_ATTR_UNSPEC, - NL802154_ATTR_WPAN_PHY, - NL802154_ATTR_WPAN_PHY_NAME, + NL802154_ATTR_WPAN_PHY, + NL802154_ATTR_WPAN_PHY_NAME, - NL802154_ATTR_IFINDEX, - NL802154_ATTR_IFNAME, - NL802154_ATTR_IFTYPE, + NL802154_ATTR_IFINDEX, + NL802154_ATTR_IFNAME, + NL802154_ATTR_IFTYPE, - NL802154_ATTR_WPAN_DEV, + NL802154_ATTR_WPAN_DEV, - NL802154_ATTR_PAGE, - NL802154_ATTR_CHANNEL, + NL802154_ATTR_PAGE, + NL802154_ATTR_CHANNEL, - NL802154_ATTR_PAN_ID, - NL802154_ATTR_SHORT_ADDR, + NL802154_ATTR_PAN_ID, + NL802154_ATTR_SHORT_ADDR, - NL802154_ATTR_TX_POWER, + NL802154_ATTR_TX_POWER, - NL802154_ATTR_CCA_MODE, - NL802154_ATTR_CCA_OPT, - NL802154_ATTR_CCA_ED_LEVEL, + NL802154_ATTR_CCA_MODE, + NL802154_ATTR_CCA_OPT, + NL802154_ATTR_CCA_ED_LEVEL, - NL802154_ATTR_MAX_FRAME_RETRIES, + NL802154_ATTR_MAX_FRAME_RETRIES, - NL802154_ATTR_MAX_BE, - NL802154_ATTR_MIN_BE, - NL802154_ATTR_MAX_CSMA_BACKOFFS, + NL802154_ATTR_MAX_BE, + NL802154_ATTR_MIN_BE, + NL802154_ATTR_MAX_CSMA_BACKOFFS, - NL802154_ATTR_LBT_MODE, + NL802154_ATTR_LBT_MODE, - NL802154_ATTR_GENERATION, + NL802154_ATTR_GENERATION, - NL802154_ATTR_CHANNELS_SUPPORTED, - NL802154_ATTR_SUPPORTED_CHANNEL, + NL802154_ATTR_CHANNELS_SUPPORTED, + NL802154_ATTR_SUPPORTED_CHANNEL, - NL802154_ATTR_EXTENDED_ADDR, + NL802154_ATTR_EXTENDED_ADDR, - NL802154_ATTR_WPAN_PHY_CAPS, + NL802154_ATTR_WPAN_PHY_CAPS, - NL802154_ATTR_SUPPORTED_COMMANDS, + NL802154_ATTR_SUPPORTED_COMMANDS, - NL802154_ATTR_ACKREQ_DEFAULT, + NL802154_ATTR_ACKREQ_DEFAULT, - NL802154_ATTR_PAD, + NL802154_ATTR_PAD, - NL802154_ATTR_PID, - NL802154_ATTR_NETNS_FD, + NL802154_ATTR_PID, + NL802154_ATTR_NETNS_FD, - /* add attributes here, update the policy in nl802154.c */ +/* add attributes here, update the policy in nl802154.c */ #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL - NL802154_ATTR_SEC_ENABLED, - NL802154_ATTR_SEC_OUT_LEVEL, - NL802154_ATTR_SEC_OUT_KEY_ID, - NL802154_ATTR_SEC_FRAME_COUNTER, - - NL802154_ATTR_SEC_LEVEL, - NL802154_ATTR_SEC_DEVICE, - NL802154_ATTR_SEC_DEVKEY, - NL802154_ATTR_SEC_KEY, + NL802154_ATTR_SEC_ENABLED, + NL802154_ATTR_SEC_OUT_LEVEL, + NL802154_ATTR_SEC_OUT_KEY_ID, + NL802154_ATTR_SEC_FRAME_COUNTER, + + NL802154_ATTR_SEC_LEVEL, + NL802154_ATTR_SEC_DEVICE, + NL802154_ATTR_SEC_DEVKEY, + NL802154_ATTR_SEC_KEY, #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ - __NL802154_ATTR_AFTER_LAST, - NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1 + __NL802154_ATTR_AFTER_LAST, + NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1 }; enum nl802154_iftype { - /* for backwards compatibility TODO */ - NL802154_IFTYPE_UNSPEC = -1, + /* for backwards compatibility TODO */ + NL802154_IFTYPE_UNSPEC = -1, - NL802154_IFTYPE_NODE, - NL802154_IFTYPE_MONITOR, - NL802154_IFTYPE_COORD, + NL802154_IFTYPE_NODE, + NL802154_IFTYPE_MONITOR, + NL802154_IFTYPE_COORD, - /* keep last */ - NUM_NL802154_IFTYPES, - NL802154_IFTYPE_MAX = NUM_NL802154_IFTYPES - 1 + /* keep last */ + NUM_NL802154_IFTYPES, + NL802154_IFTYPE_MAX = NUM_NL802154_IFTYPES - 1 }; /** @@ -167,8 +167,7 @@ enum nl802154_iftype { * * @__NL802154_CAP_ATTR_INVALID: attribute number 0 is reserved * @NL802154_CAP_ATTR_CHANNELS: a nested attribute for nl802154_channel_attr - * @NL802154_CAP_ATTR_TX_POWERS: a nested attribute for - * nl802154_wpan_phy_tx_power + * @NL802154_CAP_ATTR_TX_POWERS: a nested attribute for nl802154_wpan_phy_tx_power * @NL802154_CAP_ATTR_MIN_CCA_ED_LEVEL: minimum value for cca_ed_level * @NL802154_CAP_ATTR_MAX_CCA_ED_LEVEL: maxmimum value for cca_ed_level * @NL802154_CAP_ATTR_CCA_MODES: nl802154_cca_modes flags @@ -187,34 +186,34 @@ enum nl802154_iftype { * @__NL802154_CAP_ATTR_AFTER_LAST: internal use */ enum nl802154_wpan_phy_capability_attr { - __NL802154_CAP_ATTR_INVALID, + __NL802154_CAP_ATTR_INVALID, - NL802154_CAP_ATTR_IFTYPES, + NL802154_CAP_ATTR_IFTYPES, - NL802154_CAP_ATTR_CHANNELS, - NL802154_CAP_ATTR_TX_POWERS, + NL802154_CAP_ATTR_CHANNELS, + NL802154_CAP_ATTR_TX_POWERS, - NL802154_CAP_ATTR_CCA_ED_LEVELS, - NL802154_CAP_ATTR_CCA_MODES, - NL802154_CAP_ATTR_CCA_OPTS, + NL802154_CAP_ATTR_CCA_ED_LEVELS, + NL802154_CAP_ATTR_CCA_MODES, + NL802154_CAP_ATTR_CCA_OPTS, - NL802154_CAP_ATTR_MIN_MINBE, - NL802154_CAP_ATTR_MAX_MINBE, + NL802154_CAP_ATTR_MIN_MINBE, + NL802154_CAP_ATTR_MAX_MINBE, - NL802154_CAP_ATTR_MIN_MAXBE, - NL802154_CAP_ATTR_MAX_MAXBE, + NL802154_CAP_ATTR_MIN_MAXBE, + NL802154_CAP_ATTR_MAX_MAXBE, - NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS, - NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS, + NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS, + NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS, - NL802154_CAP_ATTR_MIN_FRAME_RETRIES, - NL802154_CAP_ATTR_MAX_FRAME_RETRIES, + NL802154_CAP_ATTR_MIN_FRAME_RETRIES, + NL802154_CAP_ATTR_MAX_FRAME_RETRIES, - NL802154_CAP_ATTR_LBT, + NL802154_CAP_ATTR_LBT, - /* keep last */ - __NL802154_CAP_ATTR_AFTER_LAST, - NL802154_CAP_ATTR_MAX = __NL802154_CAP_ATTR_AFTER_LAST - 1 + /* keep last */ + __NL802154_CAP_ATTR_AFTER_LAST, + NL802154_CAP_ATTR_MAX = __NL802154_CAP_ATTR_AFTER_LAST - 1 }; /** @@ -226,23 +225,22 @@ enum nl802154_wpan_phy_capability_attr { * @NL802154_CCA_ENERGY_CARRIER: Carrier sense with energy above threshold * @NL802154_CCA_ALOHA: CCA shall always report an idle medium * @NL802154_CCA_UWB_SHR: UWB preamble sense based on the SHR of a frame - * @NL802154_CCA_UWB_MULTIPLEXED: UWB preamble sense based on the packet with - * the multiplexed preamble + * @NL802154_CCA_UWB_MULTIPLEXED: UWB preamble sense based on the packet with the multiplexed preamble * @__NL802154_CCA_ATTR_AFTER_LAST: Internal * @NL802154_CCA_ATTR_MAX: Maximum CCA attribute number */ enum nl802154_cca_modes { - __NL802154_CCA_INVALID, - NL802154_CCA_ENERGY, - NL802154_CCA_CARRIER, - NL802154_CCA_ENERGY_CARRIER, - NL802154_CCA_ALOHA, - NL802154_CCA_UWB_SHR, - NL802154_CCA_UWB_MULTIPLEXED, - - /* keep last */ - __NL802154_CCA_ATTR_AFTER_LAST, - NL802154_CCA_ATTR_MAX = __NL802154_CCA_ATTR_AFTER_LAST - 1 + __NL802154_CCA_INVALID, + NL802154_CCA_ENERGY, + NL802154_CCA_CARRIER, + NL802154_CCA_ENERGY_CARRIER, + NL802154_CCA_ALOHA, + NL802154_CCA_UWB_SHR, + NL802154_CCA_UWB_MULTIPLEXED, + + /* keep last */ + __NL802154_CCA_ATTR_AFTER_LAST, + NL802154_CCA_ATTR_MAX = __NL802154_CCA_ATTR_AFTER_LAST - 1 }; /** @@ -252,12 +250,12 @@ enum nl802154_cca_modes { * @NL802154_CCA_OPT_ENERGY_CARRIER_AND: NL802154_CCA_ENERGY_CARRIER with AND */ enum nl802154_cca_opts { - NL802154_CCA_OPT_ENERGY_CARRIER_AND, - NL802154_CCA_OPT_ENERGY_CARRIER_OR, + NL802154_CCA_OPT_ENERGY_CARRIER_AND, + NL802154_CCA_OPT_ENERGY_CARRIER_OR, - /* keep last */ - __NL802154_CCA_OPT_ATTR_AFTER_LAST, - NL802154_CCA_OPT_ATTR_MAX = __NL802154_CCA_OPT_ATTR_AFTER_LAST - 1 + /* keep last */ + __NL802154_CCA_OPT_ATTR_AFTER_LAST, + NL802154_CCA_OPT_ATTR_MAX = __NL802154_CCA_OPT_ATTR_AFTER_LAST - 1 }; /** @@ -271,181 +269,181 @@ enum nl802154_cca_opts { * @NL802154_SUPPORTED_BOOL_MAX: highest value for bool states */ enum nl802154_supported_bool_states { - NL802154_SUPPORTED_BOOL_FALSE, - NL802154_SUPPORTED_BOOL_TRUE, - /* to handle them in a mask */ - __NL802154_SUPPORTED_BOOL_INVALD, - NL802154_SUPPORTED_BOOL_BOTH, - - /* keep last */ - __NL802154_SUPPORTED_BOOL_AFTER_LAST, - NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1 + NL802154_SUPPORTED_BOOL_FALSE, + NL802154_SUPPORTED_BOOL_TRUE, + /* to handle them in a mask */ + __NL802154_SUPPORTED_BOOL_INVALD, + NL802154_SUPPORTED_BOOL_BOTH, + + /* keep last */ + __NL802154_SUPPORTED_BOOL_AFTER_LAST, + NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1 }; #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL enum nl802154_dev_addr_modes { - NL802154_DEV_ADDR_NONE, - __NL802154_DEV_ADDR_INVALID, - NL802154_DEV_ADDR_SHORT, - NL802154_DEV_ADDR_EXTENDED, - - /* keep last */ - __NL802154_DEV_ADDR_AFTER_LAST, - NL802154_DEV_ADDR_MAX = __NL802154_DEV_ADDR_AFTER_LAST - 1 + NL802154_DEV_ADDR_NONE, + __NL802154_DEV_ADDR_INVALID, + NL802154_DEV_ADDR_SHORT, + NL802154_DEV_ADDR_EXTENDED, + + /* keep last */ + __NL802154_DEV_ADDR_AFTER_LAST, + NL802154_DEV_ADDR_MAX = __NL802154_DEV_ADDR_AFTER_LAST - 1 }; enum nl802154_dev_addr_attrs { - NL802154_DEV_ADDR_ATTR_UNSPEC, + NL802154_DEV_ADDR_ATTR_UNSPEC, - NL802154_DEV_ADDR_ATTR_PAN_ID, - NL802154_DEV_ADDR_ATTR_MODE, - NL802154_DEV_ADDR_ATTR_SHORT, - NL802154_DEV_ADDR_ATTR_EXTENDED, - NL802154_DEV_ADDR_ATTR_PAD, + NL802154_DEV_ADDR_ATTR_PAN_ID, + NL802154_DEV_ADDR_ATTR_MODE, + NL802154_DEV_ADDR_ATTR_SHORT, + NL802154_DEV_ADDR_ATTR_EXTENDED, + NL802154_DEV_ADDR_ATTR_PAD, - /* keep last */ - __NL802154_DEV_ADDR_ATTR_AFTER_LAST, - NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1 + /* keep last */ + __NL802154_DEV_ADDR_ATTR_AFTER_LAST, + NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1 }; enum nl802154_key_id_modes { - NL802154_KEY_ID_MODE_IMPLICIT, - NL802154_KEY_ID_MODE_INDEX, - NL802154_KEY_ID_MODE_INDEX_SHORT, - NL802154_KEY_ID_MODE_INDEX_EXTENDED, - - /* keep last */ - __NL802154_KEY_ID_MODE_AFTER_LAST, - NL802154_KEY_ID_MODE_MAX = __NL802154_KEY_ID_MODE_AFTER_LAST - 1 + NL802154_KEY_ID_MODE_IMPLICIT, + NL802154_KEY_ID_MODE_INDEX, + NL802154_KEY_ID_MODE_INDEX_SHORT, + NL802154_KEY_ID_MODE_INDEX_EXTENDED, + + /* keep last */ + __NL802154_KEY_ID_MODE_AFTER_LAST, + NL802154_KEY_ID_MODE_MAX = __NL802154_KEY_ID_MODE_AFTER_LAST - 1 }; enum nl802154_key_id_attrs { - NL802154_KEY_ID_ATTR_UNSPEC, - - NL802154_KEY_ID_ATTR_MODE, - NL802154_KEY_ID_ATTR_INDEX, - NL802154_KEY_ID_ATTR_IMPLICIT, - NL802154_KEY_ID_ATTR_SOURCE_SHORT, - NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, - NL802154_KEY_ID_ATTR_PAD, - - /* keep last */ - __NL802154_KEY_ID_ATTR_AFTER_LAST, - NL802154_KEY_ID_ATTR_MAX = __NL802154_KEY_ID_ATTR_AFTER_LAST - 1 + NL802154_KEY_ID_ATTR_UNSPEC, + + NL802154_KEY_ID_ATTR_MODE, + NL802154_KEY_ID_ATTR_INDEX, + NL802154_KEY_ID_ATTR_IMPLICIT, + NL802154_KEY_ID_ATTR_SOURCE_SHORT, + NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, + NL802154_KEY_ID_ATTR_PAD, + + /* keep last */ + __NL802154_KEY_ID_ATTR_AFTER_LAST, + NL802154_KEY_ID_ATTR_MAX = __NL802154_KEY_ID_ATTR_AFTER_LAST - 1 }; enum nl802154_seclevels { - NL802154_SECLEVEL_NONE, - NL802154_SECLEVEL_MIC32, - NL802154_SECLEVEL_MIC64, - NL802154_SECLEVEL_MIC128, - NL802154_SECLEVEL_ENC, - NL802154_SECLEVEL_ENC_MIC32, - NL802154_SECLEVEL_ENC_MIC64, - NL802154_SECLEVEL_ENC_MIC128, - - /* keep last */ - __NL802154_SECLEVEL_AFTER_LAST, - NL802154_SECLEVEL_MAX = __NL802154_SECLEVEL_AFTER_LAST - 1 + NL802154_SECLEVEL_NONE, + NL802154_SECLEVEL_MIC32, + NL802154_SECLEVEL_MIC64, + NL802154_SECLEVEL_MIC128, + NL802154_SECLEVEL_ENC, + NL802154_SECLEVEL_ENC_MIC32, + NL802154_SECLEVEL_ENC_MIC64, + NL802154_SECLEVEL_ENC_MIC128, + + /* keep last */ + __NL802154_SECLEVEL_AFTER_LAST, + NL802154_SECLEVEL_MAX = __NL802154_SECLEVEL_AFTER_LAST - 1 }; enum nl802154_frames { - NL802154_FRAME_BEACON, - NL802154_FRAME_DATA, - NL802154_FRAME_ACK, - NL802154_FRAME_CMD, - - /* keep last */ - __NL802154_FRAME_AFTER_LAST, - NL802154_FRAME_MAX = __NL802154_FRAME_AFTER_LAST - 1 + NL802154_FRAME_BEACON, + NL802154_FRAME_DATA, + NL802154_FRAME_ACK, + NL802154_FRAME_CMD, + + /* keep last */ + __NL802154_FRAME_AFTER_LAST, + NL802154_FRAME_MAX = __NL802154_FRAME_AFTER_LAST - 1 }; enum nl802154_cmd_frames { - __NL802154_CMD_FRAME_INVALID, - NL802154_CMD_FRAME_ASSOC_REQUEST, - NL802154_CMD_FRAME_ASSOC_RESPONSE, - NL802154_CMD_FRAME_DISASSOC_NOTIFY, - NL802154_CMD_FRAME_DATA_REQUEST, - NL802154_CMD_FRAME_PAN_ID_CONFLICT_NOTIFY, - NL802154_CMD_FRAME_ORPHAN_NOTIFY, - NL802154_CMD_FRAME_BEACON_REQUEST, - NL802154_CMD_FRAME_COORD_REALIGNMENT, - NL802154_CMD_FRAME_GTS_REQUEST, - - /* keep last */ - __NL802154_CMD_FRAME_AFTER_LAST, - NL802154_CMD_FRAME_MAX = __NL802154_CMD_FRAME_AFTER_LAST - 1 + __NL802154_CMD_FRAME_INVALID, + NL802154_CMD_FRAME_ASSOC_REQUEST, + NL802154_CMD_FRAME_ASSOC_RESPONSE, + NL802154_CMD_FRAME_DISASSOC_NOTIFY, + NL802154_CMD_FRAME_DATA_REQUEST, + NL802154_CMD_FRAME_PAN_ID_CONFLICT_NOTIFY, + NL802154_CMD_FRAME_ORPHAN_NOTIFY, + NL802154_CMD_FRAME_BEACON_REQUEST, + NL802154_CMD_FRAME_COORD_REALIGNMENT, + NL802154_CMD_FRAME_GTS_REQUEST, + + /* keep last */ + __NL802154_CMD_FRAME_AFTER_LAST, + NL802154_CMD_FRAME_MAX = __NL802154_CMD_FRAME_AFTER_LAST - 1 }; enum nl802154_seclevel_attrs { - NL802154_SECLEVEL_ATTR_UNSPEC, + NL802154_SECLEVEL_ATTR_UNSPEC, - NL802154_SECLEVEL_ATTR_LEVELS, - NL802154_SECLEVEL_ATTR_FRAME, - NL802154_SECLEVEL_ATTR_CMD_FRAME, - NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, + NL802154_SECLEVEL_ATTR_LEVELS, + NL802154_SECLEVEL_ATTR_FRAME, + NL802154_SECLEVEL_ATTR_CMD_FRAME, + NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, - /* keep last */ - __NL802154_SECLEVEL_ATTR_AFTER_LAST, - NL802154_SECLEVEL_ATTR_MAX = __NL802154_SECLEVEL_ATTR_AFTER_LAST - 1 + /* keep last */ + __NL802154_SECLEVEL_ATTR_AFTER_LAST, + NL802154_SECLEVEL_ATTR_MAX = __NL802154_SECLEVEL_ATTR_AFTER_LAST - 1 }; /* TODO what is this? couldn't find in mib */ enum { - NL802154_DEVKEY_IGNORE, - NL802154_DEVKEY_RESTRICT, - NL802154_DEVKEY_RECORD, + NL802154_DEVKEY_IGNORE, + NL802154_DEVKEY_RESTRICT, + NL802154_DEVKEY_RECORD, - /* keep last */ - __NL802154_DEVKEY_AFTER_LAST, - NL802154_DEVKEY_MAX = __NL802154_DEVKEY_AFTER_LAST - 1 + /* keep last */ + __NL802154_DEVKEY_AFTER_LAST, + NL802154_DEVKEY_MAX = __NL802154_DEVKEY_AFTER_LAST - 1 }; enum nl802154_dev { - NL802154_DEV_ATTR_UNSPEC, - - NL802154_DEV_ATTR_FRAME_COUNTER, - NL802154_DEV_ATTR_PAN_ID, - NL802154_DEV_ATTR_SHORT_ADDR, - NL802154_DEV_ATTR_EXTENDED_ADDR, - NL802154_DEV_ATTR_SECLEVEL_EXEMPT, - NL802154_DEV_ATTR_KEY_MODE, - NL802154_DEV_ATTR_PAD, - - /* keep last */ - __NL802154_DEV_ATTR_AFTER_LAST, - NL802154_DEV_ATTR_MAX = __NL802154_DEV_ATTR_AFTER_LAST - 1 + NL802154_DEV_ATTR_UNSPEC, + + NL802154_DEV_ATTR_FRAME_COUNTER, + NL802154_DEV_ATTR_PAN_ID, + NL802154_DEV_ATTR_SHORT_ADDR, + NL802154_DEV_ATTR_EXTENDED_ADDR, + NL802154_DEV_ATTR_SECLEVEL_EXEMPT, + NL802154_DEV_ATTR_KEY_MODE, + NL802154_DEV_ATTR_PAD, + + /* keep last */ + __NL802154_DEV_ATTR_AFTER_LAST, + NL802154_DEV_ATTR_MAX = __NL802154_DEV_ATTR_AFTER_LAST - 1 }; enum nl802154_devkey { - NL802154_DEVKEY_ATTR_UNSPEC, + NL802154_DEVKEY_ATTR_UNSPEC, - NL802154_DEVKEY_ATTR_FRAME_COUNTER, - NL802154_DEVKEY_ATTR_EXTENDED_ADDR, - NL802154_DEVKEY_ATTR_ID, - NL802154_DEVKEY_ATTR_PAD, + NL802154_DEVKEY_ATTR_FRAME_COUNTER, + NL802154_DEVKEY_ATTR_EXTENDED_ADDR, + NL802154_DEVKEY_ATTR_ID, + NL802154_DEVKEY_ATTR_PAD, - /* keep last */ - __NL802154_DEVKEY_ATTR_AFTER_LAST, - NL802154_DEVKEY_ATTR_MAX = __NL802154_DEVKEY_ATTR_AFTER_LAST - 1 + /* keep last */ + __NL802154_DEVKEY_ATTR_AFTER_LAST, + NL802154_DEVKEY_ATTR_MAX = __NL802154_DEVKEY_ATTR_AFTER_LAST - 1 }; enum nl802154_key { - NL802154_KEY_ATTR_UNSPEC, + NL802154_KEY_ATTR_UNSPEC, - NL802154_KEY_ATTR_ID, - NL802154_KEY_ATTR_USAGE_FRAMES, - NL802154_KEY_ATTR_USAGE_CMDS, - NL802154_KEY_ATTR_BYTES, + NL802154_KEY_ATTR_ID, + NL802154_KEY_ATTR_USAGE_FRAMES, + NL802154_KEY_ATTR_USAGE_CMDS, + NL802154_KEY_ATTR_BYTES, - /* keep last */ - __NL802154_KEY_ATTR_AFTER_LAST, - NL802154_KEY_ATTR_MAX = __NL802154_KEY_ATTR_AFTER_LAST - 1 + /* keep last */ + __NL802154_KEY_ATTR_AFTER_LAST, + NL802154_KEY_ATTR_MAX = __NL802154_KEY_ATTR_AFTER_LAST - 1 }; -#define NL802154_KEY_SIZE 16 -#define NL802154_CMD_FRAME_NR_IDS 256 + #define NL802154_KEY_SIZE 16 + #define NL802154_CMD_FRAME_NR_IDS 256 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index d9cf2de5..94c3f0e8 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2012 - 2017 Red Hat, Inc. */ @@ -25,1380 +25,1376 @@ /*****************************************************************************/ typedef struct { - const NMPObject *obj; - char *udi; - struct in6_addr ip6_lladdr; + const NMPObject *obj; + char * udi; + struct in6_addr ip6_lladdr; } NMFakePlatformLink; typedef struct { - GHashTable *options; - GArray *links; + GHashTable *options; + GArray * links; } NMFakePlatformPrivate; struct _NMFakePlatform { - NMPlatform parent; - NMFakePlatformPrivate _priv; + NMPlatform parent; + NMFakePlatformPrivate _priv; }; struct _NMFakePlatformClass { - NMPlatformClass parent; + NMPlatformClass parent; }; -G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM) +G_DEFINE_TYPE(NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM) -#define NM_FAKE_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMFakePlatform, NM_IS_FAKE_PLATFORM, NMPlatform) +#define NM_FAKE_PLATFORM_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMFakePlatform, NM_IS_FAKE_PLATFORM, NMPlatform) /*****************************************************************************/ -#define _NMLOG_PREFIX_NAME "platform-fake" -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, platform, __VA_ARGS__) - -#define _LOG(level, domain, self, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ - \ - if (nm_logging_enabled (__level, __domain)) { \ - char __prefix[32]; \ - const char *__p_prefix = _NMLOG_PREFIX_NAME; \ - NMPlatform *const __self = (self); \ - \ - if (__self && nm_platform_get_log_with_ptr (self)) { \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ - __p_prefix = __prefix; \ - } \ - _nm_log (__level, __domain, 0, NULL, NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END +#define _NMLOG_PREFIX_NAME "platform-fake" +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, platform, __VA_ARGS__) + +#define _LOG(level, domain, self, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + const NMLogDomain __domain = (domain); \ + \ + if (nm_logging_enabled(__level, __domain)) { \ + char __prefix[32]; \ + const char * __p_prefix = _NMLOG_PREFIX_NAME; \ + NMPlatform *const __self = (self); \ + \ + if (__self && nm_platform_get_log_with_ptr(self)) { \ + g_snprintf(__prefix, sizeof(__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ + __p_prefix = __prefix; \ + } \ + _nm_log(__level, \ + __domain, \ + 0, \ + NULL, \ + NULL, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + __p_prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ -static void link_changed (NMPlatform *platform, - NMFakePlatformLink *device, - NMPCacheOpsType cache_op, - const NMPObject *obj_old); - -static gboolean ipx_address_delete (NMPlatform *platform, - int addr_family, - int ifindex, - gconstpointer addr, - const guint8 *plen, - gconstpointer peer_addr); - -static gboolean ipx_route_delete (NMPlatform *platform, - int addr_family, - int ifindex, - const NMPObject *obj); - -static gboolean ip6_address_add (NMPlatform *platform, - int ifindex, - struct in6_addr addr, - guint8 plen, - struct in6_addr peer_addr, - guint32 lifetime, - guint32 preferred, - guint flags); -static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen); +static void link_changed(NMPlatform * platform, + NMFakePlatformLink *device, + NMPCacheOpsType cache_op, + const NMPObject * obj_old); + +static gboolean ipx_address_delete(NMPlatform * platform, + int addr_family, + int ifindex, + gconstpointer addr, + const guint8 *plen, + gconstpointer peer_addr); + +static gboolean +ipx_route_delete(NMPlatform *platform, int addr_family, int ifindex, const NMPObject *obj); + +static gboolean ip6_address_add(NMPlatform * platform, + int ifindex, + struct in6_addr addr, + guint8 plen, + struct in6_addr peer_addr, + guint32 lifetime, + guint32 preferred, + guint flags); +static gboolean +ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen); /*****************************************************************************/ -#define ASSERT_SYSCTL_ARGS(pathid, dirfd, path) \ - G_STMT_START { \ - const char *const _pathid = (pathid); \ - const int _dirfd = (dirfd); \ - const char *const _path = (path); \ - \ - g_assert (_path && _path[0]); \ - g_assert (!strstr (_path, "/../")); \ - if (_dirfd < 0) { \ - g_assert (!_pathid); \ - g_assert (_path[0] == '/'); \ - g_assert ( g_str_has_prefix (_path, "/proc/sys/") \ - || g_str_has_prefix (_path, "/sys/")); \ - } else { \ - g_assert_not_reached (); \ - } \ - } G_STMT_END +#define ASSERT_SYSCTL_ARGS(pathid, dirfd, path) \ + G_STMT_START \ + { \ + const char *const _pathid = (pathid); \ + const int _dirfd = (dirfd); \ + const char *const _path = (path); \ + \ + g_assert(_path &&_path[0]); \ + g_assert(!strstr(_path, "/../")); \ + if (_dirfd < 0) { \ + g_assert(!_pathid); \ + g_assert(_path[0] == '/'); \ + g_assert(g_str_has_prefix(_path, "/proc/sys/") || g_str_has_prefix(_path, "/sys/")); \ + } else { \ + g_assert_not_reached(); \ + } \ + } \ + G_STMT_END static gboolean -sysctl_set (NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value) +sysctl_set(NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform); - ASSERT_SYSCTL_ARGS (pathid, dirfd, path); + ASSERT_SYSCTL_ARGS(pathid, dirfd, path); - g_hash_table_insert (priv->options, g_strdup (path), g_strdup (value)); + g_hash_table_insert(priv->options, g_strdup(path), g_strdup(value)); - return TRUE; + return TRUE; } static char * -sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *path) +sysctl_get(NMPlatform *platform, const char *pathid, int dirfd, const char *path) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); - const char *v; + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform); + const char * v; - ASSERT_SYSCTL_ARGS (pathid, dirfd, path); + ASSERT_SYSCTL_ARGS(pathid, dirfd, path); - v = g_hash_table_lookup (priv->options, path); - if (!v) { - errno = ENOENT; - return NULL; - } + v = g_hash_table_lookup(priv->options, path); + if (!v) { + errno = ENOENT; + return NULL; + } - return g_strdup (v); + return g_strdup(v); } static NMFakePlatformLink * -link_get (NMPlatform *platform, int ifindex) +link_get(NMPlatform *platform, int ifindex) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); - NMFakePlatformLink *device; - int idx; + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform); + NMFakePlatformLink * device; + int idx; - if (ifindex <= 0) - g_return_val_if_reached (NULL); + if (ifindex <= 0) + g_return_val_if_reached(NULL); - idx = ifindex - 1; - if (idx >= priv->links->len) - goto not_found; + idx = ifindex - 1; + if (idx >= priv->links->len) + goto not_found; - device = &g_array_index (priv->links, NMFakePlatformLink, idx); - if (!device->obj) - goto not_found; + device = &g_array_index(priv->links, NMFakePlatformLink, idx); + if (!device->obj) + goto not_found; - g_assert (ifindex == NMP_OBJECT_CAST_LINK (device->obj)->ifindex); - g_assert (device->obj == nm_platform_link_get_obj (platform, ifindex, FALSE)); + g_assert(ifindex == NMP_OBJECT_CAST_LINK(device->obj)->ifindex); + g_assert(device->obj == nm_platform_link_get_obj(platform, ifindex, FALSE)); - return device; + return device; not_found: - _LOGD ("link not found: %d", ifindex); - return NULL; + _LOGD("link not found: %d", ifindex); + return NULL; } static void -link_add_prepare (NMPlatform *platform, - NMFakePlatformLink *device, - NMPObject *obj_tmp) +link_add_prepare(NMPlatform *platform, NMFakePlatformLink *device, NMPObject *obj_tmp) { - gboolean connected; - - /* we must clear the driver, because platform cache wants to set it */ - g_assert (obj_tmp->link.driver == g_intern_string (obj_tmp->link.driver)); - obj_tmp->link.driver = NULL; - - if (NM_IN_SET (obj_tmp->link.type, NM_LINK_TYPE_BRIDGE, - NM_LINK_TYPE_BOND)) { - connected = FALSE; - if (NM_FLAGS_HAS (obj_tmp->link.n_ifi_flags, IFF_UP)) { - NMPLookup lookup; - NMDedupMultiIter iter; - const NMPObject *slave_candidate = NULL; - - nmp_cache_iter_for_each (&iter, - nmp_cache_lookup (nm_platform_get_cache (platform), - nmp_lookup_init_obj_type (&lookup, - NMP_OBJECT_TYPE_LINK)), - &slave_candidate) { - if (nmp_cache_link_connected_for_slave (obj_tmp->link.ifindex, slave_candidate)) { - connected = TRUE; - break; - } - } - } - } else - connected = NM_FLAGS_HAS (obj_tmp->link.n_ifi_flags, IFF_UP); - - obj_tmp->link.n_ifi_flags = NM_FLAGS_ASSIGN (obj_tmp->link.n_ifi_flags, IFF_LOWER_UP, connected); - obj_tmp->link.connected = connected; + gboolean connected; + + /* we must clear the driver, because platform cache wants to set it */ + g_assert(obj_tmp->link.driver == g_intern_string(obj_tmp->link.driver)); + obj_tmp->link.driver = NULL; + + if (NM_IN_SET(obj_tmp->link.type, NM_LINK_TYPE_BRIDGE, NM_LINK_TYPE_BOND)) { + connected = FALSE; + if (NM_FLAGS_HAS(obj_tmp->link.n_ifi_flags, IFF_UP)) { + NMPLookup lookup; + NMDedupMultiIter iter; + const NMPObject *slave_candidate = NULL; + + nmp_cache_iter_for_each ( + &iter, + nmp_cache_lookup(nm_platform_get_cache(platform), + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK)), + &slave_candidate) { + if (nmp_cache_link_connected_for_slave(obj_tmp->link.ifindex, slave_candidate)) { + connected = TRUE; + break; + } + } + } + } else + connected = NM_FLAGS_HAS(obj_tmp->link.n_ifi_flags, IFF_UP); + + obj_tmp->link.n_ifi_flags = NM_FLAGS_ASSIGN(obj_tmp->link.n_ifi_flags, IFF_LOWER_UP, connected); + obj_tmp->link.connected = connected; } static NMFakePlatformLink * -link_add_pre (NMPlatform *platform, - const char *name, - NMLinkType type, - const void *address, - size_t address_len) +link_add_pre(NMPlatform *platform, + const char *name, + NMLinkType type, + const void *address, + size_t address_len) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); - NMFakePlatformLink *device; - int ifindex; - NMPObject *o; - NMPlatformLink *link; - gs_free char *ip6_lladdr = NULL; - - g_assert (!name || strlen (name) < IFNAMSIZ); - - g_array_set_size (priv->links, priv->links->len + 1); - device = &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1); - ifindex = priv->links->len; - - memset (device, 0, sizeof (*device)); - - o = nmp_object_new_link (ifindex); - link = NMP_OBJECT_CAST_LINK (o); - - ip6_lladdr = ifindex > 0 ? g_strdup_printf ("fe80::fa1e:%0x:%0x", ifindex / 256, ifindex % 256) : NULL; - - link->ifindex = name ? ifindex : 0; - link->type = type; - link->kind = g_intern_string (nm_link_type_to_string (type)); - link->initialized = TRUE; - if (name) - strcpy (link->name, name); - switch (link->type) { - case NM_LINK_TYPE_DUMMY: - link->n_ifi_flags = NM_FLAGS_SET (link->n_ifi_flags, IFF_NOARP); - break; - default: - link->n_ifi_flags = NM_FLAGS_UNSET (link->n_ifi_flags, IFF_NOARP); - break; - } - - o->_link.netlink.is_in_netlink = TRUE; - - if (address) { - g_assert (address_len > 0 && address_len <= sizeof (link->l_address.data)); - memcpy (link->l_address.data, address, address_len); - link->l_address.len = address_len; - } else - g_assert (address_len == 0); - - device->obj = o; - device->ip6_lladdr = *nmtst_inet6_from_string (ip6_lladdr); - - return device; + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform); + NMFakePlatformLink * device; + int ifindex; + NMPObject * o; + NMPlatformLink * link; + gs_free char * ip6_lladdr = NULL; + + g_assert(!name || strlen(name) < IFNAMSIZ); + + g_array_set_size(priv->links, priv->links->len + 1); + device = &g_array_index(priv->links, NMFakePlatformLink, priv->links->len - 1); + ifindex = priv->links->len; + + memset(device, 0, sizeof(*device)); + + o = nmp_object_new_link(ifindex); + link = NMP_OBJECT_CAST_LINK(o); + + ip6_lladdr = + ifindex > 0 ? g_strdup_printf("fe80::fa1e:%0x:%0x", ifindex / 256, ifindex % 256) : NULL; + + link->ifindex = name ? ifindex : 0; + link->type = type; + link->kind = g_intern_string(nm_link_type_to_string(type)); + link->initialized = TRUE; + if (name) + strcpy(link->name, name); + switch (link->type) { + case NM_LINK_TYPE_DUMMY: + link->n_ifi_flags = NM_FLAGS_SET(link->n_ifi_flags, IFF_NOARP); + break; + default: + link->n_ifi_flags = NM_FLAGS_UNSET(link->n_ifi_flags, IFF_NOARP); + break; + } + + o->_link.netlink.is_in_netlink = TRUE; + + if (address) { + g_assert(address_len > 0 && address_len <= sizeof(link->l_address.data)); + memcpy(link->l_address.data, address, address_len); + link->l_address.len = address_len; + } else + g_assert(address_len == 0); + + device->obj = o; + device->ip6_lladdr = *nmtst_inet6_from_string(ip6_lladdr); + + return device; } static int -link_add (NMPlatform *platform, - NMLinkType type, - const char *name, - int parent, - const void *address, - size_t address_len, - gconstpointer extra_data, - const NMPlatformLink **out_link) +link_add(NMPlatform * platform, + NMLinkType type, + const char * name, + int parent, + const void * address, + size_t address_len, + gconstpointer extra_data, + const NMPlatformLink **out_link) { - NMFakePlatformLink *device; - NMFakePlatformLink *device_veth = NULL; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - nm_auto_nmpobj const NMPObject *obj_old_veth = NULL; - nm_auto_nmpobj const NMPObject *obj_new_veth = NULL; - NMPCacheOpsType cache_op; - NMPCacheOpsType cache_op_veth = NMP_CACHE_OPS_UNCHANGED; - const char *veth_peer = NULL; - NMPObject *dev_obj; - NMPObject *dev_lnk = NULL; - - device = link_add_pre (platform, name, type, address, address_len); - - g_assert (device); - - dev_obj = (NMPObject *) device->obj; - - if (parent > 0) - dev_obj->link.parent = parent; - else - g_assert (parent == 0); - - g_assert ((parent != 0) == NM_IN_SET (type, NM_LINK_TYPE_VLAN)); - - switch (type) { - case NM_LINK_TYPE_VETH: - veth_peer = extra_data; - g_assert (veth_peer); - device_veth = link_add_pre (platform, veth_peer, type, NULL, 0); - break; - case NM_LINK_TYPE_VLAN: { - const NMPlatformLnkVlan *props = extra_data; - - g_assert (props); - - dev_lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, props); - break; - } - case NM_LINK_TYPE_VXLAN: { - const NMPlatformLnkVxlan *props = extra_data; - - g_assert (props); - - dev_lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, props); - break; - } - default: - g_assert (!extra_data); - break; - } - - if (dev_lnk) - dev_obj->_link.netlink.lnk = dev_lnk; - - link_add_prepare (platform, device, (NMPObject *) device->obj); - cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform), - (NMPObject *) device->obj, - FALSE, - &obj_old, &obj_new); - g_assert (cache_op == NMP_CACHE_OPS_ADDED); - nmp_object_unref (device->obj); - device->obj = nmp_object_ref (obj_new); - if (veth_peer) { - link_add_prepare (platform, device_veth, (NMPObject *) device_veth->obj); - cache_op_veth = nmp_cache_update_netlink (nm_platform_get_cache (platform), - (NMPObject *) device_veth->obj, - FALSE, - &obj_old_veth, &obj_new_veth); - g_assert (cache_op == NMP_CACHE_OPS_ADDED); - nmp_object_unref (device->obj); - device->obj = nmp_object_ref (obj_new); - } - - if (out_link) - *out_link = NMP_OBJECT_CAST_LINK (device->obj); - - link_changed (platform, device, cache_op, NULL); - if (veth_peer) - link_changed (platform, device_veth, cache_op_veth, NULL); - - return 0; + NMFakePlatformLink * device; + NMFakePlatformLink * device_veth = NULL; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + nm_auto_nmpobj const NMPObject *obj_old_veth = NULL; + nm_auto_nmpobj const NMPObject *obj_new_veth = NULL; + NMPCacheOpsType cache_op; + NMPCacheOpsType cache_op_veth = NMP_CACHE_OPS_UNCHANGED; + const char * veth_peer = NULL; + NMPObject * dev_obj; + NMPObject * dev_lnk = NULL; + + device = link_add_pre(platform, name, type, address, address_len); + + g_assert(device); + + dev_obj = (NMPObject *) device->obj; + + if (parent > 0) + dev_obj->link.parent = parent; + else + g_assert(parent == 0); + + g_assert((parent != 0) == NM_IN_SET(type, NM_LINK_TYPE_VLAN)); + + switch (type) { + case NM_LINK_TYPE_BRIDGE: + { + const NMPlatformLnkBridge *props = extra_data; + + g_assert(props); + + dev_lnk = nmp_object_new(NMP_OBJECT_TYPE_LNK_BRIDGE, props); + break; + } + case NM_LINK_TYPE_VETH: + veth_peer = extra_data; + g_assert(veth_peer); + device_veth = link_add_pre(platform, veth_peer, type, NULL, 0); + break; + case NM_LINK_TYPE_VLAN: + { + const NMPlatformLnkVlan *props = extra_data; + + g_assert(props); + + dev_lnk = nmp_object_new(NMP_OBJECT_TYPE_LNK_VLAN, props); + break; + } + case NM_LINK_TYPE_VXLAN: + { + const NMPlatformLnkVxlan *props = extra_data; + + g_assert(props); + + dev_lnk = nmp_object_new(NMP_OBJECT_TYPE_LNK_VXLAN, props); + break; + } + default: + g_assert(!extra_data); + break; + } + + if (dev_lnk) + dev_obj->_link.netlink.lnk = dev_lnk; + + link_add_prepare(platform, device, (NMPObject *) device->obj); + cache_op = nmp_cache_update_netlink(nm_platform_get_cache(platform), + (NMPObject *) device->obj, + FALSE, + &obj_old, + &obj_new); + g_assert(cache_op == NMP_CACHE_OPS_ADDED); + nmp_object_unref(device->obj); + device->obj = nmp_object_ref(obj_new); + if (veth_peer) { + link_add_prepare(platform, device_veth, (NMPObject *) device_veth->obj); + cache_op_veth = nmp_cache_update_netlink(nm_platform_get_cache(platform), + (NMPObject *) device_veth->obj, + FALSE, + &obj_old_veth, + &obj_new_veth); + g_assert(cache_op == NMP_CACHE_OPS_ADDED); + nmp_object_unref(device->obj); + device->obj = nmp_object_ref(obj_new); + } + + if (out_link) + *out_link = NMP_OBJECT_CAST_LINK(device->obj); + + link_changed(platform, device, cache_op, NULL); + if (veth_peer) + link_changed(platform, device_veth, cache_op_veth, NULL); + + return 0; } static NMFakePlatformLink * -link_add_one (NMPlatform *platform, - const char *name, - NMLinkType link_type, - void (*prepare_fcn) (NMPlatform *platform, NMFakePlatformLink *device, gconstpointer user_data), - gconstpointer user_data, - const NMPlatformLink **out_link) +link_add_one(NMPlatform *platform, + const char *name, + NMLinkType link_type, + void (*prepare_fcn)(NMPlatform * platform, + NMFakePlatformLink *device, + gconstpointer user_data), + gconstpointer user_data, + const NMPlatformLink **out_link) { - NMFakePlatformLink *device; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - NMPCacheOpsType cache_op; - int ifindex; + NMFakePlatformLink * device; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + NMPCacheOpsType cache_op; + int ifindex; - device = link_add_pre (platform, name, NM_LINK_TYPE_VLAN, NULL, 0); + device = link_add_pre(platform, name, NM_LINK_TYPE_VLAN, NULL, 0); - ifindex = NMP_OBJECT_CAST_LINK (device->obj)->ifindex; + ifindex = NMP_OBJECT_CAST_LINK(device->obj)->ifindex; - if (prepare_fcn) - prepare_fcn (platform, device, user_data); + if (prepare_fcn) + prepare_fcn(platform, device, user_data); - link_add_prepare (platform, device, (NMPObject *) device->obj); - cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform), - (NMPObject *) device->obj, - FALSE, - &obj_old, &obj_new); - g_assert (cache_op == NMP_CACHE_OPS_ADDED); - nmp_object_unref (device->obj); - device->obj = nmp_object_ref (obj_new); + link_add_prepare(platform, device, (NMPObject *) device->obj); + cache_op = nmp_cache_update_netlink(nm_platform_get_cache(platform), + (NMPObject *) device->obj, + FALSE, + &obj_old, + &obj_new); + g_assert(cache_op == NMP_CACHE_OPS_ADDED); + nmp_object_unref(device->obj); + device->obj = nmp_object_ref(obj_new); - link_changed (platform, device, cache_op, obj_old); + link_changed(platform, device, cache_op, obj_old); - device = link_get (platform, ifindex); - if (!device) - g_assert_not_reached (); + device = link_get(platform, ifindex); + if (!device) + g_assert_not_reached(); - NM_SET_OUT (out_link, NMP_OBJECT_CAST_LINK (device->obj)); - return device; + NM_SET_OUT(out_link, NMP_OBJECT_CAST_LINK(device->obj)); + return device; } static gboolean -link_delete (NMPlatform *platform, int ifindex) +link_delete(NMPlatform *platform, int ifindex) { - NMFakePlatformLink *device = link_get (platform, ifindex); - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_old2 = NULL; - NMPCacheOpsType cache_op; - - if (!device) - return FALSE; - - obj_old = g_steal_pointer (&device->obj); - - cache_op = nmp_cache_remove (nm_platform_get_cache (platform), - obj_old, - FALSE, - FALSE, - &obj_old2); - g_assert (cache_op == NMP_CACHE_OPS_REMOVED); - g_assert (obj_old2); - g_assert (obj_old == obj_old2); - - /* Remove addresses and routes which belong to the deleted interface */ - ipx_address_delete (platform, AF_INET, ifindex, NULL, NULL, NULL); - ipx_address_delete (platform, AF_INET6, ifindex, NULL, NULL, NULL); - ipx_route_delete (platform, AF_INET, ifindex, NULL); - ipx_route_delete (platform, AF_INET6, ifindex, NULL); - - nm_platform_cache_update_emit_signal (platform, - cache_op, - obj_old2, - NULL); - return TRUE; + NMFakePlatformLink * device = link_get(platform, ifindex); + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_old2 = NULL; + NMPCacheOpsType cache_op; + + if (!device) + return FALSE; + + obj_old = g_steal_pointer(&device->obj); + + cache_op = nmp_cache_remove(nm_platform_get_cache(platform), obj_old, FALSE, FALSE, &obj_old2); + g_assert(cache_op == NMP_CACHE_OPS_REMOVED); + g_assert(obj_old2); + g_assert(obj_old == obj_old2); + + /* Remove addresses and routes which belong to the deleted interface */ + ipx_address_delete(platform, AF_INET, ifindex, NULL, NULL, NULL); + ipx_address_delete(platform, AF_INET6, ifindex, NULL, NULL, NULL); + ipx_route_delete(platform, AF_INET, ifindex, NULL); + ipx_route_delete(platform, AF_INET6, ifindex, NULL); + + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old2, NULL); + return TRUE; } static void -link_set_obj (NMPlatform *platform, - NMFakePlatformLink *device, - NMPObject *obj_tmp) +link_set_obj(NMPlatform *platform, NMFakePlatformLink *device, NMPObject *obj_tmp) { - nm_auto_nmpobj const NMPObject *obj_new = NULL; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj NMPObject *obj_tmp_tmp = NULL; - NMPCacheOpsType cache_op; - - g_assert (device); - g_assert (NMP_OBJECT_GET_TYPE (device->obj) == NMP_OBJECT_TYPE_LINK); - - if (!obj_tmp) { - obj_tmp_tmp = nmp_object_clone (device->obj, FALSE); - obj_tmp = obj_tmp_tmp; - } - - g_assert (NMP_OBJECT_GET_TYPE (obj_tmp) == NMP_OBJECT_TYPE_LINK); - - link_add_prepare (platform, device, obj_tmp); - cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform), - obj_tmp, - FALSE, - &obj_old, &obj_new); - g_assert (NM_IN_SET (cache_op, NMP_CACHE_OPS_UNCHANGED, - NMP_CACHE_OPS_UPDATED)); - g_assert (obj_old == device->obj); - g_assert (obj_new); - - nmp_object_unref (device->obj); - device->obj = nmp_object_ref (obj_new); - - link_changed (platform, device, cache_op, obj_old); + nm_auto_nmpobj const NMPObject *obj_new = NULL; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj NMPObject *obj_tmp_tmp = NULL; + NMPCacheOpsType cache_op; + + g_assert(device); + g_assert(NMP_OBJECT_GET_TYPE(device->obj) == NMP_OBJECT_TYPE_LINK); + + if (!obj_tmp) { + obj_tmp_tmp = nmp_object_clone(device->obj, FALSE); + obj_tmp = obj_tmp_tmp; + } + + g_assert(NMP_OBJECT_GET_TYPE(obj_tmp) == NMP_OBJECT_TYPE_LINK); + + link_add_prepare(platform, device, obj_tmp); + cache_op = nmp_cache_update_netlink(nm_platform_get_cache(platform), + obj_tmp, + FALSE, + &obj_old, + &obj_new); + g_assert(NM_IN_SET(cache_op, NMP_CACHE_OPS_UNCHANGED, NMP_CACHE_OPS_UPDATED)); + g_assert(obj_old == device->obj); + g_assert(obj_new); + + nmp_object_unref(device->obj); + device->obj = nmp_object_ref(obj_new); + + link_changed(platform, device, cache_op, obj_old); } static void -link_set_flags (NMPlatform *platform, - NMFakePlatformLink *device, - guint n_ifi_flags) +link_set_flags(NMPlatform *platform, NMFakePlatformLink *device, guint n_ifi_flags) { - nm_auto_nmpobj NMPObject *obj_tmp = NULL; + nm_auto_nmpobj NMPObject *obj_tmp = NULL; - g_assert (device); - g_assert (NMP_OBJECT_GET_TYPE (device->obj) == NMP_OBJECT_TYPE_LINK); + g_assert(device); + g_assert(NMP_OBJECT_GET_TYPE(device->obj) == NMP_OBJECT_TYPE_LINK); - obj_tmp = nmp_object_clone (device->obj, FALSE); - obj_tmp->link.n_ifi_flags = n_ifi_flags; - link_set_obj (platform, device, obj_tmp); + obj_tmp = nmp_object_clone(device->obj, FALSE); + obj_tmp->link.n_ifi_flags = n_ifi_flags; + link_set_obj(platform, device, obj_tmp); } static void -link_changed (NMPlatform *platform, - NMFakePlatformLink *device, - NMPCacheOpsType cache_op, - const NMPObject *obj_old) +link_changed(NMPlatform * platform, + NMFakePlatformLink *device, + NMPCacheOpsType cache_op, + const NMPObject * obj_old) { - g_assert (device->obj); - - g_assert (!nmp_cache_link_connected_needs_toggle (nm_platform_get_cache (platform), - device->obj, NULL, NULL)); - - nm_platform_cache_update_emit_signal (platform, - cache_op, - obj_old, - device->obj); - - if (!IN6_IS_ADDR_UNSPECIFIED (&device->ip6_lladdr)) { - if (device->obj->link.connected) - ip6_address_add (platform, device->obj->link.ifindex, device->ip6_lladdr, 64, in6addr_any, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0); - else - ip6_address_delete (platform, device->obj->link.ifindex, device->ip6_lladdr, 64); - } - - if (device->obj->link.master) { - NMFakePlatformLink *master; - - master = link_get (platform, device->obj->link.master); - link_set_obj (platform, master, NULL); - } + g_assert(device->obj); + + g_assert(!nmp_cache_link_connected_needs_toggle(nm_platform_get_cache(platform), + device->obj, + NULL, + NULL)); + + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, device->obj); + + if (!IN6_IS_ADDR_UNSPECIFIED(&device->ip6_lladdr)) { + if (device->obj->link.connected) + ip6_address_add(platform, + device->obj->link.ifindex, + device->ip6_lladdr, + 64, + in6addr_any, + NM_PLATFORM_LIFETIME_PERMANENT, + NM_PLATFORM_LIFETIME_PERMANENT, + 0); + else + ip6_address_delete(platform, device->obj->link.ifindex, device->ip6_lladdr, 64); + } + + if (device->obj->link.master) { + NMFakePlatformLink *master; + + master = link_get(platform, device->obj->link.master); + link_set_obj(platform, master, NULL); + } } static gboolean -link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware) +link_set_up(NMPlatform *platform, int ifindex, gboolean *out_no_firmware) { - NMFakePlatformLink *device = link_get (platform, ifindex); + NMFakePlatformLink *device = link_get(platform, ifindex); - if (out_no_firmware) - *out_no_firmware = FALSE; + if (out_no_firmware) + *out_no_firmware = FALSE; - if (!device) { - _LOGE ("failure changing link: netlink error (No such device)"); - return FALSE; - } + if (!device) { + _LOGE("failure changing link: netlink error (No such device)"); + return FALSE; + } - link_set_flags (platform, - device, - NM_FLAGS_ASSIGN (device->obj->link.n_ifi_flags, IFF_UP, TRUE)); - return TRUE; + link_set_flags(platform, device, NM_FLAGS_ASSIGN(device->obj->link.n_ifi_flags, IFF_UP, TRUE)); + return TRUE; } static gboolean -link_set_down (NMPlatform *platform, int ifindex) +link_set_down(NMPlatform *platform, int ifindex) { - NMFakePlatformLink *device = link_get (platform, ifindex); + NMFakePlatformLink *device = link_get(platform, ifindex); - if (!device) { - _LOGE ("failure changing link: netlink error (No such device)"); - return FALSE; - } + if (!device) { + _LOGE("failure changing link: netlink error (No such device)"); + return FALSE; + } - link_set_flags (platform, - device, - NM_FLAGS_UNSET (device->obj->link.n_ifi_flags, IFF_UP)); - return TRUE; + link_set_flags(platform, device, NM_FLAGS_UNSET(device->obj->link.n_ifi_flags, IFF_UP)); + return TRUE; } static gboolean -link_set_arp (NMPlatform *platform, int ifindex) +link_set_arp(NMPlatform *platform, int ifindex) { - NMFakePlatformLink *device = link_get (platform, ifindex); + NMFakePlatformLink *device = link_get(platform, ifindex); - if (!device) { - _LOGE ("failure changing link: netlink error (No such device)"); - return FALSE; - } + if (!device) { + _LOGE("failure changing link: netlink error (No such device)"); + return FALSE; + } - link_set_flags (platform, - device, - NM_FLAGS_UNSET (device->obj->link.n_ifi_flags, IFF_NOARP)); - return TRUE; + link_set_flags(platform, device, NM_FLAGS_UNSET(device->obj->link.n_ifi_flags, IFF_NOARP)); + return TRUE; } static gboolean -link_set_noarp (NMPlatform *platform, int ifindex) +link_set_noarp(NMPlatform *platform, int ifindex) { - NMFakePlatformLink *device = link_get (platform, ifindex); + NMFakePlatformLink *device = link_get(platform, ifindex); - if (!device) { - _LOGE ("failure changing link: netlink error (No such device)"); - return FALSE; - } + if (!device) { + _LOGE("failure changing link: netlink error (No such device)"); + return FALSE; + } - link_set_flags (platform, - device, - NM_FLAGS_SET (device->obj->link.n_ifi_flags, IFF_NOARP)); - return TRUE; + link_set_flags(platform, device, NM_FLAGS_SET(device->obj->link.n_ifi_flags, IFF_NOARP)); + return TRUE; } static int -link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t len) +link_set_address(NMPlatform *platform, int ifindex, gconstpointer addr, size_t len) { - NMFakePlatformLink *device = link_get (platform, ifindex); - nm_auto_nmpobj NMPObject *obj_tmp = NULL; + NMFakePlatformLink *device = link_get(platform, ifindex); + nm_auto_nmpobj NMPObject *obj_tmp = NULL; - if ( len == 0 - || len > NM_UTILS_HWADDR_LEN_MAX - || !addr) - g_return_val_if_reached (-NME_BUG); + if (len == 0 || len > NM_UTILS_HWADDR_LEN_MAX || !addr) + g_return_val_if_reached(-NME_BUG); - if (!device) - return -NME_PL_EXISTS; + if (!device) + return -NME_PL_EXISTS; - obj_tmp = nmp_object_clone (device->obj, FALSE); - obj_tmp->link.l_address.len = len; - memset (obj_tmp->link.l_address.data, 0, sizeof (obj_tmp->link.l_address.data)); - memcpy (obj_tmp->link.l_address.data, addr, len); + obj_tmp = nmp_object_clone(device->obj, FALSE); + obj_tmp->link.l_address.len = len; + memset(obj_tmp->link.l_address.data, 0, sizeof(obj_tmp->link.l_address.data)); + memcpy(obj_tmp->link.l_address.data, addr, len); - link_set_obj (platform, device, obj_tmp); - return 0; + link_set_obj(platform, device, obj_tmp); + return 0; } static int -link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu) +link_set_mtu(NMPlatform *platform, int ifindex, guint32 mtu) { - NMFakePlatformLink *device = link_get (platform, ifindex); - nm_auto_nmpobj NMPObject *obj_tmp = NULL; - - if (!device) { - _LOGE ("failure changing link: netlink error (No such device)"); - return -NME_PL_EXISTS; - } - - obj_tmp = nmp_object_clone (device->obj, FALSE); - obj_tmp->link.mtu = mtu; - link_set_obj (platform, device, obj_tmp); - return 0; + NMFakePlatformLink *device = link_get(platform, ifindex); + nm_auto_nmpobj NMPObject *obj_tmp = NULL; + + if (!device) { + _LOGE("failure changing link: netlink error (No such device)"); + return -NME_PL_EXISTS; + } + + obj_tmp = nmp_object_clone(device->obj, FALSE); + obj_tmp->link.mtu = mtu; + link_set_obj(platform, device, obj_tmp); + return 0; } static gboolean -link_get_driver_info (NMPlatform *platform, - int ifindex, - char **out_driver_name, - char **out_driver_version, - char **out_fw_version) +link_get_driver_info(NMPlatform *platform, + int ifindex, + char ** out_driver_name, + char ** out_driver_version, + char ** out_fw_version) { - if (out_driver_name) - *out_driver_name = NULL; - if (out_driver_version) - *out_driver_version = NULL; - if (out_fw_version) - *out_fw_version = NULL; - - return TRUE; + if (out_driver_name) + *out_driver_name = NULL; + if (out_driver_version) + *out_driver_version = NULL; + if (out_fw_version) + *out_fw_version = NULL; + + return TRUE; } static gboolean -link_supports_carrier_detect (NMPlatform *platform, int ifindex) +link_supports_carrier_detect(NMPlatform *platform, int ifindex) { - NMFakePlatformLink *device = link_get (platform, ifindex); + NMFakePlatformLink *device = link_get(platform, ifindex); - if (!device) - return FALSE; + if (!device) + return FALSE; - switch (device->obj->link.type) { - case NM_LINK_TYPE_DUMMY: - return FALSE; - default: - return TRUE; - } + switch (device->obj->link.type) { + case NM_LINK_TYPE_DUMMY: + return FALSE; + default: + return TRUE; + } } static gboolean -link_supports_vlans (NMPlatform *platform, int ifindex) +link_supports_vlans(NMPlatform *platform, int ifindex) { - NMFakePlatformLink *device = link_get (platform, ifindex); + NMFakePlatformLink *device = link_get(platform, ifindex); - if (!device) - return FALSE; + if (!device) + return FALSE; - switch (device->obj->link.type) { - case NM_LINK_TYPE_LOOPBACK: - return FALSE; - default: - return TRUE; - } + switch (device->obj->link.type) { + case NM_LINK_TYPE_LOOPBACK: + return FALSE; + default: + return TRUE; + } } static gboolean -link_supports_sriov (NMPlatform *platform, int ifindex) +link_supports_sriov(NMPlatform *platform, int ifindex) { - NMFakePlatformLink *device = link_get (platform, ifindex); + NMFakePlatformLink *device = link_get(platform, ifindex); - if (!device) - return FALSE; + if (!device) + return FALSE; - switch (device->obj->link.type) { - case NM_LINK_TYPE_LOOPBACK: - return FALSE; - default: - return TRUE; - } + switch (device->obj->link.type) { + case NM_LINK_TYPE_LOOPBACK: + return FALSE; + default: + return TRUE; + } } static gboolean -link_enslave (NMPlatform *platform, int master, int slave) +link_enslave(NMPlatform *platform, int master, int slave) { - NMFakePlatformLink *device = link_get (platform, slave); - NMFakePlatformLink *master_device = link_get (platform, master); + NMFakePlatformLink *device = link_get(platform, slave); + NMFakePlatformLink *master_device = link_get(platform, master); - g_return_val_if_fail (device, FALSE); - g_return_val_if_fail (master_device, FALSE); + g_return_val_if_fail(device, FALSE); + g_return_val_if_fail(master_device, FALSE); - if (device->obj->link.master != master) { - nm_auto_nmpobj NMPObject *obj_tmp = NULL; + if (device->obj->link.master != master) { + nm_auto_nmpobj NMPObject *obj_tmp = NULL; - obj_tmp = nmp_object_clone (device->obj, FALSE); - obj_tmp->link.master = master; - if (NM_IN_SET (master_device->obj->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) - obj_tmp->link.n_ifi_flags = NM_FLAGS_SET (device->obj->link.n_ifi_flags, IFF_UP); - link_set_obj (platform, device, obj_tmp); - } + obj_tmp = nmp_object_clone(device->obj, FALSE); + obj_tmp->link.master = master; + if (NM_IN_SET(master_device->obj->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) + obj_tmp->link.n_ifi_flags = NM_FLAGS_SET(device->obj->link.n_ifi_flags, IFF_UP); + link_set_obj(platform, device, obj_tmp); + } - return TRUE; + return TRUE; } static gboolean -link_release (NMPlatform *platform, int master_idx, int slave_idx) +link_release(NMPlatform *platform, int master_idx, int slave_idx) { - NMFakePlatformLink *master = link_get (platform, master_idx); - NMFakePlatformLink *slave = link_get (platform, slave_idx); - nm_auto_nmpobj NMPObject *obj_tmp = NULL; + NMFakePlatformLink *master = link_get(platform, master_idx); + NMFakePlatformLink *slave = link_get(platform, slave_idx); + nm_auto_nmpobj NMPObject *obj_tmp = NULL; - g_return_val_if_fail (master, FALSE); - g_return_val_if_fail (slave, FALSE); + g_return_val_if_fail(master, FALSE); + g_return_val_if_fail(slave, FALSE); - if (slave->obj->link.master != master->obj->link.ifindex) - return FALSE; + if (slave->obj->link.master != master->obj->link.ifindex) + return FALSE; - obj_tmp = nmp_object_clone (slave->obj, FALSE); - obj_tmp->link.master = 0; - link_set_obj (platform, slave, obj_tmp); - return TRUE; + obj_tmp = nmp_object_clone(slave->obj, FALSE); + obj_tmp->link.master = 0; + link_set_obj(platform, slave, obj_tmp); + return TRUE; } static gboolean -link_vlan_change (NMPlatform *platform, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map) +link_vlan_change(NMPlatform * platform, + int ifindex, + NMVlanFlags flags_mask, + NMVlanFlags flags_set, + gboolean ingress_reset_all, + const NMVlanQosMapping *ingress_map, + gsize n_ingress_map, + gboolean egress_reset_all, + const NMVlanQosMapping *egress_map, + gsize n_egress_map) { - return FALSE; + return FALSE; } struct infiniband_add_data { - int parent; - int p_key; + int parent; + int p_key; }; static void -_infiniband_add_prepare (NMPlatform *platform, - NMFakePlatformLink *device, - gconstpointer user_data) +_infiniband_add_prepare(NMPlatform *platform, NMFakePlatformLink *device, gconstpointer user_data) { - const struct infiniband_add_data *d = user_data; - NMPObject *obj_tmp; - NMPObject *lnk; + const struct infiniband_add_data *d = user_data; + NMPObject * obj_tmp; + NMPObject * lnk; - obj_tmp = (NMPObject *) device->obj; + obj_tmp = (NMPObject *) device->obj; - lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL); - lnk->lnk_infiniband.p_key = d->p_key; - lnk->lnk_infiniband.mode = "datagram"; + lnk = nmp_object_new(NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL); + lnk->lnk_infiniband.p_key = d->p_key; + lnk->lnk_infiniband.mode = "datagram"; - obj_tmp->link.parent = d->parent; - obj_tmp->_link.netlink.lnk = lnk; + obj_tmp->link.parent = d->parent; + obj_tmp->_link.netlink.lnk = lnk; } static gboolean -infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link) +infiniband_partition_add(NMPlatform * platform, + int parent, + int p_key, + const NMPlatformLink **out_link) { - NMFakePlatformLink *parent_device; - char name[IFNAMSIZ]; - const struct infiniband_add_data d = { - .parent = parent, - .p_key = p_key, - }; + NMFakePlatformLink * parent_device; + char name[IFNAMSIZ]; + const struct infiniband_add_data d = { + .parent = parent, + .p_key = p_key, + }; - parent_device = link_get (platform, parent); - g_return_val_if_fail (parent_device != NULL, FALSE); + parent_device = link_get(platform, parent); + g_return_val_if_fail(parent_device != NULL, FALSE); - nm_utils_new_infiniband_name (name, parent_device->obj->link.name, p_key); + nm_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key); - link_add_one (platform, name, NM_LINK_TYPE_INFINIBAND, - _infiniband_add_prepare, &d, out_link); - return TRUE; + link_add_one(platform, name, NM_LINK_TYPE_INFINIBAND, _infiniband_add_prepare, &d, out_link); + return TRUE; } static gboolean -infiniband_partition_delete (NMPlatform *platform, int parent, int p_key) +infiniband_partition_delete(NMPlatform *platform, int parent, int p_key) { - NMFakePlatformLink *parent_device; - gs_free char *name = NULL; + NMFakePlatformLink *parent_device; + gs_free char * name = NULL; - parent_device = link_get (platform, parent); - g_return_val_if_fail (parent_device != NULL, FALSE); + parent_device = link_get(platform, parent); + g_return_val_if_fail(parent_device != NULL, FALSE); - nm_utils_new_infiniband_name (name, parent_device->obj->link.name, p_key); - return link_delete (platform, nm_platform_link_get_ifindex (platform, name)); + nm_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key); + return link_delete(platform, nm_platform_link_get_ifindex(platform, name)); } static gboolean -wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) +wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) { - NMFakePlatformLink *device = link_get (platform, ifindex); - - g_return_val_if_fail (device, FALSE); - - if (device->obj->link.type != NM_LINK_TYPE_WIFI) - return FALSE; - - if (caps) { - *caps = ( NM_WIFI_DEVICE_CAP_CIPHER_WEP40 - | NM_WIFI_DEVICE_CAP_CIPHER_WEP104 - | NM_WIFI_DEVICE_CAP_CIPHER_TKIP - | NM_WIFI_DEVICE_CAP_CIPHER_CCMP - | NM_WIFI_DEVICE_CAP_WPA - | NM_WIFI_DEVICE_CAP_RSN - | NM_WIFI_DEVICE_CAP_AP - | NM_WIFI_DEVICE_CAP_ADHOC); - } - return TRUE; + NMFakePlatformLink *device = link_get(platform, ifindex); + + g_return_val_if_fail(device, FALSE); + + if (device->obj->link.type != NM_LINK_TYPE_WIFI) + return FALSE; + + if (caps) { + *caps = (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104 + | NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP + | NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN | NM_WIFI_DEVICE_CAP_AP + | NM_WIFI_DEVICE_CAP_ADHOC); + } + return TRUE; } static gboolean -wifi_get_bssid (NMPlatform *platform, int ifindex, guint8 *bssid) +wifi_get_bssid(NMPlatform *platform, int ifindex, guint8 *bssid) { - return FALSE; + return FALSE; } static guint32 -wifi_get_frequency (NMPlatform *platform, int ifindex) +wifi_get_frequency(NMPlatform *platform, int ifindex) { - return 0; + return 0; } static int -wifi_get_quality (NMPlatform *platform, int ifindex) +wifi_get_quality(NMPlatform *platform, int ifindex) { - return 0; + return 0; } static guint32 -wifi_get_rate (NMPlatform *platform, int ifindex) +wifi_get_rate(NMPlatform *platform, int ifindex) { - return 0; + return 0; } static NM80211Mode -wifi_get_mode (NMPlatform *platform, int ifindex) +wifi_get_mode(NMPlatform *platform, int ifindex) { - return NM_802_11_MODE_UNKNOWN; + return NM_802_11_MODE_UNKNOWN; } static void -wifi_set_mode (NMPlatform *platform, int ifindex, NM80211Mode mode) +wifi_set_mode(NMPlatform *platform, int ifindex, NM80211Mode mode) { - ; + ; } static guint32 -wifi_find_frequency (NMPlatform *platform, int ifindex, const guint32 *freqs) +wifi_find_frequency(NMPlatform *platform, int ifindex, const guint32 *freqs) { - return freqs[0]; + return freqs[0]; } static void -wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean running) -{ -} +wifi_indicate_addressing_running(NMPlatform *platform, int ifindex, gboolean running) +{} static guint32 -mesh_get_channel (NMPlatform *platform, int ifindex) +mesh_get_channel(NMPlatform *platform, int ifindex) { - return 0; + return 0; } static gboolean -mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel) +mesh_set_channel(NMPlatform *platform, int ifindex, guint32 channel) { - return FALSE; + return FALSE; } static gboolean -mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) +mesh_set_ssid(NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) { - return FALSE; + return FALSE; } /*****************************************************************************/ static gboolean -ipx_address_add (NMPlatform *platform, int addr_family, const NMPlatformObject *address) +ipx_address_add(NMPlatform *platform, int addr_family, const NMPlatformObject *address) { - nm_auto_nmpobj NMPObject *obj = NULL; - NMPCacheOpsType cache_op; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - NMPCache *cache = nm_platform_get_cache (platform); - - g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - - obj = nmp_object_new (addr_family == AF_INET - ? NMP_OBJECT_TYPE_IP4_ADDRESS - : NMP_OBJECT_TYPE_IP6_ADDRESS, - address); - - cache_op = nmp_cache_update_netlink (cache, obj, FALSE, &obj_old, &obj_new); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); - return TRUE; + nm_auto_nmpobj NMPObject *obj = NULL; + NMPCacheOpsType cache_op; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + NMPCache * cache = nm_platform_get_cache(platform); + + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + obj = nmp_object_new(addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ADDRESS + : NMP_OBJECT_TYPE_IP6_ADDRESS, + address); + + cache_op = nmp_cache_update_netlink(cache, obj, FALSE, &obj_old, &obj_new); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); + return TRUE; } static gboolean -ip4_address_add (NMPlatform *platform, - int ifindex, - in_addr_t addr, - guint8 plen, - in_addr_t peer_addr, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) +ip4_address_add(NMPlatform *platform, + int ifindex, + in_addr_t addr, + guint8 plen, + in_addr_t peer_addr, + in_addr_t broadcast_address, + guint32 lifetime, + guint32 preferred, + guint32 flags, + const char *label) { - NMPlatformIP4Address address; - - address = (NMPlatformIP4Address) { - .addr_source = NM_IP_CONFIG_SOURCE_KERNEL, - .ifindex = ifindex, - .address = addr, - .plen = plen, - .peer_address = peer_addr, - .broadcast_address = broadcast_address, - .use_ip4_broadcast_address = TRUE, - .timestamp = nm_utils_get_monotonic_timestamp_sec (), - .lifetime = lifetime, - .preferred = preferred, - .n_ifa_flags = flags, - }; - if (label) - g_strlcpy (address.label, label, sizeof (address.label)); - - return ipx_address_add (platform, AF_INET, (const NMPlatformObject *) &address); + NMPlatformIP4Address address; + + address = (NMPlatformIP4Address){ + .addr_source = NM_IP_CONFIG_SOURCE_KERNEL, + .ifindex = ifindex, + .address = addr, + .plen = plen, + .peer_address = peer_addr, + .broadcast_address = broadcast_address, + .use_ip4_broadcast_address = TRUE, + .timestamp = nm_utils_get_monotonic_timestamp_sec(), + .lifetime = lifetime, + .preferred = preferred, + .n_ifa_flags = flags, + }; + if (label) + g_strlcpy(address.label, label, sizeof(address.label)); + + return ipx_address_add(platform, AF_INET, (const NMPlatformObject *) &address); } static gboolean -ip6_address_add (NMPlatform *platform, - int ifindex, - struct in6_addr addr, - guint8 plen, - struct in6_addr peer_addr, - guint32 lifetime, - guint32 preferred, - guint32 flags) +ip6_address_add(NMPlatform * platform, + int ifindex, + struct in6_addr addr, + guint8 plen, + struct in6_addr peer_addr, + guint32 lifetime, + guint32 preferred, + guint32 flags) { - NMPlatformIP6Address address; - - memset (&address, 0, sizeof (address)); - address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; - address.ifindex = ifindex; - address.address = addr; - address.peer_address = (IN6_IS_ADDR_UNSPECIFIED (&peer_addr) || IN6_ARE_ADDR_EQUAL (&addr, &peer_addr)) ? in6addr_any : peer_addr; - address.plen = plen; - address.timestamp = nm_utils_get_monotonic_timestamp_sec (); - address.lifetime = lifetime; - address.preferred = preferred; - address.n_ifa_flags = flags; - - return ipx_address_add (platform, AF_INET6, (const NMPlatformObject *) &address); + NMPlatformIP6Address address; + + memset(&address, 0, sizeof(address)); + address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; + address.ifindex = ifindex; + address.address = addr; + address.peer_address = + (IN6_IS_ADDR_UNSPECIFIED(&peer_addr) || IN6_ARE_ADDR_EQUAL(&addr, &peer_addr)) ? in6addr_any + : peer_addr; + address.plen = plen; + address.timestamp = nm_utils_get_monotonic_timestamp_sec(); + address.lifetime = lifetime; + address.preferred = preferred; + address.n_ifa_flags = flags; + + return ipx_address_add(platform, AF_INET6, (const NMPlatformObject *) &address); } static gboolean -ipx_address_delete (NMPlatform *platform, - int addr_family, - int ifindex, - gconstpointer addr, - const guint8 *plen, - gconstpointer peer_addr) +ipx_address_delete(NMPlatform * platform, + int addr_family, + int ifindex, + gconstpointer addr, + const guint8 *plen, + gconstpointer peer_addr) { - gs_unref_ptrarray GPtrArray *objs = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - NMDedupMultiIter iter; - const NMPObject *o = NULL; - guint i; - guint32 peer_addr_i; - - g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - - peer_addr_i = peer_addr ? *((guint32 *) peer_addr) : 0; - - nmp_cache_iter_for_each (&iter, - nm_platform_lookup_object (platform, - addr_family == AF_INET - ? NMP_OBJECT_TYPE_IP4_ADDRESS - : NMP_OBJECT_TYPE_IP6_ADDRESS, - 0), - &o) { - const NMPObject *obj_old = NULL; - - if (addr_family == AF_INET) { - const NMPlatformIP4Address *address = NMP_OBJECT_CAST_IP4_ADDRESS (o); - - if ( address->ifindex != ifindex - || (addr && address->address != *((guint32 *) addr)) - || (plen && address->plen != *plen) - || ( peer_addr - && (((peer_addr_i ^ address->peer_address) & _nm_utils_ip4_prefix_to_netmask (address->plen)) != 0))) - continue; - } else { - const NMPlatformIP6Address *address = NMP_OBJECT_CAST_IP6_ADDRESS (o); - - g_assert (!peer_addr); - if ( address->ifindex != ifindex - || (addr && !IN6_ARE_ADDR_EQUAL (&address->address, addr)) - || (plen && address->plen != *plen)) - continue; - } - - if (nmp_cache_remove (nm_platform_get_cache (platform), - o, - TRUE, - FALSE, - &obj_old) != NMP_CACHE_OPS_REMOVED) - g_assert_not_reached (); - g_assert (obj_old); - g_ptr_array_add (objs, (gpointer) obj_old); - } - - for (i = 0; i < objs->len; i++) { - nm_platform_cache_update_emit_signal (platform, - NMP_CACHE_OPS_REMOVED, - objs->pdata[i], - NULL); - } - return TRUE; + gs_unref_ptrarray GPtrArray *objs = + g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + NMDedupMultiIter iter; + const NMPObject *o = NULL; + guint i; + guint32 peer_addr_i; + + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + peer_addr_i = peer_addr ? *((guint32 *) peer_addr) : 0; + + nmp_cache_iter_for_each (&iter, + nm_platform_lookup_object(platform, + addr_family == AF_INET + ? NMP_OBJECT_TYPE_IP4_ADDRESS + : NMP_OBJECT_TYPE_IP6_ADDRESS, + 0), + &o) { + const NMPObject *obj_old = NULL; + + if (addr_family == AF_INET) { + const NMPlatformIP4Address *address = NMP_OBJECT_CAST_IP4_ADDRESS(o); + + if (address->ifindex != ifindex || (addr && address->address != *((guint32 *) addr)) + || (plen && address->plen != *plen) + || (peer_addr + && (((peer_addr_i ^ address->peer_address) + & _nm_utils_ip4_prefix_to_netmask(address->plen)) + != 0))) + continue; + } else { + const NMPlatformIP6Address *address = NMP_OBJECT_CAST_IP6_ADDRESS(o); + + g_assert(!peer_addr); + if (address->ifindex != ifindex + || (addr && !IN6_ARE_ADDR_EQUAL(&address->address, addr)) + || (plen && address->plen != *plen)) + continue; + } + + if (nmp_cache_remove(nm_platform_get_cache(platform), o, TRUE, FALSE, &obj_old) + != NMP_CACHE_OPS_REMOVED) + g_assert_not_reached(); + g_assert(obj_old); + g_ptr_array_add(objs, (gpointer) obj_old); + } + + for (i = 0; i < objs->len; i++) { + nm_platform_cache_update_emit_signal(platform, NMP_CACHE_OPS_REMOVED, objs->pdata[i], NULL); + } + return TRUE; } static gboolean -ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address) +ip4_address_delete(NMPlatform *platform, + int ifindex, + in_addr_t addr, + guint8 plen, + in_addr_t peer_address) { - return ipx_address_delete (platform, AF_INET, ifindex, &addr, &plen, &peer_address); + return ipx_address_delete(platform, AF_INET, ifindex, &addr, &plen, &peer_address); } static gboolean -ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen) +ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen) { - return ipx_address_delete (platform, AF_INET6, ifindex, &addr, &plen, NULL); + return ipx_address_delete(platform, AF_INET6, ifindex, &addr, &plen, NULL); } /*****************************************************************************/ static gboolean -ipx_route_delete (NMPlatform *platform, - int addr_family, - int ifindex, - const NMPObject *obj) +ipx_route_delete(NMPlatform *platform, int addr_family, int ifindex, const NMPObject *obj) { - gs_unref_ptrarray GPtrArray *objs = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - NMDedupMultiIter iter; - const NMPObject *o = NULL; - guint i; - NMPObjectType obj_type; - - if (addr_family == AF_UNSPEC) { - g_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); - g_assert (ifindex == -1); - ifindex = NMP_OBJECT_CAST_IP_ROUTE (obj)->ifindex; - obj_type = NMP_OBJECT_GET_TYPE (obj); - } else { - g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - g_assert (!obj); - g_assert (ifindex > 0); - obj_type = addr_family == AF_INET - ? NMP_OBJECT_TYPE_IP4_ROUTE - : NMP_OBJECT_TYPE_IP6_ROUTE; - } - - nmp_cache_iter_for_each (&iter, - nm_platform_lookup_object (platform, - obj_type, - ifindex), - &o) { - const NMPObject *obj_old = NULL; - - if (obj) { - if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) { - const NMPlatformIP4Route *route = NMP_OBJECT_CAST_IP4_ROUTE (o); - const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (obj); - - if ( route->network != r->network - || route->plen != r->plen - || route->metric != r->metric) - continue; - } else { - const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE (o); - const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (obj); - - if ( !IN6_ARE_ADDR_EQUAL (&route->network, &r->network) - || route->plen != r->plen - || route->metric != r->metric) - continue; - } - } - - if (nmp_cache_remove (nm_platform_get_cache (platform), - o, - TRUE, - FALSE, - &obj_old) != NMP_CACHE_OPS_REMOVED) - g_assert_not_reached (); - g_assert (obj_old); - g_ptr_array_add (objs, (gpointer) obj_old); - } - - for (i = 0; i < objs->len; i++) { - nm_platform_cache_update_emit_signal (platform, - NMP_CACHE_OPS_REMOVED, - objs->pdata[i], - NULL); - } - return TRUE; + gs_unref_ptrarray GPtrArray *objs = + g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + NMDedupMultiIter iter; + const NMPObject *o = NULL; + guint i; + NMPObjectType obj_type; + + if (addr_family == AF_UNSPEC) { + g_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE)); + g_assert(ifindex == -1); + ifindex = NMP_OBJECT_CAST_IP_ROUTE(obj)->ifindex; + obj_type = NMP_OBJECT_GET_TYPE(obj); + } else { + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + g_assert(!obj); + g_assert(ifindex > 0); + obj_type = addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE; + } + + nmp_cache_iter_for_each (&iter, nm_platform_lookup_object(platform, obj_type, ifindex), &o) { + const NMPObject *obj_old = NULL; + + if (obj) { + if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) { + const NMPlatformIP4Route *route = NMP_OBJECT_CAST_IP4_ROUTE(o); + const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE(obj); + + if (route->network != r->network || route->plen != r->plen + || route->metric != r->metric) + continue; + } else { + const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE(o); + const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE(obj); + + if (!IN6_ARE_ADDR_EQUAL(&route->network, &r->network) || route->plen != r->plen + || route->metric != r->metric) + continue; + } + } + + if (nmp_cache_remove(nm_platform_get_cache(platform), o, TRUE, FALSE, &obj_old) + != NMP_CACHE_OPS_REMOVED) + g_assert_not_reached(); + g_assert(obj_old); + g_ptr_array_add(objs, (gpointer) obj_old); + } + + for (i = 0; i < objs->len; i++) { + nm_platform_cache_update_emit_signal(platform, NMP_CACHE_OPS_REMOVED, objs->pdata[i], NULL); + } + return TRUE; } static gboolean -object_delete (NMPlatform *platform, const NMPObject *obj) +object_delete(NMPlatform *platform, const NMPObject *obj) { - g_assert (NM_IS_FAKE_PLATFORM (platform)); - g_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); + g_assert(NM_IS_FAKE_PLATFORM(platform)); + g_assert( + NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - return ipx_route_delete (platform, AF_UNSPEC, -1, obj); + return ipx_route_delete(platform, AF_UNSPEC, -1, obj); } static int -ip_route_add (NMPlatform *platform, - NMPNlmFlags flags, - int addr_family, - const NMPlatformIPRoute *route) +ip_route_add(NMPlatform * platform, + NMPNlmFlags flags, + int addr_family, + const NMPlatformIPRoute *route) { - NMDedupMultiIter iter; - nm_auto_nmpobj NMPObject *obj = NULL; - NMPCacheOpsType cache_op; - const NMPObject *o = NULL; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - nm_auto_nmpobj const NMPObject *obj_replace = NULL; - NMPCache *cache = nm_platform_get_cache (platform); - gboolean has_gateway = FALSE; - NMPlatformIPRoute *r = NULL; - NMPlatformIP4Route *r4 = NULL; - NMPlatformIP6Route *r6 = NULL; - gboolean has_same_weak_id; - gboolean only_dirty; - guint16 nlmsgflags; - - g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - - flags = NM_FLAGS_UNSET (flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE); - - /* currently, only replace is implemented. */ - g_assert (flags == NMP_NLM_FLAG_REPLACE); - - obj = nmp_object_new (addr_family == AF_INET - ? NMP_OBJECT_TYPE_IP4_ROUTE - : NMP_OBJECT_TYPE_IP6_ROUTE, - (const NMPlatformObject *) route); - r = NMP_OBJECT_CAST_IP_ROUTE (obj); - nm_platform_ip_route_normalize (addr_family, r); - - switch (addr_family) { - case AF_INET: - r4 = NMP_OBJECT_CAST_IP4_ROUTE (obj); - if (r4->gateway) - has_gateway = TRUE; - break; - case AF_INET6: - r6 = NMP_OBJECT_CAST_IP6_ROUTE (obj); - if (!IN6_IS_ADDR_UNSPECIFIED (&r6->gateway)) - has_gateway = TRUE; - break; - default: - nm_assert_not_reached (); - } - - if (has_gateway) { - gboolean has_route_to_gw = FALSE; - - nmp_cache_iter_for_each (&iter, - nm_platform_lookup_object (platform, - NMP_OBJECT_GET_TYPE (obj), - 0), - &o) { - if (addr_family == AF_INET) { - const NMPlatformIP4Route *item = NMP_OBJECT_CAST_IP4_ROUTE (o); - guint32 n = nm_utils_ip4_address_clear_host_address (item->network, item->plen); - guint32 g = nm_utils_ip4_address_clear_host_address (r4->gateway, item->plen); - - if ( r->ifindex == item->ifindex - && n == g) { - has_route_to_gw = TRUE; - break; - } - } else { - const NMPlatformIP6Route *item = NMP_OBJECT_CAST_IP6_ROUTE (o); - - if ( r->ifindex == item->ifindex - && nm_utils_ip6_address_same_prefix (&r6->gateway, &item->network, item->plen)) { - has_route_to_gw = TRUE; - break; - } - } - } - if (!has_route_to_gw) { - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - if (addr_family == AF_INET) { - nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable", - r->ifindex, _nm_utils_inet4_ntop (r4->network, sbuf), r->plen, r->metric); - } else { - nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable", - r->ifindex, _nm_utils_inet6_ntop (&r6->network, sbuf), r->plen, r->metric); - } - return -NME_UNSPEC; - } - } - - has_same_weak_id = FALSE; - nmp_cache_iter_for_each (&iter, - nm_platform_lookup_all (platform, - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - obj), - &o) { - if (addr_family == AF_INET) { - if (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (o), r4, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0) - continue; - } else { - if (nm_platform_ip6_route_cmp (NMP_OBJECT_CAST_IP6_ROUTE (o), r6, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0) - continue; - } - has_same_weak_id = TRUE; - } - - nlmsgflags = 0; - if (has_same_weak_id) { - switch (flags) { - case NMP_NLM_FLAG_REPLACE: - nlmsgflags = NLM_F_REPLACE; - break; - default: - g_assert_not_reached (); - break; - } - } - - /* we manipulate the cache the same was as NMLinuxPlatform does it. */ - cache_op = nmp_cache_update_netlink_route (cache, - obj, - FALSE, - nlmsgflags, - &obj_old, - &obj_new, - &obj_replace, - NULL); - only_dirty = FALSE; - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - if (obj_replace) { - const NMDedupMultiEntry *entry_replace; - - entry_replace = nmp_cache_lookup_entry (cache, obj_replace); - nm_assert (entry_replace && entry_replace->obj == obj_replace); - nm_dedup_multi_entry_set_dirty (entry_replace, TRUE); - only_dirty = TRUE; - } - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); - } - - if (obj_replace) { - cache_op = nmp_cache_remove (cache, obj_replace, TRUE, only_dirty, NULL); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - nm_assert (cache_op == NMP_CACHE_OPS_REMOVED); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_replace, NULL); - } - } - - return 0; + NMDedupMultiIter iter; + nm_auto_nmpobj NMPObject *obj = NULL; + NMPCacheOpsType cache_op; + const NMPObject * o = NULL; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + nm_auto_nmpobj const NMPObject *obj_replace = NULL; + NMPCache * cache = nm_platform_get_cache(platform); + gboolean has_gateway = FALSE; + NMPlatformIPRoute * r = NULL; + NMPlatformIP4Route * r4 = NULL; + NMPlatformIP6Route * r6 = NULL; + gboolean has_same_weak_id; + gboolean only_dirty; + guint16 nlmsgflags; + + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + flags = NM_FLAGS_UNSET(flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE); + + /* currently, only replace is implemented. */ + g_assert(flags == NMP_NLM_FLAG_REPLACE); + + obj = nmp_object_new(addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ROUTE + : NMP_OBJECT_TYPE_IP6_ROUTE, + (const NMPlatformObject *) route); + r = NMP_OBJECT_CAST_IP_ROUTE(obj); + nm_platform_ip_route_normalize(addr_family, r); + + switch (addr_family) { + case AF_INET: + r4 = NMP_OBJECT_CAST_IP4_ROUTE(obj); + if (r4->gateway) + has_gateway = TRUE; + break; + case AF_INET6: + r6 = NMP_OBJECT_CAST_IP6_ROUTE(obj); + if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway)) + has_gateway = TRUE; + break; + default: + nm_assert_not_reached(); + } + + if (has_gateway) { + gboolean has_route_to_gw = FALSE; + + nmp_cache_iter_for_each (&iter, + nm_platform_lookup_object(platform, NMP_OBJECT_GET_TYPE(obj), 0), + &o) { + if (addr_family == AF_INET) { + const NMPlatformIP4Route *item = NMP_OBJECT_CAST_IP4_ROUTE(o); + guint32 n = nm_utils_ip4_address_clear_host_address(item->network, item->plen); + guint32 g = nm_utils_ip4_address_clear_host_address(r4->gateway, item->plen); + + if (r->ifindex == item->ifindex && n == g) { + has_route_to_gw = TRUE; + break; + } + } else { + const NMPlatformIP6Route *item = NMP_OBJECT_CAST_IP6_ROUTE(o); + + if (r->ifindex == item->ifindex + && nm_utils_ip6_address_same_prefix(&r6->gateway, &item->network, item->plen)) { + has_route_to_gw = TRUE; + break; + } + } + } + if (!has_route_to_gw) { + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + if (addr_family == AF_INET) { + nm_log_warn( + LOGD_PLATFORM, + "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable", + r->ifindex, + _nm_utils_inet4_ntop(r4->network, sbuf), + r->plen, + r->metric); + } else { + nm_log_warn( + LOGD_PLATFORM, + "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable", + r->ifindex, + _nm_utils_inet6_ntop(&r6->network, sbuf), + r->plen, + r->metric); + } + return -NME_UNSPEC; + } + } + + has_same_weak_id = FALSE; + nmp_cache_iter_for_each ( + &iter, + nm_platform_lookup_all(platform, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, obj), + &o) { + if (addr_family == AF_INET) { + if (nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(o), + r4, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) + == 0) + continue; + } else { + if (nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(o), + r6, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) + == 0) + continue; + } + has_same_weak_id = TRUE; + } + + nlmsgflags = 0; + if (has_same_weak_id) { + switch (flags) { + case NMP_NLM_FLAG_REPLACE: + nlmsgflags = NLM_F_REPLACE; + break; + default: + g_assert_not_reached(); + break; + } + } + + /* we manipulate the cache the same was as NMLinuxPlatform does it. */ + cache_op = nmp_cache_update_netlink_route(cache, + obj, + FALSE, + nlmsgflags, + &obj_old, + &obj_new, + &obj_replace, + NULL); + only_dirty = FALSE; + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + if (obj_replace) { + const NMDedupMultiEntry *entry_replace; + + entry_replace = nmp_cache_lookup_entry(cache, obj_replace); + nm_assert(entry_replace && entry_replace->obj == obj_replace); + nm_dedup_multi_entry_set_dirty(entry_replace, TRUE); + only_dirty = TRUE; + } + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); + } + + if (obj_replace) { + cache_op = nmp_cache_remove(cache, obj_replace, TRUE, only_dirty, NULL); + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + nm_assert(cache_op == NMP_CACHE_OPS_REMOVED); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_replace, NULL); + } + } + + return 0; } /*****************************************************************************/ static void -nm_fake_platform_init (NMFakePlatform *fake_platform) +nm_fake_platform_init(NMFakePlatform *fake_platform) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (fake_platform); + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(fake_platform); - priv->options = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); - priv->links = g_array_new (TRUE, TRUE, sizeof (NMFakePlatformLink)); + priv->options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + priv->links = g_array_new(TRUE, TRUE, sizeof(NMFakePlatformLink)); } void -nm_fake_platform_setup (void) +nm_fake_platform_setup(void) { - NMPlatform *platform; + NMPlatform *platform; - platform = g_object_new (NM_TYPE_FAKE_PLATFORM, - NM_PLATFORM_LOG_WITH_PTR, FALSE, - NULL); + platform = g_object_new(NM_TYPE_FAKE_PLATFORM, NM_PLATFORM_LOG_WITH_PTR, FALSE, NULL); - nm_platform_setup (platform); + nm_platform_setup(platform); - link_add (platform, NM_LINK_TYPE_LOOPBACK, "lo", 0, NULL, 0, NULL, NULL); - link_add (platform, NM_LINK_TYPE_ETHERNET, "eth0", 0, NULL, 0, NULL, NULL); - link_add (platform, NM_LINK_TYPE_ETHERNET, "eth1", 0, NULL, 0, NULL, NULL); - link_add (platform, NM_LINK_TYPE_ETHERNET, "eth2", 0, NULL, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_LOOPBACK, "lo", 0, NULL, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_ETHERNET, "eth0", 0, NULL, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_ETHERNET, "eth1", 0, NULL, 0, NULL, NULL); + link_add(platform, NM_LINK_TYPE_ETHERNET, "eth2", 0, NULL, 0, NULL, NULL); } static void -finalize (GObject *object) +finalize(GObject *object) { - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (object); - int i; + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(object); + int i; - g_hash_table_unref (priv->options); - for (i = 0; i < priv->links->len; i++) { - NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i); + g_hash_table_unref(priv->options); + for (i = 0; i < priv->links->len; i++) { + NMFakePlatformLink *device = &g_array_index(priv->links, NMFakePlatformLink, i); - nm_clear_pointer (&device->obj, nmp_object_unref); - } - g_array_unref (priv->links); + nm_clear_pointer(&device->obj, nmp_object_unref); + } + g_array_unref(priv->links); - G_OBJECT_CLASS (nm_fake_platform_parent_class)->finalize (object); + G_OBJECT_CLASS(nm_fake_platform_parent_class)->finalize(object); } static void -nm_fake_platform_class_init (NMFakePlatformClass *klass) +nm_fake_platform_class_init(NMFakePlatformClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMPlatformClass *platform_class = NM_PLATFORM_CLASS (klass); - NMPlatformKernelSupportType kernel_support; + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMPlatformClass * platform_class = NM_PLATFORM_CLASS(klass); + NMPlatformKernelSupportType kernel_support; - for (kernel_support = 0; kernel_support < _NM_PLATFORM_KERNEL_SUPPORT_NUM; kernel_support++) - _nm_platform_kernel_support_init (kernel_support, -1); + for (kernel_support = 0; kernel_support < _NM_PLATFORM_KERNEL_SUPPORT_NUM; kernel_support++) + _nm_platform_kernel_support_init(kernel_support, -1); - object_class->finalize = finalize; + object_class->finalize = finalize; - platform_class->sysctl_set = sysctl_set; - platform_class->sysctl_get = sysctl_get; + platform_class->sysctl_set = sysctl_set; + platform_class->sysctl_get = sysctl_get; - platform_class->link_add = link_add; - platform_class->link_delete = link_delete; + platform_class->link_add = link_add; + platform_class->link_delete = link_delete; - platform_class->link_set_up = link_set_up; - platform_class->link_set_down = link_set_down; - platform_class->link_set_arp = link_set_arp; - platform_class->link_set_noarp = link_set_noarp; + platform_class->link_set_up = link_set_up; + platform_class->link_set_down = link_set_down; + platform_class->link_set_arp = link_set_arp; + platform_class->link_set_noarp = link_set_noarp; - platform_class->link_set_address = link_set_address; - platform_class->link_set_mtu = link_set_mtu; + platform_class->link_set_address = link_set_address; + platform_class->link_set_mtu = link_set_mtu; - platform_class->link_get_driver_info = link_get_driver_info; + platform_class->link_get_driver_info = link_get_driver_info; - platform_class->link_supports_carrier_detect = link_supports_carrier_detect; - platform_class->link_supports_vlans = link_supports_vlans; - platform_class->link_supports_sriov = link_supports_sriov; + platform_class->link_supports_carrier_detect = link_supports_carrier_detect; + platform_class->link_supports_vlans = link_supports_vlans; + platform_class->link_supports_sriov = link_supports_sriov; - platform_class->link_enslave = link_enslave; - platform_class->link_release = link_release; + platform_class->link_enslave = link_enslave; + platform_class->link_release = link_release; - platform_class->link_vlan_change = link_vlan_change; + platform_class->link_vlan_change = link_vlan_change; - platform_class->infiniband_partition_add = infiniband_partition_add; - platform_class->infiniband_partition_delete = infiniband_partition_delete; + platform_class->infiniband_partition_add = infiniband_partition_add; + platform_class->infiniband_partition_delete = infiniband_partition_delete; - platform_class->wifi_get_capabilities = wifi_get_capabilities; - platform_class->wifi_get_bssid = wifi_get_bssid; - platform_class->wifi_get_frequency = wifi_get_frequency; - platform_class->wifi_get_quality = wifi_get_quality; - platform_class->wifi_get_rate = wifi_get_rate; - platform_class->wifi_get_mode = wifi_get_mode; - platform_class->wifi_set_mode = wifi_set_mode; - platform_class->wifi_find_frequency = wifi_find_frequency; - platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; + platform_class->wifi_get_capabilities = wifi_get_capabilities; + platform_class->wifi_get_bssid = wifi_get_bssid; + platform_class->wifi_get_frequency = wifi_get_frequency; + platform_class->wifi_get_quality = wifi_get_quality; + platform_class->wifi_get_rate = wifi_get_rate; + platform_class->wifi_get_mode = wifi_get_mode; + platform_class->wifi_set_mode = wifi_set_mode; + platform_class->wifi_find_frequency = wifi_find_frequency; + platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; - platform_class->mesh_get_channel = mesh_get_channel; - platform_class->mesh_set_channel = mesh_set_channel; - platform_class->mesh_set_ssid = mesh_set_ssid; + platform_class->mesh_get_channel = mesh_get_channel; + platform_class->mesh_set_channel = mesh_set_channel; + platform_class->mesh_set_ssid = mesh_set_ssid; - platform_class->ip4_address_add = ip4_address_add; - platform_class->ip6_address_add = ip6_address_add; - platform_class->ip4_address_delete = ip4_address_delete; - platform_class->ip6_address_delete = ip6_address_delete; + platform_class->ip4_address_add = ip4_address_add; + platform_class->ip6_address_add = ip6_address_add; + platform_class->ip4_address_delete = ip4_address_delete; + platform_class->ip6_address_delete = ip6_address_delete; - platform_class->ip_route_add = ip_route_add; - platform_class->object_delete = object_delete; + platform_class->ip_route_add = ip_route_add; + platform_class->object_delete = object_delete; } diff --git a/src/platform/nm-fake-platform.h b/src/platform/nm-fake-platform.h index 72245e67..c3ec8921 100644 --- a/src/platform/nm-fake-platform.h +++ b/src/platform/nm-fake-platform.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2012 Red Hat, Inc. */ @@ -8,18 +8,21 @@ #include "nm-platform.h" -#define NM_TYPE_FAKE_PLATFORM (nm_fake_platform_get_type ()) -#define NM_FAKE_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_FAKE_PLATFORM, NMFakePlatform)) -#define NM_FAKE_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_FAKE_PLATFORM, NMFakePlatformClass)) -#define NM_IS_FAKE_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_FAKE_PLATFORM)) -#define NM_IS_FAKE_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_FAKE_PLATFORM)) -#define NM_FAKE_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_FAKE_PLATFORM, NMFakePlatformClass)) +#define NM_TYPE_FAKE_PLATFORM (nm_fake_platform_get_type()) +#define NM_FAKE_PLATFORM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_FAKE_PLATFORM, NMFakePlatform)) +#define NM_FAKE_PLATFORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_FAKE_PLATFORM, NMFakePlatformClass)) +#define NM_IS_FAKE_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_FAKE_PLATFORM)) +#define NM_IS_FAKE_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_FAKE_PLATFORM)) +#define NM_FAKE_PLATFORM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_FAKE_PLATFORM, NMFakePlatformClass)) -typedef struct _NMFakePlatform NMFakePlatform; +typedef struct _NMFakePlatform NMFakePlatform; typedef struct _NMFakePlatformClass NMFakePlatformClass; -GType nm_fake_platform_get_type (void); +GType nm_fake_platform_get_type(void); -void nm_fake_platform_setup (void); +void nm_fake_platform_setup(void); #endif /* __NETWORKMANAGER_FAKE_PLATFORM_H__ */ diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 2f33dc04..05125fa8 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ @@ -56,17 +56,10 @@ #include <linux/pkt_cls.h> struct tc_defact { - tc_gen; + tc_gen; }; -enum { - TCA_DEF_UNSPEC, - TCA_DEF_TM, - TCA_DEF_PARMS, - TCA_DEF_DATA, - TCA_DEF_PAD, - __TCA_DEF_MAX -}; +enum { TCA_DEF_UNSPEC, TCA_DEF_TM, TCA_DEF_PARMS, TCA_DEF_DATA, TCA_DEF_PAD, __TCA_DEF_MAX }; #define TCA_DEF_MAX (__TCA_DEF_MAX - 1) /*****************************************************************************/ @@ -82,134 +75,135 @@ enum { /*****************************************************************************/ -#define IFQDISCSIZ 32 +#define IFQDISCSIZ 32 /*****************************************************************************/ #ifndef IFLA_PROMISCUITY -#define IFLA_PROMISCUITY 30 + #define IFLA_PROMISCUITY 30 #endif -#define IFLA_NUM_TX_QUEUES 31 -#define IFLA_NUM_RX_QUEUES 32 -#define IFLA_CARRIER 33 -#define IFLA_PHYS_PORT_ID 34 -#define IFLA_LINK_NETNSID 37 -#define __IFLA_MAX 39 - -#define IFLA_INET6_TOKEN 7 -#define IFLA_INET6_ADDR_GEN_MODE 8 -#define __IFLA_INET6_MAX 9 - -#define IFLA_VLAN_PROTOCOL 5 -#define __IFLA_VLAN_MAX 6 - -#define IFA_FLAGS 8 -#define __IFA_MAX 9 - -#define IFLA_MACVLAN_FLAGS 2 -#define __IFLA_MACVLAN_MAX 3 - -#define IFLA_IPTUN_LINK 1 -#define IFLA_IPTUN_LOCAL 2 -#define IFLA_IPTUN_REMOTE 3 -#define IFLA_IPTUN_TTL 4 -#define IFLA_IPTUN_TOS 5 -#define IFLA_IPTUN_ENCAP_LIMIT 6 -#define IFLA_IPTUN_FLOWINFO 7 -#define IFLA_IPTUN_FLAGS 8 -#define IFLA_IPTUN_PROTO 9 -#define IFLA_IPTUN_PMTUDISC 10 -#define __IFLA_IPTUN_MAX 19 +#define IFLA_NUM_TX_QUEUES 31 +#define IFLA_NUM_RX_QUEUES 32 +#define IFLA_CARRIER 33 +#define IFLA_PHYS_PORT_ID 34 +#define IFLA_LINK_NETNSID 37 +#define __IFLA_MAX 39 + +#define IFLA_INET6_TOKEN 7 +#define IFLA_INET6_ADDR_GEN_MODE 8 +#define __IFLA_INET6_MAX 9 + +#define IFLA_VLAN_PROTOCOL 5 +#define __IFLA_VLAN_MAX 6 + +#define IFA_FLAGS 8 +#define __IFA_MAX 9 + +#define IFLA_MACVLAN_FLAGS 2 +#define __IFLA_MACVLAN_MAX 3 + +#define IFLA_IPTUN_LINK 1 +#define IFLA_IPTUN_LOCAL 2 +#define IFLA_IPTUN_REMOTE 3 +#define IFLA_IPTUN_TTL 4 +#define IFLA_IPTUN_TOS 5 +#define IFLA_IPTUN_ENCAP_LIMIT 6 +#define IFLA_IPTUN_FLOWINFO 7 +#define IFLA_IPTUN_FLAGS 8 +#define IFLA_IPTUN_PROTO 9 +#define IFLA_IPTUN_PMTUDISC 10 +#define __IFLA_IPTUN_MAX 19 #ifndef IFLA_IPTUN_MAX -#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) + #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) #endif -#define IFLA_TUN_UNSPEC 0 -#define IFLA_TUN_OWNER 1 -#define IFLA_TUN_GROUP 2 -#define IFLA_TUN_TYPE 3 -#define IFLA_TUN_PI 4 -#define IFLA_TUN_VNET_HDR 5 -#define IFLA_TUN_PERSIST 6 -#define IFLA_TUN_MULTI_QUEUE 7 -#define IFLA_TUN_NUM_QUEUES 8 -#define IFLA_TUN_NUM_DISABLED_QUEUES 9 -#define __IFLA_TUN_MAX 10 -#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1) - -G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1)); -#define RTA_PREF 20 -#undef RTA_MAX -#define RTA_MAX (MAX ((__RTA_MAX - 1), RTA_PREF)) +#define IFLA_TUN_UNSPEC 0 +#define IFLA_TUN_OWNER 1 +#define IFLA_TUN_GROUP 2 +#define IFLA_TUN_TYPE 3 +#define IFLA_TUN_PI 4 +#define IFLA_TUN_VNET_HDR 5 +#define IFLA_TUN_PERSIST 6 +#define IFLA_TUN_MULTI_QUEUE 7 +#define IFLA_TUN_NUM_QUEUES 8 +#define IFLA_TUN_NUM_DISABLED_QUEUES 9 +#define __IFLA_TUN_MAX 10 +#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1) + +G_STATIC_ASSERT(RTA_MAX == (__RTA_MAX - 1)); +#define RTA_PREF 20 +#undef RTA_MAX +#define RTA_MAX (MAX((__RTA_MAX - 1), RTA_PREF)) #ifndef MACVLAN_FLAG_NOPROMISC -#define MACVLAN_FLAG_NOPROMISC 1 + #define MACVLAN_FLAG_NOPROMISC 1 #endif -#define IP6_FLOWINFO_TCLASS_MASK 0x0FF00000 -#define IP6_FLOWINFO_TCLASS_SHIFT 20 -#define IP6_FLOWINFO_FLOWLABEL_MASK 0x000FFFFF +#define IP6_FLOWINFO_TCLASS_MASK 0x0FF00000 +#define IP6_FLOWINFO_TCLASS_SHIFT 20 +#define IP6_FLOWINFO_FLOWLABEL_MASK 0x000FFFFF + +#define IFLA_BR_VLAN_STATS_ENABLED 41 /*****************************************************************************/ -/* Appeared in in kernel prior to 3.13 dated 19 January, 2014 */ +/* Appeared in the kernel prior to 3.13 dated 19 January, 2014 */ #ifndef ARPHRD_6LOWPAN -#define ARPHRD_6LOWPAN 825 + #define ARPHRD_6LOWPAN 825 #endif /*****************************************************************************/ -#define FRA_TUN_ID 12 -#define FRA_SUPPRESS_IFGROUP 13 -#define FRA_SUPPRESS_PREFIXLEN 14 -#define FRA_PAD 18 -#define FRA_L3MDEV 19 -#define FRA_UID_RANGE 20 -#define FRA_PROTOCOL 21 -#define FRA_IP_PROTO 22 -#define FRA_SPORT_RANGE 23 -#define FRA_DPORT_RANGE 24 +#define FRA_TUN_ID 12 +#define FRA_SUPPRESS_IFGROUP 13 +#define FRA_SUPPRESS_PREFIXLEN 14 +#define FRA_PAD 18 +#define FRA_L3MDEV 19 +#define FRA_UID_RANGE 20 +#define FRA_PROTOCOL 21 +#define FRA_IP_PROTO 22 +#define FRA_SPORT_RANGE 23 +#define FRA_DPORT_RANGE 24 /*****************************************************************************/ -#define IFLA_MACSEC_UNSPEC 0 -#define IFLA_MACSEC_SCI 1 -#define IFLA_MACSEC_PORT 2 -#define IFLA_MACSEC_ICV_LEN 3 -#define IFLA_MACSEC_CIPHER_SUITE 4 -#define IFLA_MACSEC_WINDOW 5 -#define IFLA_MACSEC_ENCODING_SA 6 -#define IFLA_MACSEC_ENCRYPT 7 -#define IFLA_MACSEC_PROTECT 8 -#define IFLA_MACSEC_INC_SCI 9 -#define IFLA_MACSEC_ES 10 -#define IFLA_MACSEC_SCB 11 -#define IFLA_MACSEC_REPLAY_PROTECT 12 -#define IFLA_MACSEC_VALIDATION 13 -#define IFLA_MACSEC_PAD 14 -#define __IFLA_MACSEC_MAX 15 +#define IFLA_MACSEC_UNSPEC 0 +#define IFLA_MACSEC_SCI 1 +#define IFLA_MACSEC_PORT 2 +#define IFLA_MACSEC_ICV_LEN 3 +#define IFLA_MACSEC_CIPHER_SUITE 4 +#define IFLA_MACSEC_WINDOW 5 +#define IFLA_MACSEC_ENCODING_SA 6 +#define IFLA_MACSEC_ENCRYPT 7 +#define IFLA_MACSEC_PROTECT 8 +#define IFLA_MACSEC_INC_SCI 9 +#define IFLA_MACSEC_ES 10 +#define IFLA_MACSEC_SCB 11 +#define IFLA_MACSEC_REPLAY_PROTECT 12 +#define IFLA_MACSEC_VALIDATION 13 +#define IFLA_MACSEC_PAD 14 +#define __IFLA_MACSEC_MAX 15 /*****************************************************************************/ #define WG_CMD_GET_DEVICE 0 #define WG_CMD_SET_DEVICE 1 -#define WGDEVICE_F_REPLACE_PEERS ((guint32) (1U << 0)) - -#define WGPEER_F_REMOVE_ME ((guint32) (1U << 0)) -#define WGPEER_F_REPLACE_ALLOWEDIPS ((guint32) (1U << 1)) +#define WGDEVICE_F_REPLACE_PEERS ((guint32)(1U << 0)) +#define WGPEER_F_REMOVE_ME ((guint32)(1U << 0)) +#define WGPEER_F_REPLACE_ALLOWEDIPS ((guint32)(1U << 1)) -#define WGDEVICE_A_UNSPEC 0 -#define WGDEVICE_A_IFINDEX 1 -#define WGDEVICE_A_IFNAME 2 -#define WGDEVICE_A_PRIVATE_KEY 3 -#define WGDEVICE_A_PUBLIC_KEY 4 -#define WGDEVICE_A_FLAGS 5 -#define WGDEVICE_A_LISTEN_PORT 6 -#define WGDEVICE_A_FWMARK 7 -#define WGDEVICE_A_PEERS 8 -#define WGDEVICE_A_MAX 8 +#define WGDEVICE_A_UNSPEC 0 +#define WGDEVICE_A_IFINDEX 1 +#define WGDEVICE_A_IFNAME 2 +#define WGDEVICE_A_PRIVATE_KEY 3 +#define WGDEVICE_A_PUBLIC_KEY 4 +#define WGDEVICE_A_FLAGS 5 +#define WGDEVICE_A_LISTEN_PORT 6 +#define WGDEVICE_A_FWMARK 7 +#define WGDEVICE_A_PEERS 8 +#define WGDEVICE_A_MAX 8 #define WGPEER_A_UNSPEC 0 #define WGPEER_A_PUBLIC_KEY 1 @@ -223,58 +217,58 @@ G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1)); #define WGPEER_A_ALLOWEDIPS 9 #define WGPEER_A_MAX 9 -#define WGALLOWEDIP_A_UNSPEC 0 -#define WGALLOWEDIP_A_FAMILY 1 -#define WGALLOWEDIP_A_IPADDR 2 -#define WGALLOWEDIP_A_CIDR_MASK 3 -#define WGALLOWEDIP_A_MAX 3 +#define WGALLOWEDIP_A_UNSPEC 0 +#define WGALLOWEDIP_A_FAMILY 1 +#define WGALLOWEDIP_A_IPADDR 2 +#define WGALLOWEDIP_A_CIDR_MASK 3 +#define WGALLOWEDIP_A_MAX 3 /*****************************************************************************/ /* Redefine VF enums and structures that are not available on older kernels. */ -#define IFLA_VF_UNSPEC 0 -#define IFLA_VF_MAC 1 -#define IFLA_VF_VLAN 2 -#define IFLA_VF_TX_RATE 3 -#define IFLA_VF_SPOOFCHK 4 -#define IFLA_VF_LINK_STATE 5 -#define IFLA_VF_RATE 6 -#define IFLA_VF_RSS_QUERY_EN 7 -#define IFLA_VF_STATS 8 -#define IFLA_VF_TRUST 9 -#define IFLA_VF_IB_NODE_GUID 10 -#define IFLA_VF_IB_PORT_GUID 11 -#define IFLA_VF_VLAN_LIST 12 - -#define IFLA_VF_VLAN_INFO_UNSPEC 0 -#define IFLA_VF_VLAN_INFO 1 +#define IFLA_VF_UNSPEC 0 +#define IFLA_VF_MAC 1 +#define IFLA_VF_VLAN 2 +#define IFLA_VF_TX_RATE 3 +#define IFLA_VF_SPOOFCHK 4 +#define IFLA_VF_LINK_STATE 5 +#define IFLA_VF_RATE 6 +#define IFLA_VF_RSS_QUERY_EN 7 +#define IFLA_VF_STATS 8 +#define IFLA_VF_TRUST 9 +#define IFLA_VF_IB_NODE_GUID 10 +#define IFLA_VF_IB_PORT_GUID 11 +#define IFLA_VF_VLAN_LIST 12 + +#define IFLA_VF_VLAN_INFO_UNSPEC 0 +#define IFLA_VF_VLAN_INFO 1 /* valid for TRUST, SPOOFCHK, LINK_STATE, RSS_QUERY_EN */ struct _ifla_vf_setting { - guint32 vf; - guint32 setting; + guint32 vf; + guint32 setting; }; struct _ifla_vf_rate { - guint32 vf; - guint32 min_tx_rate; - guint32 max_tx_rate; + guint32 vf; + guint32 min_tx_rate; + guint32 max_tx_rate; }; struct _ifla_vf_vlan_info { - guint32 vf; - guint32 vlan; /* 0 - 4095, 0 disables VLAN filter */ - guint32 qos; - guint16 vlan_proto; /* VLAN protocol, either 802.1Q or 802.1ad */ + guint32 vf; + guint32 vlan; /* 0 - 4095, 0 disables VLAN filter */ + guint32 qos; + guint16 vlan_proto; /* VLAN protocol, either 802.1Q or 802.1ad */ }; /*****************************************************************************/ -/* Appeared in in kernel 4.0 dated April 12, 2015 */ +/* Appeared in the kernel 4.0 dated April 12, 2015 */ #ifndef BRIDGE_VLAN_INFO_RANGE_BEGIN -#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1 << 3) /* VLAN is start of vlan range */ -#define BRIDGE_VLAN_INFO_RANGE_END (1 << 4) /* VLAN is end of vlan range */ + #define BRIDGE_VLAN_INFO_RANGE_BEGIN (1 << 3) /* VLAN is start of vlan range */ + #define BRIDGE_VLAN_INFO_RANGE_END (1 << 4) /* VLAN is end of vlan range */ #endif /*****************************************************************************/ @@ -284,300 +278,318 @@ struct _ifla_vf_vlan_info { /*****************************************************************************/ typedef enum { - INFINIBAND_ACTION_CREATE_CHILD, - INFINIBAND_ACTION_DELETE_CHILD, + INFINIBAND_ACTION_CREATE_CHILD, + INFINIBAND_ACTION_DELETE_CHILD, } InfinibandAction; typedef enum { - CHANGE_LINK_TYPE_UNSPEC, - CHANGE_LINK_TYPE_SET_MTU, - CHANGE_LINK_TYPE_SET_ADDRESS, + CHANGE_LINK_TYPE_UNSPEC, + CHANGE_LINK_TYPE_SET_MTU, + CHANGE_LINK_TYPE_SET_ADDRESS, } ChangeLinkType; typedef struct { - union { - struct { - gconstpointer address; - gsize length; - } set_address; - }; + union { + struct { + gconstpointer address; + gsize length; + } set_address; + }; } ChangeLinkData; typedef enum { - _REFRESH_ALL_TYPE_FIRST = 0, - - REFRESH_ALL_TYPE_LINKS = 0, - REFRESH_ALL_TYPE_IP4_ADDRESSES = 1, - REFRESH_ALL_TYPE_IP6_ADDRESSES = 2, - REFRESH_ALL_TYPE_IP4_ROUTES = 3, - REFRESH_ALL_TYPE_IP6_ROUTES = 4, - REFRESH_ALL_TYPE_ROUTING_RULES_IP4 = 5, - REFRESH_ALL_TYPE_ROUTING_RULES_IP6 = 6, - REFRESH_ALL_TYPE_QDISCS = 7, - REFRESH_ALL_TYPE_TFILTERS = 8, - - _REFRESH_ALL_TYPE_NUM, + _REFRESH_ALL_TYPE_FIRST = 0, + + REFRESH_ALL_TYPE_LINKS = 0, + REFRESH_ALL_TYPE_IP4_ADDRESSES = 1, + REFRESH_ALL_TYPE_IP6_ADDRESSES = 2, + REFRESH_ALL_TYPE_IP4_ROUTES = 3, + REFRESH_ALL_TYPE_IP6_ROUTES = 4, + REFRESH_ALL_TYPE_ROUTING_RULES_IP4 = 5, + REFRESH_ALL_TYPE_ROUTING_RULES_IP6 = 6, + REFRESH_ALL_TYPE_QDISCS = 7, + REFRESH_ALL_TYPE_TFILTERS = 8, + + _REFRESH_ALL_TYPE_NUM, } RefreshAllType; typedef struct { - NMPObjectType obj_type; + NMPObjectType obj_type; - /* for NLM_F_DUMP, which address family to request. */ - int addr_family; + /* for NLM_F_DUMP, which address family to request. */ + int addr_family; } RefreshAllInfo; typedef enum { - DELAYED_ACTION_TYPE_NONE = 0, - -#define F(val, name) ((sizeof (char[(((val)) == (name)) ? 1 : -1]) * 0) + (val)) - DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS = 1 << F (0, REFRESH_ALL_TYPE_LINKS), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES = 1 << F (1, REFRESH_ALL_TYPE_IP4_ADDRESSES), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES = 1 << F (2, REFRESH_ALL_TYPE_IP6_ADDRESSES), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES = 1 << F (3, REFRESH_ALL_TYPE_IP4_ROUTES), - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES = 1 << F (4, REFRESH_ALL_TYPE_IP6_ROUTES), - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4 = 1 << F (5, REFRESH_ALL_TYPE_ROUTING_RULES_IP4), - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6 = 1 << F (6, REFRESH_ALL_TYPE_ROUTING_RULES_IP6), - DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS = 1 << F (7, REFRESH_ALL_TYPE_QDISCS), - DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS = 1 << F (8, REFRESH_ALL_TYPE_TFILTERS), + DELAYED_ACTION_TYPE_NONE = 0, + +#define F(val, name) ((sizeof(char[(((val)) == (name)) ? 1 : -1]) * 0) + (val)) + DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS = 1 << F(0, REFRESH_ALL_TYPE_LINKS), + DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES = 1 << F(1, REFRESH_ALL_TYPE_IP4_ADDRESSES), + DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES = 1 << F(2, REFRESH_ALL_TYPE_IP6_ADDRESSES), + DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES = 1 << F(3, REFRESH_ALL_TYPE_IP4_ROUTES), + DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES = 1 << F(4, REFRESH_ALL_TYPE_IP6_ROUTES), + DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4 = 1 + << F(5, REFRESH_ALL_TYPE_ROUTING_RULES_IP4), + DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6 = 1 + << F(6, REFRESH_ALL_TYPE_ROUTING_RULES_IP6), + DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS = 1 << F(7, REFRESH_ALL_TYPE_QDISCS), + DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS = 1 << F(8, REFRESH_ALL_TYPE_TFILTERS), #undef F - DELAYED_ACTION_TYPE_REFRESH_LINK = 1 << 9, - DELAYED_ACTION_TYPE_MASTER_CONNECTED = 1 << 10, - DELAYED_ACTION_TYPE_READ_NETLINK = 1 << 11, - DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE = 1 << 12, + DELAYED_ACTION_TYPE_REFRESH_LINK = 1 << 9, + DELAYED_ACTION_TYPE_MASTER_CONNECTED = 1 << 10, + DELAYED_ACTION_TYPE_READ_NETLINK = 1 << 11, + DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE = 1 << 12, - __DELAYED_ACTION_TYPE_MAX, + __DELAYED_ACTION_TYPE_MAX, - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL = DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4 | - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, + DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL = + DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4 + | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, - DELAYED_ACTION_TYPE_REFRESH_ALL = DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL | - DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS | - DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, + DELAYED_ACTION_TYPE_REFRESH_ALL = + DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS + | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - DELAYED_ACTION_TYPE_MAX = __DELAYED_ACTION_TYPE_MAX -1, + DELAYED_ACTION_TYPE_MAX = __DELAYED_ACTION_TYPE_MAX - 1, } DelayedActionType; -#define FOR_EACH_DELAYED_ACTION(iflags, flags_all) \ - for ((iflags) = (DelayedActionType) 0x1LL; \ - ({ \ - gboolean _good = FALSE; \ - \ - nm_assert (nm_utils_is_power_of_two (iflags)); \ - \ - while ((iflags) <= DELAYED_ACTION_TYPE_MAX) { \ - if (NM_FLAGS_ANY ((flags_all), (iflags))) { \ - _good = TRUE; \ - break; \ - } \ - (iflags) <<= 1; \ - } \ - _good; \ - }); \ - (iflags) <<= 1) +#define FOR_EACH_DELAYED_ACTION(iflags, flags_all) \ + for ((iflags) = (DelayedActionType) 0x1LL; ({ \ + gboolean _good = FALSE; \ + \ + nm_assert(nm_utils_is_power_of_two(iflags)); \ + \ + while ((iflags) <= DELAYED_ACTION_TYPE_MAX) { \ + if (NM_FLAGS_ANY((flags_all), (iflags))) { \ + _good = TRUE; \ + break; \ + } \ + (iflags) <<= 1; \ + } \ + _good; \ + }); \ + (iflags) <<= 1) typedef enum { - /* Negative values are errors from kernel. Add dummy member to - * make enum signed. */ - _WAIT_FOR_NL_RESPONSE_RESULT_SYSTEM_ERROR = G_MININT, - - WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN = 0, - WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK, - WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS, + /* Negative values are errors from kernel. Add dummy member to + * make enum signed. */ + _WAIT_FOR_NL_RESPONSE_RESULT_SYSTEM_ERROR = G_MININT, + + WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN = 0, + WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK, + WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS, } WaitForNlResponseResult; typedef enum { - DELAYED_ACTION_RESPONSE_TYPE_VOID = 0, - DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS = 1, - DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET = 2, + DELAYED_ACTION_RESPONSE_TYPE_VOID = 0, + DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS = 1, + DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET = 2, } DelayedActionWaitForNlResponseType; typedef struct { - guint32 seq_number; - WaitForNlResponseResult seq_result; - DelayedActionWaitForNlResponseType response_type; - gint64 timeout_abs_ns; - WaitForNlResponseResult *out_seq_result; - char **out_errmsg; - union { - int *out_refresh_all_in_progress; - NMPObject **out_route_get; - gpointer out_data; - } response; + guint32 seq_number; + WaitForNlResponseResult seq_result; + DelayedActionWaitForNlResponseType response_type; + gint64 timeout_abs_ns; + WaitForNlResponseResult * out_seq_result; + char ** out_errmsg; + union { + int * out_refresh_all_in_progress; + NMPObject **out_route_get; + gpointer out_data; + } response; } DelayedActionWaitForNlResponseData; /*****************************************************************************/ typedef struct { - struct nl_sock *genl; + struct nl_sock *genl; - struct nl_sock *nlh; + struct nl_sock *nlh; - GSource *event_source; + GSource *event_source; - guint32 nlh_seq_next; + guint32 nlh_seq_next; #if NM_MORE_LOGGING - guint32 nlh_seq_last_handled; + guint32 nlh_seq_last_handled; #endif - guint32 nlh_seq_last_seen; + guint32 nlh_seq_last_seen; - guint32 pruning[_REFRESH_ALL_TYPE_NUM]; + guint32 pruning[_REFRESH_ALL_TYPE_NUM]; - GHashTable *sysctl_get_prev_values; - CList sysctl_list; + GHashTable *sysctl_get_prev_values; + CList sysctl_list; - NMUdevClient *udev_client; + NMUdevClient *udev_client; - struct { - /* which delayed actions are scheduled, as marked in @flags. - * Some types have additional arguments in the fields below. */ - DelayedActionType flags; + struct { + /* which delayed actions are scheduled, as marked in @flags. + * Some types have additional arguments in the fields below. */ + DelayedActionType flags; - /* counter that a refresh all action is in progress, separated - * by type. */ - int refresh_all_in_progress[_REFRESH_ALL_TYPE_NUM]; + /* counter that a refresh all action is in progress, separated + * by type. */ + int refresh_all_in_progress[_REFRESH_ALL_TYPE_NUM]; - GPtrArray *list_master_connected; - GPtrArray *list_refresh_link; - GArray *list_wait_for_nl_response; + GPtrArray *list_master_connected; + GPtrArray *list_refresh_link; + GArray * list_wait_for_nl_response; - int is_handling; - } delayed_action; + int is_handling; + } delayed_action; } NMLinuxPlatformPrivate; struct _NMLinuxPlatform { - NMPlatform parent; - NMLinuxPlatformPrivate _priv; + NMPlatform parent; + NMLinuxPlatformPrivate _priv; }; struct _NMLinuxPlatformClass { - NMPlatformClass parent; + NMPlatformClass parent; }; -G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM) +G_DEFINE_TYPE(NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM) -#define NM_LINUX_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMLinuxPlatform, NM_IS_LINUX_PLATFORM, NMPlatform) +#define NM_LINUX_PLATFORM_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMLinuxPlatform, NM_IS_LINUX_PLATFORM, NMPlatform) /*****************************************************************************/ -#define _NMLOG_PREFIX_NAME "platform-linux" -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG2_DOMAIN LOGD_PLATFORM -#define _NMLOG(level, ...) _LOG ( level, _NMLOG_DOMAIN, platform, __VA_ARGS__) -#define _NMLOG_err(errsv, level, ...) _LOG_err (errsv, level, _NMLOG_DOMAIN, platform, __VA_ARGS__) -#define _NMLOG2(level, ...) _LOG ( level, _NMLOG2_DOMAIN, NULL, __VA_ARGS__) -#define _NMLOG2_err(errsv, level, ...) _LOG_err (errsv, level, _NMLOG2_DOMAIN, NULL, __VA_ARGS__) - -#define _LOG_print(__level, __domain, __errsv, self, ...) \ - G_STMT_START { \ - char __prefix[32]; \ - const char *__p_prefix = _NMLOG_PREFIX_NAME; \ - NMPlatform *const __self = (self); \ - \ - if (__self && nm_platform_get_log_with_ptr (__self)) { \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ - __p_prefix = __prefix; \ - } \ - _nm_log (__level, __domain, __errsv, NULL, NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } G_STMT_END - -#define _LOG(level, domain, self, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ - \ - if (nm_logging_enabled (__level, __domain)) { \ - _LOG_print (__level, __domain, 0, self, __VA_ARGS__); \ - } \ - } G_STMT_END - -#define _LOG_err(errsv, level, domain, self, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ - \ - if (nm_logging_enabled (__level, __domain)) { \ - int __errsv = (errsv); \ - \ +#define _NMLOG_PREFIX_NAME "platform-linux" +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG2_DOMAIN LOGD_PLATFORM +#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, platform, __VA_ARGS__) +#define _NMLOG_err(errsv, level, ...) _LOG_err(errsv, level, _NMLOG_DOMAIN, platform, __VA_ARGS__) +#define _NMLOG2(level, ...) _LOG(level, _NMLOG2_DOMAIN, NULL, __VA_ARGS__) +#define _NMLOG2_err(errsv, level, ...) _LOG_err(errsv, level, _NMLOG2_DOMAIN, NULL, __VA_ARGS__) + +#define _LOG_print(__level, __domain, __errsv, self, ...) \ + G_STMT_START \ + { \ + char __prefix[32]; \ + const char * __p_prefix = _NMLOG_PREFIX_NAME; \ + NMPlatform *const __self = (self); \ + \ + if (__self && nm_platform_get_log_with_ptr(__self)) { \ + g_snprintf(__prefix, sizeof(__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ + __p_prefix = __prefix; \ + } \ + _nm_log(__level, \ + __domain, \ + __errsv, \ + NULL, \ + NULL, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + __p_prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END + +#define _LOG(level, domain, self, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + const NMLogDomain __domain = (domain); \ + \ + if (nm_logging_enabled(__level, __domain)) { \ + _LOG_print(__level, __domain, 0, self, __VA_ARGS__); \ + } \ + } \ + G_STMT_END + +#define _LOG_err(errsv, level, domain, self, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + const NMLogDomain __domain = (domain); \ + \ + if (nm_logging_enabled(__level, __domain)) { \ + int __errsv = (errsv); \ + \ /* The %m format specifier (GNU extension) would already allow you to specify the error * message conveniently (and nm_log would get that right too). But we don't want to depend * on that, so instead append the message at the end. - * Currently users are expected not to use %m in the format string. */ \ - _LOG_print (__level, __domain, __errsv, self, \ - _NM_UTILS_MACRO_FIRST (__VA_ARGS__) ": %s (%d)" \ - _NM_UTILS_MACRO_REST (__VA_ARGS__), \ - nm_strerror_native (__errsv), __errsv); \ - } \ - } G_STMT_END + * Currently, users are expected not to use %m in the format string. */ \ + _LOG_print( \ + __level, \ + __domain, \ + __errsv, \ + self, \ + _NM_UTILS_MACRO_FIRST(__VA_ARGS__) ": %s (%d)" _NM_UTILS_MACRO_REST(__VA_ARGS__), \ + nm_strerror_native(__errsv), \ + __errsv); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ -static void delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gpointer user_data); -static gboolean delayed_action_handle_all (NMPlatform *platform, gboolean read_netlink); -static void do_request_link_no_delayed_actions (NMPlatform *platform, int ifindex, const char *name); -static void do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType action_type); -static void cache_on_change (NMPlatform *platform, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new); -static void cache_prune_all (NMPlatform *platform); -static gboolean event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks); -static struct nl_sock *_genl_sock (NMLinuxPlatform *platform); +static void +delayed_action_schedule(NMPlatform *platform, DelayedActionType action_type, gpointer user_data); +static gboolean delayed_action_handle_all(NMPlatform *platform, gboolean read_netlink); +static void do_request_link_no_delayed_actions(NMPlatform *platform, int ifindex, const char *name); +static void do_request_all_no_delayed_actions(NMPlatform *platform, DelayedActionType action_type); +static void cache_on_change(NMPlatform * platform, + NMPCacheOpsType cache_op, + const NMPObject *obj_old, + const NMPObject *obj_new); +static void cache_prune_all(NMPlatform *platform); +static gboolean event_handler_read_netlink(NMPlatform *platform, gboolean wait_for_acks); +static struct nl_sock *_genl_sock(NMLinuxPlatform *platform); /*****************************************************************************/ static int -wait_for_nl_response_to_nmerr (WaitForNlResponseResult seq_result) +wait_for_nl_response_to_nmerr(WaitForNlResponseResult seq_result) { - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; - if (seq_result < 0) - return (int) seq_result; - return -NME_PL_NETLINK; + if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) + return 0; + if (seq_result < 0) + return (int) seq_result; + return -NME_PL_NETLINK; } static const char * -wait_for_nl_response_to_string (WaitForNlResponseResult seq_result, - const char *errmsg, - char *buf, gsize buf_size) -{ - char *buf0 = buf; - - switch (seq_result) { - case WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN: - nm_utils_strbuf_append_str (&buf, &buf_size, "unknown"); - break; - case WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK: - nm_utils_strbuf_append_str (&buf, &buf_size, "success"); - break; - case WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN: - nm_utils_strbuf_append_str (&buf, &buf_size, "failure"); - break; - default: - if (seq_result < 0) { - nm_utils_strbuf_append (&buf, &buf_size, "failure %d (%s%s%s)", - -((int) seq_result), - nm_strerror_native (-((int) seq_result)), - errmsg ? " - " : "", - errmsg ?: ""); - } - else - nm_utils_strbuf_append (&buf, &buf_size, "internal failure %d", (int) seq_result); - break; - } - return buf0; +wait_for_nl_response_to_string(WaitForNlResponseResult seq_result, + const char * errmsg, + char * buf, + gsize buf_size) +{ + char *buf0 = buf; + + switch (seq_result) { + case WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN: + nm_utils_strbuf_append_str(&buf, &buf_size, "unknown"); + break; + case WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK: + nm_utils_strbuf_append_str(&buf, &buf_size, "success"); + break; + case WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN: + nm_utils_strbuf_append_str(&buf, &buf_size, "failure"); + break; + default: + if (seq_result < 0) { + nm_utils_strbuf_append(&buf, + &buf_size, + "failure %d (%s%s%s)", + -((int) seq_result), + nm_strerror_native(-((int) seq_result)), + errmsg ? " - " : "", + errmsg ?: ""); + } else + nm_utils_strbuf_append(&buf, &buf_size, "internal failure %d", (int) seq_result); + break; + } + return buf0; } /****************************************************************** @@ -585,22 +597,22 @@ wait_for_nl_response_to_string (WaitForNlResponseResult seq_result, ******************************************************************/ static int -_vlan_qos_mapping_cmp_from (gconstpointer a, gconstpointer b, gpointer user_data) +_vlan_qos_mapping_cmp_from(gconstpointer a, gconstpointer b, gpointer user_data) { - const NMVlanQosMapping *map_a = a; - const NMVlanQosMapping *map_b = b; + const NMVlanQosMapping *map_a = a; + const NMVlanQosMapping *map_b = b; - if (map_a->from != map_b->from) - return map_a->from < map_b->from ? -1 : 1; - return 0; + if (map_a->from != map_b->from) + return map_a->from < map_b->from ? -1 : 1; + return 0; } static int -_vlan_qos_mapping_cmp_from_ptr (gconstpointer a, gconstpointer b, gpointer user_data) +_vlan_qos_mapping_cmp_from_ptr(gconstpointer a, gconstpointer b, gpointer user_data) { - return _vlan_qos_mapping_cmp_from (*((const NMVlanQosMapping **) a), - *((const NMVlanQosMapping **) b), - NULL); + return _vlan_qos_mapping_cmp_from(*((const NMVlanQosMapping **) a), + *((const NMVlanQosMapping **) b), + NULL); } /****************************************************************** @@ -608,222 +620,222 @@ _vlan_qos_mapping_cmp_from_ptr (gconstpointer a, gconstpointer b, gpointer user_ ******************************************************************/ typedef struct { - - const char *type_string; - - /* IFLA_INFO_KIND / rtnl_link_get_type() where applicable; the rtnl type - * should only be specified if the device type can be created without - * additional parameters, and if the device type can be determined from - * the rtnl_type. eg, tun/tap should not be specified since both - * tun and tap devices use "tun", and InfiniBand should not be - * specified because a PKey is required at creation. Drivers set this - * value from their 'struct rtnl_link_ops' structure. - */ - const char *rtnl_type; - - /* uevent DEVTYPE where applicable, from /sys/class/net/<ifname>/uevent; - * drivers set this value from their SET_NETDEV_DEV() call and the - * 'struct device_type' name member. - */ - const char *devtype; + const char *type_string; + + /* IFLA_INFO_KIND / rtnl_link_get_type() where applicable; the rtnl type + * should only be specified if the device type can be created without + * additional parameters, and if the device type can be determined from + * the rtnl_type. eg, tun/tap should not be specified since both + * tun and tap devices use "tun", and InfiniBand should not be + * specified because a PKey is required at creation. Drivers set this + * value from their 'struct rtnl_link_ops' structure. + */ + const char *rtnl_type; + + /* uevent DEVTYPE where applicable, from /sys/class/net/<ifname>/uevent; + * drivers set this value from their SET_NETDEV_DEV() call and the + * 'struct device_type' name member. + */ + const char *devtype; } LinkDesc; static const LinkDesc link_descs[] = { - [NM_LINK_TYPE_NONE] = { "none", NULL, NULL }, - [NM_LINK_TYPE_UNKNOWN] = { "unknown", NULL, NULL }, - [NM_LINK_TYPE_ANY] = { "any", NULL, NULL }, - - [NM_LINK_TYPE_ETHERNET] = { "ethernet", NULL, NULL }, - [NM_LINK_TYPE_INFINIBAND] = { "infiniband", NULL, NULL }, - [NM_LINK_TYPE_OLPC_MESH] = { "olpc-mesh", NULL, NULL }, - [NM_LINK_TYPE_WIFI] = { "wifi", NULL, "wlan" }, - [NM_LINK_TYPE_WWAN_NET] = { "wwan", NULL, "wwan" }, - [NM_LINK_TYPE_WIMAX] = { "wimax", "wimax", "wimax" }, - [NM_LINK_TYPE_WPAN] = { "wpan", NULL, NULL }, - [NM_LINK_TYPE_6LOWPAN] = { "6lowpan", NULL, NULL }, - - [NM_LINK_TYPE_BNEP] = { "bluetooth", NULL, "bluetooth" }, - [NM_LINK_TYPE_DUMMY] = { "dummy", "dummy", NULL }, - [NM_LINK_TYPE_GRE] = { "gre", "gre", NULL }, - [NM_LINK_TYPE_GRETAP] = { "gretap", "gretap", NULL }, - [NM_LINK_TYPE_IFB] = { "ifb", "ifb", NULL }, - [NM_LINK_TYPE_IP6TNL] = { "ip6tnl", "ip6tnl", NULL }, - [NM_LINK_TYPE_IP6GRE] = { "ip6gre", "ip6gre", NULL }, - [NM_LINK_TYPE_IP6GRETAP] = { "ip6gretap", "ip6gretap", NULL }, - [NM_LINK_TYPE_IPIP] = { "ipip", "ipip", NULL }, - [NM_LINK_TYPE_LOOPBACK] = { "loopback", NULL, NULL }, - [NM_LINK_TYPE_MACSEC] = { "macsec", "macsec", NULL }, - [NM_LINK_TYPE_MACVLAN] = { "macvlan", "macvlan", NULL }, - [NM_LINK_TYPE_MACVTAP] = { "macvtap", "macvtap", NULL }, - [NM_LINK_TYPE_OPENVSWITCH] = { "openvswitch", "openvswitch", NULL }, - [NM_LINK_TYPE_PPP] = { "ppp", NULL, "ppp" }, - [NM_LINK_TYPE_SIT] = { "sit", "sit", NULL }, - [NM_LINK_TYPE_TUN] = { "tun", "tun", NULL }, - [NM_LINK_TYPE_VETH] = { "veth", "veth", NULL }, - [NM_LINK_TYPE_VLAN] = { "vlan", "vlan", "vlan" }, - [NM_LINK_TYPE_VRF] = { "vrf", "vrf", "vrf" }, - [NM_LINK_TYPE_VXLAN] = { "vxlan", "vxlan", "vxlan" }, - [NM_LINK_TYPE_WIREGUARD] = { "wireguard", "wireguard", "wireguard" }, - - [NM_LINK_TYPE_BRIDGE] = { "bridge", "bridge", "bridge" }, - [NM_LINK_TYPE_BOND] = { "bond", "bond", "bond" }, - [NM_LINK_TYPE_TEAM] = { "team", "team", NULL }, + [NM_LINK_TYPE_NONE] = {"none", NULL, NULL}, + [NM_LINK_TYPE_UNKNOWN] = {"unknown", NULL, NULL}, + [NM_LINK_TYPE_ANY] = {"any", NULL, NULL}, + + [NM_LINK_TYPE_ETHERNET] = {"ethernet", NULL, NULL}, + [NM_LINK_TYPE_INFINIBAND] = {"infiniband", NULL, NULL}, + [NM_LINK_TYPE_OLPC_MESH] = {"olpc-mesh", NULL, NULL}, + [NM_LINK_TYPE_WIFI] = {"wifi", NULL, "wlan"}, + [NM_LINK_TYPE_WWAN_NET] = {"wwan", NULL, "wwan"}, + [NM_LINK_TYPE_WIMAX] = {"wimax", "wimax", "wimax"}, + [NM_LINK_TYPE_WPAN] = {"wpan", NULL, NULL}, + [NM_LINK_TYPE_6LOWPAN] = {"6lowpan", NULL, NULL}, + + [NM_LINK_TYPE_BNEP] = {"bluetooth", NULL, "bluetooth"}, + [NM_LINK_TYPE_DUMMY] = {"dummy", "dummy", NULL}, + [NM_LINK_TYPE_GRE] = {"gre", "gre", NULL}, + [NM_LINK_TYPE_GRETAP] = {"gretap", "gretap", NULL}, + [NM_LINK_TYPE_IFB] = {"ifb", "ifb", NULL}, + [NM_LINK_TYPE_IP6TNL] = {"ip6tnl", "ip6tnl", NULL}, + [NM_LINK_TYPE_IP6GRE] = {"ip6gre", "ip6gre", NULL}, + [NM_LINK_TYPE_IP6GRETAP] = {"ip6gretap", "ip6gretap", NULL}, + [NM_LINK_TYPE_IPIP] = {"ipip", "ipip", NULL}, + [NM_LINK_TYPE_LOOPBACK] = {"loopback", NULL, NULL}, + [NM_LINK_TYPE_MACSEC] = {"macsec", "macsec", NULL}, + [NM_LINK_TYPE_MACVLAN] = {"macvlan", "macvlan", NULL}, + [NM_LINK_TYPE_MACVTAP] = {"macvtap", "macvtap", NULL}, + [NM_LINK_TYPE_OPENVSWITCH] = {"openvswitch", "openvswitch", NULL}, + [NM_LINK_TYPE_PPP] = {"ppp", NULL, "ppp"}, + [NM_LINK_TYPE_SIT] = {"sit", "sit", NULL}, + [NM_LINK_TYPE_TUN] = {"tun", "tun", NULL}, + [NM_LINK_TYPE_VETH] = {"veth", "veth", NULL}, + [NM_LINK_TYPE_VLAN] = {"vlan", "vlan", "vlan"}, + [NM_LINK_TYPE_VRF] = {"vrf", "vrf", "vrf"}, + [NM_LINK_TYPE_VXLAN] = {"vxlan", "vxlan", "vxlan"}, + [NM_LINK_TYPE_WIREGUARD] = {"wireguard", "wireguard", "wireguard"}, + + [NM_LINK_TYPE_BRIDGE] = {"bridge", "bridge", "bridge"}, + [NM_LINK_TYPE_BOND] = {"bond", "bond", "bond"}, + [NM_LINK_TYPE_TEAM] = {"team", "team", NULL}, }; static const LinkDesc * -_link_desc_from_link_type (NMLinkType link_type) +_link_desc_from_link_type(NMLinkType link_type) { - nm_assert (_NM_INT_NOT_NEGATIVE (link_type)); - nm_assert (link_type < G_N_ELEMENTS (link_descs)); - nm_assert (link_descs[link_type].type_string); + nm_assert(_NM_INT_NOT_NEGATIVE(link_type)); + nm_assert(link_type < G_N_ELEMENTS(link_descs)); + nm_assert(link_descs[link_type].type_string); - return &link_descs[link_type]; + return &link_descs[link_type]; } static NMLinkType -_link_type_from_rtnl_type (const char *name) \ -{ - static const NMLinkType LIST[] = { - NM_LINK_TYPE_BOND, /* "bond" */ - NM_LINK_TYPE_BRIDGE, /* "bridge" */ - NM_LINK_TYPE_DUMMY, /* "dummy" */ - NM_LINK_TYPE_GRE, /* "gre" */ - NM_LINK_TYPE_GRETAP, /* "gretap" */ - NM_LINK_TYPE_IFB, /* "ifb" */ - NM_LINK_TYPE_IP6GRE, /* "ip6gre" */ - NM_LINK_TYPE_IP6GRETAP, /* "ip6gretap" */ - NM_LINK_TYPE_IP6TNL, /* "ip6tnl" */ - NM_LINK_TYPE_IPIP, /* "ipip" */ - NM_LINK_TYPE_MACSEC, /* "macsec" */ - NM_LINK_TYPE_MACVLAN, /* "macvlan" */ - NM_LINK_TYPE_MACVTAP, /* "macvtap" */ - NM_LINK_TYPE_OPENVSWITCH, /* "openvswitch" */ - NM_LINK_TYPE_SIT, /* "sit" */ - NM_LINK_TYPE_TEAM, /* "team" */ - NM_LINK_TYPE_TUN, /* "tun" */ - NM_LINK_TYPE_VETH, /* "veth" */ - NM_LINK_TYPE_VLAN, /* "vlan" */ - NM_LINK_TYPE_VRF, /* "vrf" */ - NM_LINK_TYPE_VXLAN, /* "vxlan" */ - NM_LINK_TYPE_WIMAX, /* "wimax" */ - NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ - }; - - nm_assert (name); - - if (NM_MORE_ASSERT_ONCE (5)) { - int i, j, k; - - for (i = 0; i < G_N_ELEMENTS (LIST); i++) { - nm_assert (_link_desc_from_link_type (LIST[i]) == &link_descs[LIST[i]]); - nm_assert (link_descs[LIST[i]].rtnl_type); - if (i > 0) - nm_assert (strcmp (link_descs[LIST[i - 1]].rtnl_type, link_descs[LIST[i]].rtnl_type) < 0); - } - for (i = 0; i < G_N_ELEMENTS (link_descs); i++) { - if (!link_descs[i].rtnl_type) - continue; - for (j = 0, k = 0; j < G_N_ELEMENTS (LIST); j++) - k += (LIST[j] == i); - nm_assert (k == 1); - } - } - - { - int imin = 0; - int imax = (G_N_ELEMENTS (LIST) - 1); - int imid = (G_N_ELEMENTS (LIST) - 1) / 2; - - for (;;) { - const int cmp = strcmp (link_descs[LIST[imid]].rtnl_type, name); - - if (G_UNLIKELY (cmp == 0)) - return LIST[imid]; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - - if (G_UNLIKELY (imin > imax)) - return NM_LINK_TYPE_NONE; - - imid = (imin + imax) / 2; - } - } +_link_type_from_rtnl_type(const char *name) +{ + static const NMLinkType LIST[] = { + NM_LINK_TYPE_BOND, /* "bond" */ + NM_LINK_TYPE_BRIDGE, /* "bridge" */ + NM_LINK_TYPE_DUMMY, /* "dummy" */ + NM_LINK_TYPE_GRE, /* "gre" */ + NM_LINK_TYPE_GRETAP, /* "gretap" */ + NM_LINK_TYPE_IFB, /* "ifb" */ + NM_LINK_TYPE_IP6GRE, /* "ip6gre" */ + NM_LINK_TYPE_IP6GRETAP, /* "ip6gretap" */ + NM_LINK_TYPE_IP6TNL, /* "ip6tnl" */ + NM_LINK_TYPE_IPIP, /* "ipip" */ + NM_LINK_TYPE_MACSEC, /* "macsec" */ + NM_LINK_TYPE_MACVLAN, /* "macvlan" */ + NM_LINK_TYPE_MACVTAP, /* "macvtap" */ + NM_LINK_TYPE_OPENVSWITCH, /* "openvswitch" */ + NM_LINK_TYPE_SIT, /* "sit" */ + NM_LINK_TYPE_TEAM, /* "team" */ + NM_LINK_TYPE_TUN, /* "tun" */ + NM_LINK_TYPE_VETH, /* "veth" */ + NM_LINK_TYPE_VLAN, /* "vlan" */ + NM_LINK_TYPE_VRF, /* "vrf" */ + NM_LINK_TYPE_VXLAN, /* "vxlan" */ + NM_LINK_TYPE_WIMAX, /* "wimax" */ + NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ + }; + + nm_assert(name); + + if (NM_MORE_ASSERT_ONCE(5)) { + int i, j, k; + + for (i = 0; i < G_N_ELEMENTS(LIST); i++) { + nm_assert(_link_desc_from_link_type(LIST[i]) == &link_descs[LIST[i]]); + nm_assert(link_descs[LIST[i]].rtnl_type); + if (i > 0) + nm_assert(strcmp(link_descs[LIST[i - 1]].rtnl_type, link_descs[LIST[i]].rtnl_type) + < 0); + } + for (i = 0; i < G_N_ELEMENTS(link_descs); i++) { + if (!link_descs[i].rtnl_type) + continue; + for (j = 0, k = 0; j < G_N_ELEMENTS(LIST); j++) + k += (LIST[j] == i); + nm_assert(k == 1); + } + } + + { + int imin = 0; + int imax = (G_N_ELEMENTS(LIST) - 1); + int imid = (G_N_ELEMENTS(LIST) - 1) / 2; + + for (;;) { + const int cmp = strcmp(link_descs[LIST[imid]].rtnl_type, name); + + if (G_UNLIKELY(cmp == 0)) + return LIST[imid]; + + if (cmp < 0) + imin = imid + 1; + else + imax = imid - 1; + + if (G_UNLIKELY(imin > imax)) + return NM_LINK_TYPE_NONE; + + imid = (imin + imax) / 2; + } + } } static NMLinkType -_link_type_from_devtype (const char *name) \ -{ - static const NMLinkType LIST[] = { - NM_LINK_TYPE_BNEP, /* "bluetooth" */ - NM_LINK_TYPE_BOND, /* "bond" */ - NM_LINK_TYPE_BRIDGE, /* "bridge" */ - NM_LINK_TYPE_PPP, /* "ppp" */ - NM_LINK_TYPE_VLAN, /* "vlan" */ - NM_LINK_TYPE_VRF, /* "vrf" */ - NM_LINK_TYPE_VXLAN, /* "vxlan" */ - NM_LINK_TYPE_WIMAX, /* "wimax" */ - NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ - NM_LINK_TYPE_WIFI, /* "wlan" */ - NM_LINK_TYPE_WWAN_NET, /* "wwan" */ - }; - - nm_assert (name); - - if (NM_MORE_ASSERT_ONCE (5)) { - int i, j, k; - - for (i = 0; i < G_N_ELEMENTS (LIST); i++) { - nm_assert (_link_desc_from_link_type (LIST[i]) == &link_descs[LIST[i]]); - nm_assert (link_descs[LIST[i]].devtype); - if (i > 0) - nm_assert (strcmp (link_descs[LIST[i - 1]].devtype, link_descs[LIST[i]].devtype) < 0); - } - for (i = 0; i < G_N_ELEMENTS (link_descs); i++) { - if (!link_descs[i].devtype) - continue; - for (j = 0, k = 0; j < G_N_ELEMENTS (LIST); j++) - k += (LIST[j] == i); - nm_assert (k == 1); - } - } - - { - int imin = 0; - int imax = (G_N_ELEMENTS (LIST) - 1); - int imid = (G_N_ELEMENTS (LIST) - 1) / 2; - - for (;;) { - const int cmp = strcmp (link_descs[LIST[imid]].devtype, name); - - if (G_UNLIKELY (cmp == 0)) - return LIST[imid]; - - if (cmp < 0) - imin = imid + 1; - else - imax = imid - 1; - - if (G_UNLIKELY (imin > imax)) - return NM_LINK_TYPE_NONE; - - imid = (imin + imax) / 2; - } - } +_link_type_from_devtype(const char *name) +{ + static const NMLinkType LIST[] = { + NM_LINK_TYPE_BNEP, /* "bluetooth" */ + NM_LINK_TYPE_BOND, /* "bond" */ + NM_LINK_TYPE_BRIDGE, /* "bridge" */ + NM_LINK_TYPE_PPP, /* "ppp" */ + NM_LINK_TYPE_VLAN, /* "vlan" */ + NM_LINK_TYPE_VRF, /* "vrf" */ + NM_LINK_TYPE_VXLAN, /* "vxlan" */ + NM_LINK_TYPE_WIMAX, /* "wimax" */ + NM_LINK_TYPE_WIREGUARD, /* "wireguard" */ + NM_LINK_TYPE_WIFI, /* "wlan" */ + NM_LINK_TYPE_WWAN_NET, /* "wwan" */ + }; + + nm_assert(name); + + if (NM_MORE_ASSERT_ONCE(5)) { + int i, j, k; + + for (i = 0; i < G_N_ELEMENTS(LIST); i++) { + nm_assert(_link_desc_from_link_type(LIST[i]) == &link_descs[LIST[i]]); + nm_assert(link_descs[LIST[i]].devtype); + if (i > 0) + nm_assert(strcmp(link_descs[LIST[i - 1]].devtype, link_descs[LIST[i]].devtype) < 0); + } + for (i = 0; i < G_N_ELEMENTS(link_descs); i++) { + if (!link_descs[i].devtype) + continue; + for (j = 0, k = 0; j < G_N_ELEMENTS(LIST); j++) + k += (LIST[j] == i); + nm_assert(k == 1); + } + } + + { + int imin = 0; + int imax = (G_N_ELEMENTS(LIST) - 1); + int imid = (G_N_ELEMENTS(LIST) - 1) / 2; + + for (;;) { + const int cmp = strcmp(link_descs[LIST[imid]].devtype, name); + + if (G_UNLIKELY(cmp == 0)) + return LIST[imid]; + + if (cmp < 0) + imin = imid + 1; + else + imax = imid - 1; + + if (G_UNLIKELY(imin > imax)) + return NM_LINK_TYPE_NONE; + + imid = (imin + imax) / 2; + } + } } static const char * -nm_link_type_to_rtnl_type_string (NMLinkType link_type) +nm_link_type_to_rtnl_type_string(NMLinkType link_type) { - return _link_desc_from_link_type (link_type)->rtnl_type; + return _link_desc_from_link_type(link_type)->rtnl_type; } const char * -nm_link_type_to_string (NMLinkType link_type) +nm_link_type_to_string(NMLinkType link_type) { - return _link_desc_from_link_type (link_type)->type_string; + return _link_desc_from_link_type(link_type)->type_string; } /****************************************************************** @@ -841,80 +853,79 @@ nm_link_type_to_string (NMLinkType link_type) * the uint32 counter wraps every 497 days of uptime, so we have to compensate * for that. */ static gint64 -_timestamp_nl_to_ms (guint32 timestamp_nl, gint64 monotonic_ms) +_timestamp_nl_to_ms(guint32 timestamp_nl, gint64 monotonic_ms) { - const gint64 WRAP_INTERVAL = (((gint64) G_MAXUINT32) + 1) * (1000 / 100); - gint64 timestamp_nl_ms; + const gint64 WRAP_INTERVAL = (((gint64) G_MAXUINT32) + 1) * (1000 / 100); + gint64 timestamp_nl_ms; - /* convert timestamp from 1/100th of a second to msec. */ - timestamp_nl_ms = ((gint64) timestamp_nl) * (1000 / 100); + /* convert timestamp from 1/100th of a second to msec. */ + timestamp_nl_ms = ((gint64) timestamp_nl) * (1000 / 100); - /* timestamp wraps every 497 days. Try to compensate for that.*/ - if (timestamp_nl_ms > monotonic_ms) { - /* timestamp_nl_ms is in the future. Truncate it to *now* */ - timestamp_nl_ms = monotonic_ms; - } else if (monotonic_ms >= WRAP_INTERVAL) { - timestamp_nl_ms += (monotonic_ms / WRAP_INTERVAL) * WRAP_INTERVAL; - if (timestamp_nl_ms > monotonic_ms) - timestamp_nl_ms -= WRAP_INTERVAL; - } + /* timestamp wraps every 497 days. Try to compensate for that.*/ + if (timestamp_nl_ms > monotonic_ms) { + /* timestamp_nl_ms is in the future. Truncate it to *now* */ + timestamp_nl_ms = monotonic_ms; + } else if (monotonic_ms >= WRAP_INTERVAL) { + timestamp_nl_ms += (monotonic_ms / WRAP_INTERVAL) * WRAP_INTERVAL; + if (timestamp_nl_ms > monotonic_ms) + timestamp_nl_ms -= WRAP_INTERVAL; + } - return timestamp_nl_ms; + return timestamp_nl_ms; } static guint32 -_addrtime_timestamp_to_nm (guint32 timestamp, gint32 *out_now_nm) +_addrtime_timestamp_to_nm(guint32 timestamp, gint32 *out_now_nm) { - gint64 now_nl; - gint64 now_nm; - gint64 result; + gint64 now_nl; + gint64 now_nm; + gint64 result; - /* timestamp is unset. Default to 1. */ - if (!timestamp) { - NM_SET_OUT (out_now_nm, 0); - return 1; - } + /* timestamp is unset. Default to 1. */ + if (!timestamp) { + NM_SET_OUT(out_now_nm, 0); + return 1; + } - /* do all the calculations in milliseconds scale */ + /* do all the calculations in milliseconds scale */ - now_nm = nm_utils_get_monotonic_timestamp_msec (); - now_nl = nm_utils_clock_gettime_msec (CLOCK_MONOTONIC); + now_nm = nm_utils_get_monotonic_timestamp_msec(); + now_nl = nm_utils_clock_gettime_msec(CLOCK_MONOTONIC); - nm_assert (now_nm >= 1000); - nm_assert (now_nl >= 0); + nm_assert(now_nm >= 1000); + nm_assert(now_nl >= 0); - result = now_nm - (now_nl - _timestamp_nl_to_ms (timestamp, now_nl)); + result = now_nm - (now_nl - _timestamp_nl_to_ms(timestamp, now_nl)); - NM_SET_OUT (out_now_nm, now_nm / 1000); + NM_SET_OUT(out_now_nm, now_nm / 1000); - /* converting the timestamp into nm_utils_get_monotonic_timestamp_msec() scale is - * a good guess but fails in the following situations: - * - * - If the address existed before start of the process, the timestamp in nm scale would - * be negative or zero. In this case we default to 1. - * - during hibernation, the CLOCK_MONOTONIC/timestamp drifts from - * nm_utils_get_monotonic_timestamp_msec() scale. - */ - if (result <= 1000) - return 1; + /* converting the timestamp into nm_utils_get_monotonic_timestamp_msec() scale is + * a good guess but fails in the following situations: + * + * - If the address existed before start of the process, the timestamp in nm scale would + * be negative or zero. In this case we default to 1. + * - during hibernation, the CLOCK_MONOTONIC/timestamp drifts from + * nm_utils_get_monotonic_timestamp_msec() scale. + */ + if (result <= 1000) + return 1; - if (result > now_nm) - return now_nm / 1000; + if (result > now_nm) + return now_nm / 1000; - return result / 1000; + return result / 1000; } static guint32 -_addrtime_extend_lifetime (guint32 lifetime, guint32 seconds) +_addrtime_extend_lifetime(guint32 lifetime, guint32 seconds) { - guint64 v; + guint64 v; - if ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT - || seconds == 0) - return lifetime; + if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT || seconds == 0) + return lifetime; - v = (guint64) lifetime + (guint64) seconds; - return MIN (v, NM_PLATFORM_LIFETIME_PERMANENT - 1); + v = (guint64) lifetime + (guint64) seconds; + return MIN(v, NM_PLATFORM_LIFETIME_PERMANENT - 1); } /* The rtnl_addr object contains relative lifetimes @valid and @preferred @@ -930,61 +941,58 @@ _addrtime_extend_lifetime (guint32 lifetime, guint32 seconds) * via netlink, the lifetimes keep counting down. **/ static void -_addrtime_get_lifetimes (guint32 timestamp, - guint32 lifetime, - guint32 preferred, - guint32 *out_timestamp, - guint32 *out_lifetime, - guint32 *out_preferred) -{ - gint32 now; - - if ( lifetime != NM_PLATFORM_LIFETIME_PERMANENT - || preferred != NM_PLATFORM_LIFETIME_PERMANENT) { - if (preferred > lifetime) - preferred = lifetime; - timestamp = _addrtime_timestamp_to_nm (timestamp, &now); - - if (now == 0) { - /* strange. failed to detect the last-update time and assumed that timestamp is 1. */ - nm_assert (timestamp == 1); - now = nm_utils_get_monotonic_timestamp_sec (); - } - if (timestamp < now) { - guint32 diff = now - timestamp; - - lifetime = _addrtime_extend_lifetime (lifetime, diff); - preferred = _addrtime_extend_lifetime (preferred, diff); - } else - nm_assert (timestamp == now); - } else - timestamp = 0; - *out_timestamp = timestamp; - *out_lifetime = lifetime; - *out_preferred = preferred; +_addrtime_get_lifetimes(guint32 timestamp, + guint32 lifetime, + guint32 preferred, + guint32 *out_timestamp, + guint32 *out_lifetime, + guint32 *out_preferred) +{ + gint32 now; + + if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT || preferred != NM_PLATFORM_LIFETIME_PERMANENT) { + if (preferred > lifetime) + preferred = lifetime; + timestamp = _addrtime_timestamp_to_nm(timestamp, &now); + + if (now == 0) { + /* strange. failed to detect the last-update time and assumed that timestamp is 1. */ + nm_assert(timestamp == 1); + now = nm_utils_get_monotonic_timestamp_sec(); + } + if (timestamp < now) { + guint32 diff = now - timestamp; + + lifetime = _addrtime_extend_lifetime(lifetime, diff); + preferred = _addrtime_extend_lifetime(preferred, diff); + } else + nm_assert(timestamp == now); + } else + timestamp = 0; + *out_timestamp = timestamp; + *out_lifetime = lifetime; + *out_preferred = preferred; } /*****************************************************************************/ static const NMPObject * -_lookup_cached_link (const NMPCache *cache, - int ifindex, - gboolean *completed_from_cache, - const NMPObject **link_cached) +_lookup_cached_link(const NMPCache * cache, + int ifindex, + gboolean * completed_from_cache, + const NMPObject **link_cached) { - const NMPObject *obj; + const NMPObject *obj; - nm_assert (completed_from_cache && link_cached); + nm_assert(completed_from_cache && link_cached); - if (!*completed_from_cache) { - obj = ifindex > 0 && cache - ? nmp_cache_lookup_link (cache, ifindex) - : NULL; + if (!*completed_from_cache) { + obj = ifindex > 0 && cache ? nmp_cache_lookup_link(cache, ifindex) : NULL; - *link_cached = obj; - *completed_from_cache = TRUE; - } - return *link_cached; + *link_cached = obj; + *completed_from_cache = TRUE; + } + return *link_cached; } /*****************************************************************************/ @@ -992,217 +1000,207 @@ _lookup_cached_link (const NMPCache *cache, #define DEVTYPE_PREFIX "DEVTYPE=" static char * -_linktype_read_devtype (int dirfd) -{ - gs_free char *contents = NULL; - char *cont, *end; - - nm_assert (dirfd >= 0); - - if (!nm_utils_file_get_contents (dirfd, - "uevent", - 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, - NULL, - NULL, - NULL)) - return NULL; - for (cont = contents; cont; cont = end) { - end = strpbrk (cont, "\r\n"); - if (end) - *end++ = '\0'; - if (strncmp (cont, DEVTYPE_PREFIX, NM_STRLEN (DEVTYPE_PREFIX)) == 0) { - cont += NM_STRLEN (DEVTYPE_PREFIX); - memmove (contents, cont, strlen (cont) + 1); - return g_steal_pointer (&contents); - } - } - return NULL; +_linktype_read_devtype(int dirfd) +{ + gs_free char *contents = NULL; + char * cont, *end; + + nm_assert(dirfd >= 0); + + if (!nm_utils_file_get_contents(dirfd, + "uevent", + 1 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &contents, + NULL, + NULL, + NULL)) + return NULL; + for (cont = contents; cont; cont = end) { + end = strpbrk(cont, "\r\n"); + if (end) + *end++ = '\0'; + if (strncmp(cont, DEVTYPE_PREFIX, NM_STRLEN(DEVTYPE_PREFIX)) == 0) { + cont += NM_STRLEN(DEVTYPE_PREFIX); + memmove(contents, cont, strlen(cont) + 1); + return g_steal_pointer(&contents); + } + } + return NULL; } static NMLinkType -_linktype_get_type (NMPlatform *platform, - const NMPCache *cache, - const char *kind, - int ifindex, - const char *ifname, - unsigned flags, - unsigned arptype, - gboolean *completed_from_cache, - const NMPObject **link_cached, - const char **out_kind) -{ - NMLinkType link_type; - - NMTST_ASSERT_PLATFORM_NETNS_CURRENT (platform); - nm_assert (ifname); - nm_assert (_link_type_from_devtype ("wlan") == NM_LINK_TYPE_WIFI); - nm_assert (_link_type_from_rtnl_type ("bond") == NM_LINK_TYPE_BOND); - - if (completed_from_cache) { - const NMPObject *obj; - - obj = _lookup_cached_link (cache, ifindex, completed_from_cache, link_cached); - - /* If we detected the link type before, we stick to that - * decision unless the "kind" or "name" changed. If "name" changed, - * it means that their type may not have been determined correctly - * due to race conditions while accessing sysfs. - * - * This way, we save edditional ethtool/sysctl lookups, but moreover, - * we keep the linktype stable and don't change it as long as the link - * exists. - * - * Note that kernel *can* reuse the ifindex (on integer overflow, and - * when moving interfce to other netns). Thus here there is a tiny potential - * of messing stuff up. */ - if ( obj - && obj->_link.netlink.is_in_netlink - && !NM_IN_SET (obj->link.type, NM_LINK_TYPE_UNKNOWN, NM_LINK_TYPE_NONE) - && nm_streq (ifname, obj->link.name) - && ( !kind - || nm_streq0 (kind, obj->link.kind))) { - nm_assert (obj->link.kind == g_intern_string (obj->link.kind)); - *out_kind = obj->link.kind; - return obj->link.type; - } - } - - /* we intern kind to not require us to keep the pointer alive. Essentially - * leaking it in a global cache. That should be safe enough, because the - * kind comes only from kernel messages, which depend on the number of - * available drivers. So, there is not the danger that we leak uncontrolled - * many kinds. */ - *out_kind = g_intern_string (kind); - - if (kind) { - link_type = _link_type_from_rtnl_type (kind); - if (link_type != NM_LINK_TYPE_NONE) - return link_type; - } - - if (arptype == ARPHRD_LOOPBACK) - return NM_LINK_TYPE_LOOPBACK; - else if (arptype == ARPHRD_INFINIBAND) - return NM_LINK_TYPE_INFINIBAND; - else if (arptype == ARPHRD_SIT) - return NM_LINK_TYPE_SIT; - else if (arptype == ARPHRD_TUNNEL6) - return NM_LINK_TYPE_IP6TNL; - else if (arptype == ARPHRD_PPP) - return NM_LINK_TYPE_PPP; - else if (arptype == ARPHRD_IEEE802154) - return NM_LINK_TYPE_WPAN; - else if (arptype == ARPHRD_6LOWPAN) - return NM_LINK_TYPE_6LOWPAN; - - { - NMPUtilsEthtoolDriverInfo driver_info; - - /* Fallback OVS detection for kernel <= 3.16 */ - if (nmp_utils_ethtool_get_driver_info (ifindex, &driver_info)) { - if (nm_streq (driver_info.driver, "openvswitch")) - return NM_LINK_TYPE_OPENVSWITCH; - - if (arptype == 256) { - /* Some s390 CTC-type devices report 256 for the encapsulation type - * for some reason, but we need to call them Ethernet. - */ - if (nm_streq (driver_info.driver, "ctcm")) - return NM_LINK_TYPE_ETHERNET; - } - } - } - - { - nm_auto_close int dirfd = -1; - gs_free char *devtype = NULL; - char ifname_verified[IFNAMSIZ]; - - dirfd = nmp_utils_sysctl_open_netdir (ifindex, ifname, ifname_verified); - if (dirfd >= 0) { - if (faccessat (dirfd, "anycast_mask", F_OK, 0) == 0) - return NM_LINK_TYPE_OLPC_MESH; - - devtype = _linktype_read_devtype (dirfd); - if (devtype) { - link_type = _link_type_from_devtype (devtype); - if (link_type != NM_LINK_TYPE_NONE) { - if ( link_type == NM_LINK_TYPE_BNEP - && arptype != ARPHRD_ETHER) { - /* Both BNEP and 6lowpan use DEVTYPE=bluetooth, so we must - * use arptype to distinguish between them. - */ - } else - return link_type; - } - } - - /* Fallback for drivers that don't call SET_NETDEV_DEVTYPE() */ - if (nm_wifi_utils_is_wifi (dirfd, ifname_verified)) - return NM_LINK_TYPE_WIFI; - } - - if (arptype == ARPHRD_ETHER) { - /* Misc non-upstream WWAN drivers. rmnet is Qualcomm's proprietary - * modem interface, ccmni is MediaTek's. FIXME: these drivers should - * really set devtype=WWAN. - */ - if (g_str_has_prefix (ifname, "rmnet") || - g_str_has_prefix (ifname, "rev_rmnet") || - g_str_has_prefix (ifname, "ccmni")) - return NM_LINK_TYPE_WWAN_NET; - - /* Standard wired ethernet interfaces don't report an rtnl_link_type, so - * only allow fallback to Ethernet if no type is given. This should - * prevent future virtual network drivers from being treated as Ethernet - * when they should be Generic instead. - */ - if (!kind && !devtype) - return NM_LINK_TYPE_ETHERNET; - - /* The USB gadget interfaces behave and look like ordinary ethernet devices - * aside from the DEVTYPE. */ - if (nm_streq0 (devtype, "gadget")) - return NM_LINK_TYPE_ETHERNET; - - /* Distributed Switch Architecture switch chips */ - if (nm_streq0 (devtype, "dsa")) - return NM_LINK_TYPE_ETHERNET; - } - } - - return NM_LINK_TYPE_UNKNOWN; +_linktype_get_type(NMPlatform * platform, + const NMPCache * cache, + const char * kind, + int ifindex, + const char * ifname, + unsigned flags, + unsigned arptype, + gboolean * completed_from_cache, + const NMPObject **link_cached, + const char ** out_kind) +{ + NMLinkType link_type; + + NMTST_ASSERT_PLATFORM_NETNS_CURRENT(platform); + nm_assert(ifname); + nm_assert(_link_type_from_devtype("wlan") == NM_LINK_TYPE_WIFI); + nm_assert(_link_type_from_rtnl_type("bond") == NM_LINK_TYPE_BOND); + + if (completed_from_cache) { + const NMPObject *obj; + + obj = _lookup_cached_link(cache, ifindex, completed_from_cache, link_cached); + + /* If we detected the link type before, we stick to that + * decision unless the "kind" or "name" changed. If "name" changed, + * it means that their type may not have been determined correctly + * due to race conditions while accessing sysfs. + * + * This way, we save additional ethtool/sysctl lookups, but moreover, + * we keep the linktype stable and don't change it as long as the link + * exists. + * + * Note that kernel *can* reuse the ifindex (on integer overflow, and + * when moving interface to other netns). Thus here there is a tiny potential + * of messing stuff up. */ + if (obj && obj->_link.netlink.is_in_netlink + && !NM_IN_SET(obj->link.type, NM_LINK_TYPE_UNKNOWN, NM_LINK_TYPE_NONE) + && nm_streq(ifname, obj->link.name) && (!kind || nm_streq0(kind, obj->link.kind))) { + nm_assert(obj->link.kind == g_intern_string(obj->link.kind)); + *out_kind = obj->link.kind; + return obj->link.type; + } + } + + /* we intern kind to not require us to keep the pointer alive. Essentially + * leaking it in a global cache. That should be safe enough, because the + * kind comes only from kernel messages, which depend on the number of + * available drivers. So, there is not the danger that we leak uncontrolled + * many kinds. */ + *out_kind = g_intern_string(kind); + + if (kind) { + link_type = _link_type_from_rtnl_type(kind); + if (link_type != NM_LINK_TYPE_NONE) + return link_type; + } + + if (arptype == ARPHRD_LOOPBACK) + return NM_LINK_TYPE_LOOPBACK; + else if (arptype == ARPHRD_INFINIBAND) + return NM_LINK_TYPE_INFINIBAND; + else if (arptype == ARPHRD_SIT) + return NM_LINK_TYPE_SIT; + else if (arptype == ARPHRD_TUNNEL6) + return NM_LINK_TYPE_IP6TNL; + else if (arptype == ARPHRD_PPP) + return NM_LINK_TYPE_PPP; + else if (arptype == ARPHRD_IEEE802154) + return NM_LINK_TYPE_WPAN; + else if (arptype == ARPHRD_6LOWPAN) + return NM_LINK_TYPE_6LOWPAN; + + { + NMPUtilsEthtoolDriverInfo driver_info; + + /* Fallback OVS detection for kernel <= 3.16 */ + if (nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) { + if (nm_streq(driver_info.driver, "openvswitch")) + return NM_LINK_TYPE_OPENVSWITCH; + + if (arptype == 256) { + /* Some s390 CTC-type devices report 256 for the encapsulation type + * for some reason, but we need to call them Ethernet. + */ + if (nm_streq(driver_info.driver, "ctcm")) + return NM_LINK_TYPE_ETHERNET; + } + } + } + + { + nm_auto_close int dirfd = -1; + gs_free char * devtype = NULL; + char ifname_verified[IFNAMSIZ]; + + dirfd = nmp_utils_sysctl_open_netdir(ifindex, ifname, ifname_verified); + if (dirfd >= 0) { + if (faccessat(dirfd, "anycast_mask", F_OK, 0) == 0) + return NM_LINK_TYPE_OLPC_MESH; + + devtype = _linktype_read_devtype(dirfd); + if (devtype) { + link_type = _link_type_from_devtype(devtype); + if (link_type != NM_LINK_TYPE_NONE) { + if (link_type == NM_LINK_TYPE_BNEP && arptype != ARPHRD_ETHER) { + /* Both BNEP and 6lowpan use DEVTYPE=bluetooth, so we must + * use arptype to distinguish between them. + */ + } else + return link_type; + } + } + + /* Fallback for drivers that don't call SET_NETDEV_DEVTYPE() */ + if (nm_wifi_utils_is_wifi(dirfd, ifname_verified)) + return NM_LINK_TYPE_WIFI; + } + + if (arptype == ARPHRD_ETHER) { + /* Misc non-upstream WWAN drivers. rmnet is Qualcomm's proprietary + * modem interface, ccmni is MediaTek's. FIXME: these drivers should + * really set devtype=WWAN. + */ + if (g_str_has_prefix(ifname, "rmnet") || g_str_has_prefix(ifname, "rev_rmnet") + || g_str_has_prefix(ifname, "ccmni")) + return NM_LINK_TYPE_WWAN_NET; + + /* Standard wired ethernet interfaces don't report an rtnl_link_type, so + * only allow fallback to Ethernet if no type is given. This should + * prevent future virtual network drivers from being treated as Ethernet + * when they should be Generic instead. + */ + if (!kind && !devtype) + return NM_LINK_TYPE_ETHERNET; + + /* The USB gadget interfaces behave and look like ordinary ethernet devices + * aside from the DEVTYPE. */ + if (nm_streq0(devtype, "gadget")) + return NM_LINK_TYPE_ETHERNET; + + /* Distributed Switch Architecture switch chips */ + if (nm_streq0(devtype, "dsa")) + return NM_LINK_TYPE_ETHERNET; + } + } + + return NM_LINK_TYPE_UNKNOWN; } /****************************************************************** * libnl unility functions and wrappers ******************************************************************/ -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN ((nmsg)->nlmsg_len))) +#define NLMSG_TAIL(nmsg) ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) /* copied from iproute2's addattr_l(). */ static gboolean -_nl_addattr_l (struct nlmsghdr *n, - int maxlen, - int type, - const void *data, - int alen) +_nl_addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) { - int len = RTA_LENGTH (alen); - struct rtattr *rta; + int len = RTA_LENGTH(alen); + struct rtattr *rta; - if (NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len) > maxlen) - return FALSE; + if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) + return FALSE; - rta = NLMSG_TAIL (n); - rta->rta_type = type; - rta->rta_len = len; - memcpy (RTA_DATA (rta), data, alen); - n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len); - return TRUE; + rta = NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + return TRUE; } /****************************************************************** @@ -1210,143 +1208,245 @@ _nl_addattr_l (struct nlmsghdr *n, ******************************************************************/ #define _check_addr_or_return_val(tb, attr, addr_len, ret_val) \ - ({ \ - const struct nlattr *__t = (tb)[(attr)]; \ - \ - if (__t) { \ - if (nla_len (__t) != (addr_len)) { \ - return ret_val; \ - } \ - } \ - !!__t; \ - }) + ({ \ + const struct nlattr *__t = (tb)[(attr)]; \ + \ + if (__t) { \ + if (nla_len(__t) != (addr_len)) { \ + return ret_val; \ + } \ + } \ + !!__t; \ + }) #define _check_addr_or_return_null(tb, attr, addr_len) \ - _check_addr_or_return_val (tb, attr, addr_len, NULL) + _check_addr_or_return_val(tb, attr, addr_len, NULL) /*****************************************************************************/ /* Copied and heavily modified from libnl3's inet6_parse_protinfo(). */ static gboolean -_parse_af_inet6 (NMPlatform *platform, - struct nlattr *attr, - NMUtilsIPv6IfaceId *out_token, - gboolean *out_token_valid, - guint8 *out_addr_gen_mode_inv, - gboolean *out_addr_gen_mode_valid) -{ - static const struct nla_policy policy[] = { - [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, - [IFLA_INET6_CACHEINFO] = { .minlen = nm_offsetofend (struct ifla_cacheinfo, retrans_time) }, - [IFLA_INET6_CONF] = { .minlen = 4 }, - [IFLA_INET6_STATS] = { .minlen = 8 }, - [IFLA_INET6_ICMP6STATS] = { .minlen = 8 }, - [IFLA_INET6_TOKEN] = { .minlen = sizeof (struct in6_addr) }, - [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - struct in6_addr i6_token; - gboolean token_valid = FALSE; - gboolean addr_gen_mode_valid = FALSE; - guint8 i6_addr_gen_mode_inv = 0; - - if (nla_parse_nested_arr (tb, attr, policy) < 0) - return FALSE; - - if (tb[IFLA_INET6_CONF] && nla_len (tb[IFLA_INET6_CONF]) % 4) - return FALSE; - if (tb[IFLA_INET6_STATS] && nla_len (tb[IFLA_INET6_STATS]) % 8) - return FALSE; - if (tb[IFLA_INET6_ICMP6STATS] && nla_len (tb[IFLA_INET6_ICMP6STATS]) % 8) - return FALSE; - - if (_check_addr_or_return_val (tb, IFLA_INET6_TOKEN, sizeof (struct in6_addr), FALSE)) { - nla_memcpy (&i6_token, tb[IFLA_INET6_TOKEN], sizeof (struct in6_addr)); - token_valid = TRUE; - } - - /* Hack to detect support addrgenmode of the kernel. We only parse - * netlink messages that we receive from kernel, hence this check - * is valid. */ - if (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { - /* IFLA_INET6_ADDR_GEN_MODE was added in kernel 3.17, dated 5 October, 2014. */ - _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL, - tb[IFLA_INET6_ADDR_GEN_MODE] ? 1 : -1); - } - - if (tb[IFLA_INET6_ADDR_GEN_MODE]) { - i6_addr_gen_mode_inv = _nm_platform_uint8_inv (nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE])); - if (i6_addr_gen_mode_inv == 0) { - /* an inverse addrgenmode of zero is unexpected. We need to reserve zero - * to signal "unset". */ - return FALSE; - } - addr_gen_mode_valid = TRUE; - } - - if (token_valid) { - *out_token_valid = token_valid; - nm_utils_ipv6_interface_identifier_get_from_addr (out_token, &i6_token); - } - if (addr_gen_mode_valid) { - *out_addr_gen_mode_valid = addr_gen_mode_valid; - *out_addr_gen_mode_inv = i6_addr_gen_mode_inv; - } - return TRUE; +_parse_af_inet6(NMPlatform * platform, + struct nlattr * attr, + NMUtilsIPv6IfaceId *out_token, + gboolean * out_token_valid, + guint8 * out_addr_gen_mode_inv, + gboolean * out_addr_gen_mode_valid) +{ + static const struct nla_policy policy[] = { + [IFLA_INET6_FLAGS] = {.type = NLA_U32}, + [IFLA_INET6_CACHEINFO] = {.minlen = nm_offsetofend(struct ifla_cacheinfo, retrans_time)}, + [IFLA_INET6_CONF] = {.minlen = 4}, + [IFLA_INET6_STATS] = {.minlen = 8}, + [IFLA_INET6_ICMP6STATS] = {.minlen = 8}, + [IFLA_INET6_TOKEN] = {.minlen = sizeof(struct in6_addr)}, + [IFLA_INET6_ADDR_GEN_MODE] = {.type = NLA_U8}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + struct in6_addr i6_token; + gboolean token_valid = FALSE; + gboolean addr_gen_mode_valid = FALSE; + guint8 i6_addr_gen_mode_inv = 0; + + if (nla_parse_nested_arr(tb, attr, policy) < 0) + return FALSE; + + if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4) + return FALSE; + if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8) + return FALSE; + if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8) + return FALSE; + + if (_check_addr_or_return_val(tb, IFLA_INET6_TOKEN, sizeof(struct in6_addr), FALSE)) { + nla_memcpy(&i6_token, tb[IFLA_INET6_TOKEN], sizeof(struct in6_addr)); + token_valid = TRUE; + } + + /* Hack to detect support addrgenmode of the kernel. We only parse + * netlink messages that we receive from kernel, hence this check + * is valid. */ + if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { + /* IFLA_INET6_ADDR_GEN_MODE was added in kernel 3.17, dated 5 October, 2014. */ + _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL, + tb[IFLA_INET6_ADDR_GEN_MODE] ? 1 : -1); + } + + if (tb[IFLA_INET6_ADDR_GEN_MODE]) { + i6_addr_gen_mode_inv = _nm_platform_uint8_inv(nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE])); + if (i6_addr_gen_mode_inv == 0) { + /* an inverse addrgenmode of zero is unexpected. We need to reserve zero + * to signal "unset". */ + return FALSE; + } + addr_gen_mode_valid = TRUE; + } + + if (token_valid) { + *out_token_valid = token_valid; + nm_utils_ipv6_interface_identifier_get_from_addr(out_token, &i6_token); + } + if (addr_gen_mode_valid) { + *out_addr_gen_mode_valid = addr_gen_mode_valid; + *out_addr_gen_mode_inv = i6_addr_gen_mode_inv; + } + return TRUE; } /*****************************************************************************/ static NMPObject * -_parse_lnk_gre (const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_GRE_LINK] = { .type = NLA_U32 }, - [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, - [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, - [IFLA_GRE_IKEY] = { .type = NLA_U32 }, - [IFLA_GRE_OKEY] = { .type = NLA_U32 }, - [IFLA_GRE_LOCAL] = { .type = NLA_U32 }, - [IFLA_GRE_REMOTE] = { .type = NLA_U32 }, - [IFLA_GRE_TTL] = { .type = NLA_U8 }, - [IFLA_GRE_TOS] = { .type = NLA_U8 }, - [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - NMPlatformLnkGre *props; - gboolean is_tap; - - if ( !info_data - || !kind) - return NULL; - - if (nm_streq (kind, "gretap")) - is_tap = TRUE; - else if (nm_streq (kind, "gre")) - is_tap = FALSE; - else - return NULL; - - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new (is_tap ? NMP_OBJECT_TYPE_LNK_GRETAP : NMP_OBJECT_TYPE_LNK_GRE, NULL); - props = &obj->lnk_gre; - - props->parent_ifindex = tb[IFLA_GRE_LINK] ? nla_get_u32 (tb[IFLA_GRE_LINK]) : 0; - props->input_flags = tb[IFLA_GRE_IFLAGS] ? ntohs (nla_get_u16 (tb[IFLA_GRE_IFLAGS])) : 0; - props->output_flags = tb[IFLA_GRE_OFLAGS] ? ntohs (nla_get_u16 (tb[IFLA_GRE_OFLAGS])) : 0; - props->input_key = tb[IFLA_GRE_IKEY] ? ntohl (nla_get_u32 (tb[IFLA_GRE_IKEY])) : 0; - props->output_key = tb[IFLA_GRE_OKEY] ? ntohl (nla_get_u32 (tb[IFLA_GRE_OKEY])) : 0; - props->local = tb[IFLA_GRE_LOCAL] ? nla_get_u32 (tb[IFLA_GRE_LOCAL]) : 0; - props->remote = tb[IFLA_GRE_REMOTE] ? nla_get_u32 (tb[IFLA_GRE_REMOTE]) : 0; - props->tos = tb[IFLA_GRE_TOS] ? nla_get_u8 (tb[IFLA_GRE_TOS]) : 0; - props->ttl = tb[IFLA_GRE_TTL] ? nla_get_u8 (tb[IFLA_GRE_TTL]) : 0; - props->path_mtu_discovery = !tb[IFLA_GRE_PMTUDISC] || !!nla_get_u8 (tb[IFLA_GRE_PMTUDISC]); - props->is_tap = is_tap; - - return obj; +_parse_lnk_bridge(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_BR_FORWARD_DELAY] = {.type = NLA_U32}, + [IFLA_BR_HELLO_TIME] = {.type = NLA_U32}, + [IFLA_BR_MAX_AGE] = {.type = NLA_U32}, + [IFLA_BR_AGEING_TIME] = {.type = NLA_U32}, + [IFLA_BR_STP_STATE] = {.type = NLA_U32}, + [IFLA_BR_PRIORITY] = {.type = NLA_U16}, + [IFLA_BR_VLAN_PROTOCOL] = {.type = NLA_U16}, + [IFLA_BR_VLAN_STATS_ENABLED] = {.type = NLA_U8}, + [IFLA_BR_GROUP_FWD_MASK] = {.type = NLA_U16}, + [IFLA_BR_GROUP_ADDR] = {.minlen = sizeof(NMEtherAddr)}, + [IFLA_BR_MCAST_SNOOPING] = {.type = NLA_U8}, + [IFLA_BR_MCAST_ROUTER] = {.type = NLA_U8}, + [IFLA_BR_MCAST_QUERY_USE_IFADDR] = {.type = NLA_U8}, + [IFLA_BR_MCAST_QUERIER] = {.type = NLA_U8}, + [IFLA_BR_MCAST_HASH_MAX] = {.type = NLA_U32}, + [IFLA_BR_MCAST_LAST_MEMBER_CNT] = {.type = NLA_U32}, + [IFLA_BR_MCAST_STARTUP_QUERY_CNT] = {.type = NLA_U32}, + [IFLA_BR_MCAST_LAST_MEMBER_INTVL] = {.type = NLA_U64}, + [IFLA_BR_MCAST_MEMBERSHIP_INTVL] = {.type = NLA_U64}, + [IFLA_BR_MCAST_QUERIER_INTVL] = {.type = NLA_U64}, + [IFLA_BR_MCAST_QUERY_INTVL] = {.type = NLA_U64}, + [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = {.type = NLA_U64}, + [IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = {.type = NLA_U64}, + }; + NMPlatformLnkBridge *props; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + + if (!info_data || !nm_streq0(kind, "bridge")) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_BRIDGE, NULL); + + props = &obj->lnk_bridge; + *props = nm_platform_lnk_bridge_default; + + if (!_nm_platform_kernel_support_detected( + NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED)) { + /* IFLA_BR_VLAN_STATS_ENABLED was added in kernel 4.10 on April 30, 2016. + * See commit 6dada9b10a0818ba72c249526a742c8c41274a73. */ + _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED, + tb[IFLA_BR_VLAN_STATS_ENABLED] ? 1 : -1); + } + + if (tb[IFLA_BR_FORWARD_DELAY]) + props->forward_delay = nla_get_u32(tb[IFLA_BR_FORWARD_DELAY]); + if (tb[IFLA_BR_HELLO_TIME]) + props->hello_time = nla_get_u32(tb[IFLA_BR_HELLO_TIME]); + if (tb[IFLA_BR_MAX_AGE]) + props->max_age = nla_get_u32(tb[IFLA_BR_MAX_AGE]); + if (tb[IFLA_BR_AGEING_TIME]) + props->ageing_time = nla_get_u32(tb[IFLA_BR_AGEING_TIME]); + if (tb[IFLA_BR_STP_STATE]) + props->stp_state = !!nla_get_u32(tb[IFLA_BR_STP_STATE]); + if (tb[IFLA_BR_PRIORITY]) + props->priority = nla_get_u16(tb[IFLA_BR_PRIORITY]); + if (tb[IFLA_BR_VLAN_PROTOCOL]) + props->vlan_protocol = ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL])); + if (tb[IFLA_BR_VLAN_STATS_ENABLED]) + props->vlan_stats_enabled = nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]); + if (tb[IFLA_BR_GROUP_FWD_MASK]) + props->group_fwd_mask = nla_get_u16(tb[IFLA_BR_GROUP_FWD_MASK]); + if (tb[IFLA_BR_GROUP_ADDR]) + props->group_addr = *nla_data_as(NMEtherAddr, tb[IFLA_BR_GROUP_ADDR]); + if (tb[IFLA_BR_MCAST_SNOOPING]) + props->mcast_snooping = !!nla_get_u8(tb[IFLA_BR_MCAST_SNOOPING]); + if (tb[IFLA_BR_MCAST_ROUTER]) + props->mcast_router = nla_get_u8(tb[IFLA_BR_MCAST_ROUTER]); + if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]) + props->mcast_query_use_ifaddr = !!nla_get_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]); + if (tb[IFLA_BR_MCAST_QUERIER]) + props->mcast_querier = nla_get_u8(tb[IFLA_BR_MCAST_QUERIER]); + if (tb[IFLA_BR_MCAST_HASH_MAX]) + props->mcast_hash_max = nla_get_u32(tb[IFLA_BR_MCAST_HASH_MAX]); + if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]) + props->mcast_last_member_count = nla_get_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]); + if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]) + props->mcast_startup_query_count = nla_get_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]); + if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]) + props->mcast_last_member_interval = nla_get_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]); + if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]) + props->mcast_membership_interval = nla_get_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]); + if (tb[IFLA_BR_MCAST_QUERIER_INTVL]) + props->mcast_querier_interval = nla_get_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]); + if (tb[IFLA_BR_MCAST_QUERY_INTVL]) + props->mcast_query_interval = nla_get_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]); + if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]) + props->mcast_query_response_interval = nla_get_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]); + if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) + props->mcast_startup_query_interval = nla_get_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]); + + return obj; +} + +/***********************************************************************************/ + +static NMPObject * +_parse_lnk_gre(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_GRE_LINK] = {.type = NLA_U32}, + [IFLA_GRE_IFLAGS] = {.type = NLA_U16}, + [IFLA_GRE_OFLAGS] = {.type = NLA_U16}, + [IFLA_GRE_IKEY] = {.type = NLA_U32}, + [IFLA_GRE_OKEY] = {.type = NLA_U32}, + [IFLA_GRE_LOCAL] = {.type = NLA_U32}, + [IFLA_GRE_REMOTE] = {.type = NLA_U32}, + [IFLA_GRE_TTL] = {.type = NLA_U8}, + [IFLA_GRE_TOS] = {.type = NLA_U8}, + [IFLA_GRE_PMTUDISC] = {.type = NLA_U8}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + NMPlatformLnkGre *props; + gboolean is_tap; + + if (!info_data || !kind) + return NULL; + + if (nm_streq(kind, "gretap")) + is_tap = TRUE; + else if (nm_streq(kind, "gre")) + is_tap = FALSE; + else + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(is_tap ? NMP_OBJECT_TYPE_LNK_GRETAP : NMP_OBJECT_TYPE_LNK_GRE, NULL); + props = &obj->lnk_gre; + + props->parent_ifindex = tb[IFLA_GRE_LINK] ? nla_get_u32(tb[IFLA_GRE_LINK]) : 0; + props->input_flags = tb[IFLA_GRE_IFLAGS] ? ntohs(nla_get_u16(tb[IFLA_GRE_IFLAGS])) : 0; + props->output_flags = tb[IFLA_GRE_OFLAGS] ? ntohs(nla_get_u16(tb[IFLA_GRE_OFLAGS])) : 0; + props->input_key = tb[IFLA_GRE_IKEY] ? ntohl(nla_get_u32(tb[IFLA_GRE_IKEY])) : 0; + props->output_key = tb[IFLA_GRE_OKEY] ? ntohl(nla_get_u32(tb[IFLA_GRE_OKEY])) : 0; + props->local = tb[IFLA_GRE_LOCAL] ? nla_get_u32(tb[IFLA_GRE_LOCAL]) : 0; + props->remote = tb[IFLA_GRE_REMOTE] ? nla_get_u32(tb[IFLA_GRE_REMOTE]) : 0; + props->tos = tb[IFLA_GRE_TOS] ? nla_get_u8(tb[IFLA_GRE_TOS]) : 0; + props->ttl = tb[IFLA_GRE_TTL] ? nla_get_u8(tb[IFLA_GRE_TTL]) : 0; + props->path_mtu_discovery = !tb[IFLA_GRE_PMTUDISC] || !!nla_get_u8(tb[IFLA_GRE_PMTUDISC]); + props->is_tap = is_tap; + + return obj; } /*****************************************************************************/ @@ -1366,503 +1466,520 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data) #define IPOIB_MODE_CONNECTED 1 /* using connected QPs */ static NMPObject * -_parse_lnk_infiniband (const char *kind, struct nlattr *info_data) +_parse_lnk_infiniband(const char *kind, struct nlattr *info_data) { - static const struct nla_policy policy[] = { - [IFLA_IPOIB_PKEY] = { .type = NLA_U16 }, - [IFLA_IPOIB_MODE] = { .type = NLA_U16 }, - [IFLA_IPOIB_UMCAST] = { .type = NLA_U16 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPlatformLnkInfiniband *info; - NMPObject *obj; - const char *mode; + static const struct nla_policy policy[] = { + [IFLA_IPOIB_PKEY] = {.type = NLA_U16}, + [IFLA_IPOIB_MODE] = {.type = NLA_U16}, + [IFLA_IPOIB_UMCAST] = {.type = NLA_U16}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPlatformLnkInfiniband *info; + NMPObject * obj; + const char * mode; - if ( !info_data - || !nm_streq0 (kind, "ipoib")) - return NULL; + if (!info_data || !nm_streq0(kind, "ipoib")) + return NULL; - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; - if ( !tb[IFLA_IPOIB_PKEY] - || !tb[IFLA_IPOIB_MODE]) - return NULL; + if (!tb[IFLA_IPOIB_PKEY] || !tb[IFLA_IPOIB_MODE]) + return NULL; - switch (nla_get_u16 (tb[IFLA_IPOIB_MODE])) { - case IPOIB_MODE_DATAGRAM: - mode = "datagram"; - break; - case IPOIB_MODE_CONNECTED: - mode = "connected"; - break; - default: - return NULL; - } + switch (nla_get_u16(tb[IFLA_IPOIB_MODE])) { + case IPOIB_MODE_DATAGRAM: + mode = "datagram"; + break; + case IPOIB_MODE_CONNECTED: + mode = "connected"; + break; + default: + return NULL; + } - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL); - info = &obj->lnk_infiniband; + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL); + info = &obj->lnk_infiniband; - info->p_key = nla_get_u16 (tb[IFLA_IPOIB_PKEY]); - info->mode = mode; + info->p_key = nla_get_u16(tb[IFLA_IPOIB_PKEY]); + info->mode = mode; - return obj; + return obj; } /*****************************************************************************/ static NMPObject * -_parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, - [IFLA_IPTUN_LOCAL] = { .minlen = sizeof (struct in6_addr)}, - [IFLA_IPTUN_REMOTE] = { .minlen = sizeof (struct in6_addr)}, - [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, - [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 }, - [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 }, - [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, - [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - NMPlatformLnkIp6Tnl *props; - guint32 flowinfo; - - if ( !info_data - || !nm_streq0 (kind, "ip6tnl")) - return NULL; - - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_IP6TNL, NULL); - props = &obj->lnk_ip6tnl; - - if (tb[IFLA_IPTUN_LINK]) - props->parent_ifindex = nla_get_u32 (tb[IFLA_IPTUN_LINK]); - if (tb[IFLA_IPTUN_LOCAL]) - props->local = *nla_data_as (struct in6_addr, tb[IFLA_IPTUN_LOCAL]); - if (tb[IFLA_IPTUN_REMOTE]) - props->remote = *nla_data_as (struct in6_addr, tb[IFLA_IPTUN_REMOTE]); - if (tb[IFLA_IPTUN_TTL]) - props->ttl = nla_get_u8 (tb[IFLA_IPTUN_TTL]); - if (tb[IFLA_IPTUN_ENCAP_LIMIT]) - props->encap_limit = nla_get_u8 (tb[IFLA_IPTUN_ENCAP_LIMIT]); - if (tb[IFLA_IPTUN_FLOWINFO]) { - flowinfo = ntohl (nla_get_u32 (tb[IFLA_IPTUN_FLOWINFO])); - props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; - props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; - } - if (tb[IFLA_IPTUN_PROTO]) - props->proto = nla_get_u8 (tb[IFLA_IPTUN_PROTO]); - if (tb[IFLA_IPTUN_FLAGS]) - props->flags = nla_get_u32 (tb[IFLA_IPTUN_FLAGS]); - - return obj; +_parse_lnk_ip6tnl(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_IPTUN_LINK] = {.type = NLA_U32}, + [IFLA_IPTUN_LOCAL] = {.minlen = sizeof(struct in6_addr)}, + [IFLA_IPTUN_REMOTE] = {.minlen = sizeof(struct in6_addr)}, + [IFLA_IPTUN_TTL] = {.type = NLA_U8}, + [IFLA_IPTUN_ENCAP_LIMIT] = {.type = NLA_U8}, + [IFLA_IPTUN_FLOWINFO] = {.type = NLA_U32}, + [IFLA_IPTUN_PROTO] = {.type = NLA_U8}, + [IFLA_IPTUN_FLAGS] = {.type = NLA_U32}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + NMPlatformLnkIp6Tnl *props; + guint32 flowinfo; + + if (!info_data || !nm_streq0(kind, "ip6tnl")) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_IP6TNL, NULL); + props = &obj->lnk_ip6tnl; + + if (tb[IFLA_IPTUN_LINK]) + props->parent_ifindex = nla_get_u32(tb[IFLA_IPTUN_LINK]); + if (tb[IFLA_IPTUN_LOCAL]) + props->local = *nla_data_as(struct in6_addr, tb[IFLA_IPTUN_LOCAL]); + if (tb[IFLA_IPTUN_REMOTE]) + props->remote = *nla_data_as(struct in6_addr, tb[IFLA_IPTUN_REMOTE]); + if (tb[IFLA_IPTUN_TTL]) + props->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]); + if (tb[IFLA_IPTUN_ENCAP_LIMIT]) + props->encap_limit = nla_get_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]); + if (tb[IFLA_IPTUN_FLOWINFO]) { + flowinfo = ntohl(nla_get_u32(tb[IFLA_IPTUN_FLOWINFO])); + props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; + props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; + } + if (tb[IFLA_IPTUN_PROTO]) + props->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]); + if (tb[IFLA_IPTUN_FLAGS]) + props->flags = nla_get_u32(tb[IFLA_IPTUN_FLAGS]); + + return obj; } static NMPObject * -_parse_lnk_ip6gre (const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_GRE_LINK] = { .type = NLA_U32 }, - [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, - [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, - [IFLA_GRE_IKEY] = { .type = NLA_U32 }, - [IFLA_GRE_OKEY] = { .type = NLA_U32 }, - [IFLA_GRE_LOCAL] = { .type = NLA_UNSPEC, - .minlen = sizeof (struct in6_addr)}, - [IFLA_GRE_REMOTE] = { .type = NLA_UNSPEC, - .minlen = sizeof (struct in6_addr)}, - [IFLA_GRE_TTL] = { .type = NLA_U8 }, - [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 }, - [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 }, - [IFLA_GRE_FLAGS] = { .type = NLA_U32 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - NMPlatformLnkIp6Tnl *props; - guint32 flowinfo; - gboolean is_tap; - - if (!info_data || !kind) - return NULL; - - if (nm_streq (kind, "ip6gre")) - is_tap = FALSE; - else if (nm_streq (kind, "ip6gretap")) - is_tap = TRUE; - else - return NULL; - - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new (is_tap ? NMP_OBJECT_TYPE_LNK_IP6GRETAP : NMP_OBJECT_TYPE_LNK_IP6GRE, NULL); - props = &obj->lnk_ip6tnl; - props->is_gre = TRUE; - props->is_tap = is_tap; - - if (tb[IFLA_GRE_LINK]) - props->parent_ifindex = nla_get_u32 (tb[IFLA_GRE_LINK]); - if (tb[IFLA_GRE_IFLAGS]) - props->input_flags = ntohs (nla_get_u16 (tb[IFLA_GRE_IFLAGS])); - if (tb[IFLA_GRE_OFLAGS]) - props->output_flags = ntohs (nla_get_u16 (tb[IFLA_GRE_OFLAGS])); - if (tb[IFLA_GRE_IKEY]) - props->input_key = ntohl (nla_get_u32 (tb[IFLA_GRE_IKEY])); - if (tb[IFLA_GRE_OKEY]) - props->output_key = ntohl (nla_get_u32 (tb[IFLA_GRE_OKEY])); - if (tb[IFLA_GRE_LOCAL]) - props->local = *nla_data_as (struct in6_addr, tb[IFLA_GRE_LOCAL]); - if (tb[IFLA_GRE_REMOTE]) - props->remote = *nla_data_as (struct in6_addr, tb[IFLA_GRE_REMOTE]); - if (tb[IFLA_GRE_TTL]) - props->ttl = nla_get_u8 (tb[IFLA_GRE_TTL]); - if (tb[IFLA_GRE_ENCAP_LIMIT]) - props->encap_limit = nla_get_u8 (tb[IFLA_GRE_ENCAP_LIMIT]); - if (tb[IFLA_GRE_FLOWINFO]) { - flowinfo = ntohl (nla_get_u32 (tb[IFLA_GRE_FLOWINFO])); - props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; - props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; - } - if (tb[IFLA_GRE_FLAGS]) - props->flags = nla_get_u32 (tb[IFLA_GRE_FLAGS]); - - return obj; +_parse_lnk_ip6gre(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_GRE_LINK] = {.type = NLA_U32}, + [IFLA_GRE_IFLAGS] = {.type = NLA_U16}, + [IFLA_GRE_OFLAGS] = {.type = NLA_U16}, + [IFLA_GRE_IKEY] = {.type = NLA_U32}, + [IFLA_GRE_OKEY] = {.type = NLA_U32}, + [IFLA_GRE_LOCAL] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, + [IFLA_GRE_REMOTE] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, + [IFLA_GRE_TTL] = {.type = NLA_U8}, + [IFLA_GRE_ENCAP_LIMIT] = {.type = NLA_U8}, + [IFLA_GRE_FLOWINFO] = {.type = NLA_U32}, + [IFLA_GRE_FLAGS] = {.type = NLA_U32}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + NMPlatformLnkIp6Tnl *props; + guint32 flowinfo; + gboolean is_tap; + + if (!info_data || !kind) + return NULL; + + if (nm_streq(kind, "ip6gre")) + is_tap = FALSE; + else if (nm_streq(kind, "ip6gretap")) + is_tap = TRUE; + else + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(is_tap ? NMP_OBJECT_TYPE_LNK_IP6GRETAP : NMP_OBJECT_TYPE_LNK_IP6GRE, NULL); + props = &obj->lnk_ip6tnl; + props->is_gre = TRUE; + props->is_tap = is_tap; + + if (tb[IFLA_GRE_LINK]) + props->parent_ifindex = nla_get_u32(tb[IFLA_GRE_LINK]); + if (tb[IFLA_GRE_IFLAGS]) + props->input_flags = ntohs(nla_get_u16(tb[IFLA_GRE_IFLAGS])); + if (tb[IFLA_GRE_OFLAGS]) + props->output_flags = ntohs(nla_get_u16(tb[IFLA_GRE_OFLAGS])); + if (tb[IFLA_GRE_IKEY]) + props->input_key = ntohl(nla_get_u32(tb[IFLA_GRE_IKEY])); + if (tb[IFLA_GRE_OKEY]) + props->output_key = ntohl(nla_get_u32(tb[IFLA_GRE_OKEY])); + if (tb[IFLA_GRE_LOCAL]) + props->local = *nla_data_as(struct in6_addr, tb[IFLA_GRE_LOCAL]); + if (tb[IFLA_GRE_REMOTE]) + props->remote = *nla_data_as(struct in6_addr, tb[IFLA_GRE_REMOTE]); + if (tb[IFLA_GRE_TTL]) + props->ttl = nla_get_u8(tb[IFLA_GRE_TTL]); + if (tb[IFLA_GRE_ENCAP_LIMIT]) + props->encap_limit = nla_get_u8(tb[IFLA_GRE_ENCAP_LIMIT]); + if (tb[IFLA_GRE_FLOWINFO]) { + flowinfo = ntohl(nla_get_u32(tb[IFLA_GRE_FLOWINFO])); + props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; + props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; + } + if (tb[IFLA_GRE_FLAGS]) + props->flags = nla_get_u32(tb[IFLA_GRE_FLAGS]); + + return obj; } /*****************************************************************************/ static NMPObject * -_parse_lnk_ipip (const char *kind, struct nlattr *info_data) +_parse_lnk_ipip(const char *kind, struct nlattr *info_data) { - static const struct nla_policy policy[] = { - [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, - [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 }, - [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 }, - [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, - [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, - [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - NMPlatformLnkIpIp *props; + static const struct nla_policy policy[] = { + [IFLA_IPTUN_LINK] = {.type = NLA_U32}, + [IFLA_IPTUN_LOCAL] = {.type = NLA_U32}, + [IFLA_IPTUN_REMOTE] = {.type = NLA_U32}, + [IFLA_IPTUN_TTL] = {.type = NLA_U8}, + [IFLA_IPTUN_TOS] = {.type = NLA_U8}, + [IFLA_IPTUN_PMTUDISC] = {.type = NLA_U8}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + NMPlatformLnkIpIp *props; - if ( !info_data - || !nm_streq0 (kind, "ipip")) - return NULL; + if (!info_data || !nm_streq0(kind, "ipip")) + return NULL; - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_IPIP, NULL); - props = &obj->lnk_ipip; + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_IPIP, NULL); + props = &obj->lnk_ipip; - props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32 (tb[IFLA_IPTUN_LINK]) : 0; - props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32 (tb[IFLA_IPTUN_LOCAL]) : 0; - props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32 (tb[IFLA_IPTUN_REMOTE]) : 0; - props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8 (tb[IFLA_IPTUN_TOS]) : 0; - props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8 (tb[IFLA_IPTUN_TTL]) : 0; - props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8 (tb[IFLA_IPTUN_PMTUDISC]); + props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32(tb[IFLA_IPTUN_LINK]) : 0; + props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32(tb[IFLA_IPTUN_LOCAL]) : 0; + props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32(tb[IFLA_IPTUN_REMOTE]) : 0; + props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8(tb[IFLA_IPTUN_TOS]) : 0; + props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8(tb[IFLA_IPTUN_TTL]) : 0; + props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]); - return obj; + return obj; } /*****************************************************************************/ static NMPObject * -_parse_lnk_macvlan (const char *kind, struct nlattr *info_data) +_parse_lnk_macvlan(const char *kind, struct nlattr *info_data) { - static const struct nla_policy policy[] = { - [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, - [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 }, - }; - NMPlatformLnkMacvlan *props; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - gboolean tap; + static const struct nla_policy policy[] = { + [IFLA_MACVLAN_MODE] = {.type = NLA_U32}, + [IFLA_MACVLAN_FLAGS] = {.type = NLA_U16}, + }; + NMPlatformLnkMacvlan *props; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + gboolean tap; - if ( !info_data - || !kind) - return NULL; + if (!info_data || !kind) + return NULL; - if (nm_streq (kind, "macvlan")) - tap = FALSE; - else if (nm_streq (kind, "macvtap")) - tap = TRUE; - else - return NULL; + if (nm_streq(kind, "macvlan")) + tap = FALSE; + else if (nm_streq(kind, "macvtap")) + tap = TRUE; + else + return NULL; - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; - if (!tb[IFLA_MACVLAN_MODE]) - return NULL; + if (!tb[IFLA_MACVLAN_MODE]) + return NULL; - obj = nmp_object_new (tap ? NMP_OBJECT_TYPE_LNK_MACVTAP : NMP_OBJECT_TYPE_LNK_MACVLAN, NULL); - props = &obj->lnk_macvlan; - props->mode = nla_get_u32 (tb[IFLA_MACVLAN_MODE]); - props->tap = tap; + obj = nmp_object_new(tap ? NMP_OBJECT_TYPE_LNK_MACVTAP : NMP_OBJECT_TYPE_LNK_MACVLAN, NULL); + props = &obj->lnk_macvlan; + props->mode = nla_get_u32(tb[IFLA_MACVLAN_MODE]); + props->tap = tap; - if (tb[IFLA_MACVLAN_FLAGS]) - props->no_promisc = NM_FLAGS_HAS (nla_get_u16 (tb[IFLA_MACVLAN_FLAGS]), MACVLAN_FLAG_NOPROMISC); + if (tb[IFLA_MACVLAN_FLAGS]) + props->no_promisc = + NM_FLAGS_HAS(nla_get_u16(tb[IFLA_MACVLAN_FLAGS]), MACVLAN_FLAG_NOPROMISC); - return obj; + return obj; } /*****************************************************************************/ static NMPObject * -_parse_lnk_macsec (const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_MACSEC_SCI] = { .type = NLA_U64 }, - [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 }, - [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 }, - [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 }, - [IFLA_MACSEC_ENCODING_SA] = { .type = NLA_U8 }, - [IFLA_MACSEC_ENCRYPT] = { .type = NLA_U8 }, - [IFLA_MACSEC_PROTECT] = { .type = NLA_U8 }, - [IFLA_MACSEC_INC_SCI] = { .type = NLA_U8 }, - [IFLA_MACSEC_ES] = { .type = NLA_U8 }, - [IFLA_MACSEC_SCB] = { .type = NLA_U8 }, - [IFLA_MACSEC_REPLAY_PROTECT] = { .type = NLA_U8 }, - [IFLA_MACSEC_VALIDATION] = { .type = NLA_U8 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - NMPlatformLnkMacsec *props; - - if ( !info_data - || !nm_streq0 (kind, "macsec")) - return NULL; - - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_MACSEC, NULL); - props = &obj->lnk_macsec; - - if (tb[IFLA_MACSEC_SCI]) { props->sci = nla_get_be64 (tb[IFLA_MACSEC_SCI]); } - if (tb[IFLA_MACSEC_ICV_LEN]) { props->icv_length = nla_get_u8 (tb[IFLA_MACSEC_ICV_LEN]); } - if (tb[IFLA_MACSEC_CIPHER_SUITE]) { props->cipher_suite = nla_get_u64 (tb[IFLA_MACSEC_CIPHER_SUITE]); } - if (tb[IFLA_MACSEC_WINDOW]) { props->window = nla_get_u32 (tb[IFLA_MACSEC_WINDOW]); } - if (tb[IFLA_MACSEC_ENCODING_SA]) { props->encoding_sa = !!nla_get_u8 (tb[IFLA_MACSEC_ENCODING_SA]); } - if (tb[IFLA_MACSEC_ENCRYPT]) { props->encrypt = !!nla_get_u8 (tb[IFLA_MACSEC_ENCRYPT]); } - if (tb[IFLA_MACSEC_PROTECT]) { props->protect = !!nla_get_u8 (tb[IFLA_MACSEC_PROTECT]); } - if (tb[IFLA_MACSEC_INC_SCI]) { props->include_sci = !!nla_get_u8 (tb[IFLA_MACSEC_INC_SCI]); } - if (tb[IFLA_MACSEC_ES]) { props->es = !!nla_get_u8 (tb[IFLA_MACSEC_ES]); } - if (tb[IFLA_MACSEC_SCB]) { props->scb = !!nla_get_u8 (tb[IFLA_MACSEC_SCB]); } - if (tb[IFLA_MACSEC_REPLAY_PROTECT]) { props->replay_protect = !!nla_get_u8 (tb[IFLA_MACSEC_REPLAY_PROTECT]); } - if (tb[IFLA_MACSEC_VALIDATION]) { props->validation = nla_get_u8 (tb[IFLA_MACSEC_VALIDATION]); } - - return obj; +_parse_lnk_macsec(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_MACSEC_SCI] = {.type = NLA_U64}, + [IFLA_MACSEC_ICV_LEN] = {.type = NLA_U8}, + [IFLA_MACSEC_CIPHER_SUITE] = {.type = NLA_U64}, + [IFLA_MACSEC_WINDOW] = {.type = NLA_U32}, + [IFLA_MACSEC_ENCODING_SA] = {.type = NLA_U8}, + [IFLA_MACSEC_ENCRYPT] = {.type = NLA_U8}, + [IFLA_MACSEC_PROTECT] = {.type = NLA_U8}, + [IFLA_MACSEC_INC_SCI] = {.type = NLA_U8}, + [IFLA_MACSEC_ES] = {.type = NLA_U8}, + [IFLA_MACSEC_SCB] = {.type = NLA_U8}, + [IFLA_MACSEC_REPLAY_PROTECT] = {.type = NLA_U8}, + [IFLA_MACSEC_VALIDATION] = {.type = NLA_U8}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + NMPlatformLnkMacsec *props; + + if (!info_data || !nm_streq0(kind, "macsec")) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_MACSEC, NULL); + props = &obj->lnk_macsec; + + if (tb[IFLA_MACSEC_SCI]) { + props->sci = nla_get_be64(tb[IFLA_MACSEC_SCI]); + } + if (tb[IFLA_MACSEC_ICV_LEN]) { + props->icv_length = nla_get_u8(tb[IFLA_MACSEC_ICV_LEN]); + } + if (tb[IFLA_MACSEC_CIPHER_SUITE]) { + props->cipher_suite = nla_get_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); + } + if (tb[IFLA_MACSEC_WINDOW]) { + props->window = nla_get_u32(tb[IFLA_MACSEC_WINDOW]); + } + if (tb[IFLA_MACSEC_ENCODING_SA]) { + props->encoding_sa = !!nla_get_u8(tb[IFLA_MACSEC_ENCODING_SA]); + } + if (tb[IFLA_MACSEC_ENCRYPT]) { + props->encrypt = !!nla_get_u8(tb[IFLA_MACSEC_ENCRYPT]); + } + if (tb[IFLA_MACSEC_PROTECT]) { + props->protect = !!nla_get_u8(tb[IFLA_MACSEC_PROTECT]); + } + if (tb[IFLA_MACSEC_INC_SCI]) { + props->include_sci = !!nla_get_u8(tb[IFLA_MACSEC_INC_SCI]); + } + if (tb[IFLA_MACSEC_ES]) { + props->es = !!nla_get_u8(tb[IFLA_MACSEC_ES]); + } + if (tb[IFLA_MACSEC_SCB]) { + props->scb = !!nla_get_u8(tb[IFLA_MACSEC_SCB]); + } + if (tb[IFLA_MACSEC_REPLAY_PROTECT]) { + props->replay_protect = !!nla_get_u8(tb[IFLA_MACSEC_REPLAY_PROTECT]); + } + if (tb[IFLA_MACSEC_VALIDATION]) { + props->validation = nla_get_u8(tb[IFLA_MACSEC_VALIDATION]); + } + + return obj; } /*****************************************************************************/ static NMPObject * -_parse_lnk_sit (const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_IPTUN_LINK] = { .type = NLA_U32 }, - [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 }, - [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 }, - [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, - [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, - [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, - [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, - [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - NMPlatformLnkSit *props; - - if ( !info_data - || !nm_streq0 (kind, "sit")) - return NULL; - - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_SIT, NULL); - props = &obj->lnk_sit; - - props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32 (tb[IFLA_IPTUN_LINK]) : 0; - props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32 (tb[IFLA_IPTUN_LOCAL]) : 0; - props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32 (tb[IFLA_IPTUN_REMOTE]) : 0; - props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8 (tb[IFLA_IPTUN_TOS]) : 0; - props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8 (tb[IFLA_IPTUN_TTL]) : 0; - props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8 (tb[IFLA_IPTUN_PMTUDISC]); - props->flags = tb[IFLA_IPTUN_FLAGS] ? nla_get_u16 (tb[IFLA_IPTUN_FLAGS]) : 0; - props->proto = tb[IFLA_IPTUN_PROTO] ? nla_get_u8 (tb[IFLA_IPTUN_PROTO]) : 0; - - return obj; +_parse_lnk_sit(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_IPTUN_LINK] = {.type = NLA_U32}, + [IFLA_IPTUN_LOCAL] = {.type = NLA_U32}, + [IFLA_IPTUN_REMOTE] = {.type = NLA_U32}, + [IFLA_IPTUN_TTL] = {.type = NLA_U8}, + [IFLA_IPTUN_TOS] = {.type = NLA_U8}, + [IFLA_IPTUN_PMTUDISC] = {.type = NLA_U8}, + [IFLA_IPTUN_FLAGS] = {.type = NLA_U16}, + [IFLA_IPTUN_PROTO] = {.type = NLA_U8}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + NMPlatformLnkSit *props; + + if (!info_data || !nm_streq0(kind, "sit")) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_SIT, NULL); + props = &obj->lnk_sit; + + props->parent_ifindex = tb[IFLA_IPTUN_LINK] ? nla_get_u32(tb[IFLA_IPTUN_LINK]) : 0; + props->local = tb[IFLA_IPTUN_LOCAL] ? nla_get_u32(tb[IFLA_IPTUN_LOCAL]) : 0; + props->remote = tb[IFLA_IPTUN_REMOTE] ? nla_get_u32(tb[IFLA_IPTUN_REMOTE]) : 0; + props->tos = tb[IFLA_IPTUN_TOS] ? nla_get_u8(tb[IFLA_IPTUN_TOS]) : 0; + props->ttl = tb[IFLA_IPTUN_TTL] ? nla_get_u8(tb[IFLA_IPTUN_TTL]) : 0; + props->path_mtu_discovery = !tb[IFLA_IPTUN_PMTUDISC] || !!nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]); + props->flags = tb[IFLA_IPTUN_FLAGS] ? nla_get_u16(tb[IFLA_IPTUN_FLAGS]) : 0; + props->proto = tb[IFLA_IPTUN_PROTO] ? nla_get_u8(tb[IFLA_IPTUN_PROTO]) : 0; + + return obj; } /*****************************************************************************/ static NMPObject * -_parse_lnk_tun (const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_TUN_OWNER] = { .type = NLA_U32 }, - [IFLA_TUN_GROUP] = { .type = NLA_U32 }, - [IFLA_TUN_TYPE] = { .type = NLA_U8 }, - [IFLA_TUN_PI] = { .type = NLA_U8 }, - [IFLA_TUN_VNET_HDR] = { .type = NLA_U8 }, - [IFLA_TUN_PERSIST] = { .type = NLA_U8 }, - [IFLA_TUN_MULTI_QUEUE] = { .type = NLA_U8 }, - [IFLA_TUN_NUM_QUEUES] = { .type = NLA_U32 }, - [IFLA_TUN_NUM_DISABLED_QUEUES] = { .type = NLA_U32 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - NMPlatformLnkTun *props; - - if ( !info_data - || !nm_streq0 (kind, "tun")) - return NULL; - - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; - - if (!tb[IFLA_TUN_TYPE]) - return NULL; - - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_TUN, NULL); - props = &obj->lnk_tun; - - props->type = nla_get_u8 (tb[IFLA_TUN_TYPE]); - - props->pi = !!nla_get_u8_cond (tb, IFLA_TUN_PI, FALSE); - props->vnet_hdr = !!nla_get_u8_cond (tb, IFLA_TUN_VNET_HDR, FALSE); - props->multi_queue = !!nla_get_u8_cond (tb, IFLA_TUN_MULTI_QUEUE, FALSE); - props->persist = !!nla_get_u8_cond (tb, IFLA_TUN_PERSIST, FALSE); - - if (tb[IFLA_TUN_OWNER]) { - props->owner_valid = TRUE; - props->owner = nla_get_u32 (tb[IFLA_TUN_OWNER]); - } - if (tb[IFLA_TUN_GROUP]) { - props->group_valid = TRUE; - props->group = nla_get_u32 (tb[IFLA_TUN_GROUP]); - } - return obj; +_parse_lnk_tun(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_TUN_OWNER] = {.type = NLA_U32}, + [IFLA_TUN_GROUP] = {.type = NLA_U32}, + [IFLA_TUN_TYPE] = {.type = NLA_U8}, + [IFLA_TUN_PI] = {.type = NLA_U8}, + [IFLA_TUN_VNET_HDR] = {.type = NLA_U8}, + [IFLA_TUN_PERSIST] = {.type = NLA_U8}, + [IFLA_TUN_MULTI_QUEUE] = {.type = NLA_U8}, + [IFLA_TUN_NUM_QUEUES] = {.type = NLA_U32}, + [IFLA_TUN_NUM_DISABLED_QUEUES] = {.type = NLA_U32}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + NMPlatformLnkTun *props; + + if (!info_data || !nm_streq0(kind, "tun")) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + if (!tb[IFLA_TUN_TYPE]) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_TUN, NULL); + props = &obj->lnk_tun; + + props->type = nla_get_u8(tb[IFLA_TUN_TYPE]); + + props->pi = !!nla_get_u8_cond(tb, IFLA_TUN_PI, FALSE); + props->vnet_hdr = !!nla_get_u8_cond(tb, IFLA_TUN_VNET_HDR, FALSE); + props->multi_queue = !!nla_get_u8_cond(tb, IFLA_TUN_MULTI_QUEUE, FALSE); + props->persist = !!nla_get_u8_cond(tb, IFLA_TUN_PERSIST, FALSE); + + if (tb[IFLA_TUN_OWNER]) { + props->owner_valid = TRUE; + props->owner = nla_get_u32(tb[IFLA_TUN_OWNER]); + } + if (tb[IFLA_TUN_GROUP]) { + props->group_valid = TRUE; + props->group = nla_get_u32(tb[IFLA_TUN_GROUP]); + } + return obj; } /*****************************************************************************/ static gboolean -_vlan_qos_mapping_from_nla (struct nlattr *nlattr, - const NMVlanQosMapping **out_map, - guint *out_n_map) +_vlan_qos_mapping_from_nla(struct nlattr * nlattr, + const NMVlanQosMapping **out_map, + guint * out_n_map) { - struct nlattr *nla; - int remaining; - gs_unref_ptrarray GPtrArray *array = NULL; + struct nlattr * nla; + int remaining; + gs_unref_ptrarray GPtrArray *array = NULL; - G_STATIC_ASSERT (sizeof (NMVlanQosMapping) == sizeof (struct ifla_vlan_qos_mapping)); - G_STATIC_ASSERT (sizeof (((NMVlanQosMapping *) 0)->to) == sizeof (((struct ifla_vlan_qos_mapping *) 0)->to)); - G_STATIC_ASSERT (sizeof (((NMVlanQosMapping *) 0)->from) == sizeof (((struct ifla_vlan_qos_mapping *) 0)->from)); - G_STATIC_ASSERT (sizeof (NMVlanQosMapping) == sizeof (((NMVlanQosMapping *) 0)->from) + sizeof (((NMVlanQosMapping *) 0)->to)); + G_STATIC_ASSERT(sizeof(NMVlanQosMapping) == sizeof(struct ifla_vlan_qos_mapping)); + G_STATIC_ASSERT(sizeof(((NMVlanQosMapping *) 0)->to) + == sizeof(((struct ifla_vlan_qos_mapping *) 0)->to)); + G_STATIC_ASSERT(sizeof(((NMVlanQosMapping *) 0)->from) + == sizeof(((struct ifla_vlan_qos_mapping *) 0)->from)); + G_STATIC_ASSERT(sizeof(NMVlanQosMapping) + == sizeof(((NMVlanQosMapping *) 0)->from) + + sizeof(((NMVlanQosMapping *) 0)->to)); - nm_assert (out_map && !*out_map); - nm_assert (out_n_map && !*out_n_map); + nm_assert(out_map && !*out_map); + nm_assert(out_n_map && !*out_n_map); - if (!nlattr) - return TRUE; + if (!nlattr) + return TRUE; - array = g_ptr_array_new (); - nla_for_each_nested (nla, nlattr, remaining) { - if (nla_len (nla) < sizeof (NMVlanQosMapping)) - return FALSE; - g_ptr_array_add (array, nla_data (nla)); - } + array = g_ptr_array_new(); + nla_for_each_nested (nla, nlattr, remaining) { + if (nla_len(nla) < sizeof(NMVlanQosMapping)) + return FALSE; + g_ptr_array_add(array, nla_data(nla)); + } - if (array->len > 0) { - NMVlanQosMapping *list; - guint i, j; + if (array->len > 0) { + NMVlanQosMapping *list; + guint i, j; - /* The sorting is necessary, because for egress mapping, kernel - * doesn't sent the items strictly sorted by the from field. */ - g_ptr_array_sort_with_data (array, _vlan_qos_mapping_cmp_from_ptr, NULL); + /* The sorting is necessary, because for egress mapping, kernel + * doesn't sent the items strictly sorted by the from field. */ + g_ptr_array_sort_with_data(array, _vlan_qos_mapping_cmp_from_ptr, NULL); - list = g_new (NMVlanQosMapping, array->len); + list = g_new(NMVlanQosMapping, array->len); - for (i = 0, j = 0; i < array->len; i++) { - NMVlanQosMapping *map; + for (i = 0, j = 0; i < array->len; i++) { + NMVlanQosMapping *map; - map = array->pdata[i]; + map = array->pdata[i]; - /* kernel doesn't really send us duplicates. Just be extra cautious - * because we want strong guarantees about the sort order and uniqueness - * of our mapping list (for simpler equality comparison). */ - if ( j > 0 - && list[j - 1].from == map->from) - list[j - 1] = *map; - else - list[j++] = *map; - } + /* kernel doesn't really send us duplicates. Just be extra cautious + * because we want strong guarantees about the sort order and uniqueness + * of our mapping list (for simpler equality comparison). */ + if (j > 0 && list[j - 1].from == map->from) + list[j - 1] = *map; + else + list[j++] = *map; + } - *out_n_map = j; - *out_map = list; - } + *out_n_map = j; + *out_map = list; + } - return TRUE; + return TRUE; } /* Copied and heavily modified from libnl3's vlan_parse() */ static NMPObject * -_parse_lnk_vlan (const char *kind, struct nlattr *info_data) +_parse_lnk_vlan(const char *kind, struct nlattr *info_data) { - static const struct nla_policy policy[] = { - [IFLA_VLAN_ID] = { .type = NLA_U16 }, - [IFLA_VLAN_FLAGS] = { .minlen = nm_offsetofend (struct ifla_vlan_flags, flags) }, - [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED }, - [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED }, - [IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - nm_auto_nmpobj NMPObject *obj = NULL; - NMPObject *obj_result; + static const struct nla_policy policy[] = { + [IFLA_VLAN_ID] = {.type = NLA_U16}, + [IFLA_VLAN_FLAGS] = {.minlen = nm_offsetofend(struct ifla_vlan_flags, flags)}, + [IFLA_VLAN_INGRESS_QOS] = {.type = NLA_NESTED}, + [IFLA_VLAN_EGRESS_QOS] = {.type = NLA_NESTED}, + [IFLA_VLAN_PROTOCOL] = {.type = NLA_U16}, + }; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + nm_auto_nmpobj NMPObject *obj = NULL; + NMPObject * obj_result; - if ( !info_data - || !nm_streq0 (kind, "vlan")) - return NULL; + if (!info_data || !nm_streq0(kind, "vlan")) + return NULL; - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; - if (!tb[IFLA_VLAN_ID]) - return NULL; + if (!tb[IFLA_VLAN_ID]) + return NULL; - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, NULL); - obj->lnk_vlan.id = nla_get_u16 (tb[IFLA_VLAN_ID]); + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_VLAN, NULL); + obj->lnk_vlan.id = nla_get_u16(tb[IFLA_VLAN_ID]); - if (tb[IFLA_VLAN_FLAGS]) { - struct ifla_vlan_flags flags; + if (tb[IFLA_VLAN_FLAGS]) { + struct ifla_vlan_flags flags; - nla_memcpy (&flags, tb[IFLA_VLAN_FLAGS], sizeof (flags)); + nla_memcpy(&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags)); - obj->lnk_vlan.flags = flags.flags; - } + obj->lnk_vlan.flags = flags.flags; + } - if (!_vlan_qos_mapping_from_nla (tb[IFLA_VLAN_INGRESS_QOS], - &obj->_lnk_vlan.ingress_qos_map, - &obj->_lnk_vlan.n_ingress_qos_map)) - return NULL; + if (!_vlan_qos_mapping_from_nla(tb[IFLA_VLAN_INGRESS_QOS], + &obj->_lnk_vlan.ingress_qos_map, + &obj->_lnk_vlan.n_ingress_qos_map)) + return NULL; - if (!_vlan_qos_mapping_from_nla (tb[IFLA_VLAN_EGRESS_QOS], - &obj->_lnk_vlan.egress_qos_map, - &obj->_lnk_vlan.n_egress_qos_map)) - return NULL; + if (!_vlan_qos_mapping_from_nla(tb[IFLA_VLAN_EGRESS_QOS], + &obj->_lnk_vlan.egress_qos_map, + &obj->_lnk_vlan.n_egress_qos_map)) + return NULL; - obj_result = obj; - obj = NULL; - return obj_result; + obj_result = obj; + obj = NULL; + return obj_result; } /*****************************************************************************/ @@ -1872,16 +1989,16 @@ _parse_lnk_vlan (const char *kind, struct nlattr *info_data) * So until we depend on kernel >= 3.11, we just ignore the actual enum * in if_link.h and define the values ourselves. */ -#define IFLA_VXLAN_UNSPEC 0 -#define IFLA_VXLAN_ID 1 -#define IFLA_VXLAN_GROUP 2 -#define IFLA_VXLAN_LINK 3 -#define IFLA_VXLAN_LOCAL 4 -#define IFLA_VXLAN_TTL 5 -#define IFLA_VXLAN_TOS 6 -#define IFLA_VXLAN_LEARNING 7 -#define IFLA_VXLAN_AGEING 8 -#define IFLA_VXLAN_LIMIT 9 +#define IFLA_VXLAN_UNSPEC 0 +#define IFLA_VXLAN_ID 1 +#define IFLA_VXLAN_GROUP 2 +#define IFLA_VXLAN_LINK 3 +#define IFLA_VXLAN_LOCAL 4 +#define IFLA_VXLAN_TTL 5 +#define IFLA_VXLAN_TOS 6 +#define IFLA_VXLAN_LEARNING 7 +#define IFLA_VXLAN_AGEING 8 +#define IFLA_VXLAN_LIMIT 9 #define IFLA_VXLAN_PORT_RANGE 10 #define IFLA_VXLAN_PROXY 11 #define IFLA_VXLAN_RSC 12 @@ -1893,1952 +2010,1984 @@ _parse_lnk_vlan (const char *kind, struct nlattr *info_data) #undef IFLA_VXLAN_MAX #define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6 -#define IFLA_VRF_TABLE 1 +#define IFLA_VRF_TABLE 1 /* older kernel header might not contain 'struct ifla_vxlan_port_range'. * Redefine it. */ struct nm_ifla_vxlan_port_range { - guint16 low; - guint16 high; + guint16 low; + guint16 high; }; static NMPObject * -_parse_lnk_vxlan (const char *kind, struct nlattr *info_data) -{ - static const struct nla_policy policy[] = { - [IFLA_VXLAN_ID] = { .type = NLA_U32 }, - [IFLA_VXLAN_GROUP] = { .type = NLA_U32 }, - [IFLA_VXLAN_GROUP6] = { .type = NLA_UNSPEC, - .minlen = sizeof (struct in6_addr) }, - [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, - [IFLA_VXLAN_LOCAL] = { .type = NLA_U32 }, - [IFLA_VXLAN_LOCAL6] = { .type = NLA_UNSPEC, - .minlen = sizeof (struct in6_addr) }, - [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, - [IFLA_VXLAN_TTL] = { .type = NLA_U8 }, - [IFLA_VXLAN_LEARNING] = { .type = NLA_U8 }, - [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, - [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, - [IFLA_VXLAN_PORT_RANGE] = { .type = NLA_UNSPEC, - .minlen = sizeof (struct nm_ifla_vxlan_port_range) }, - [IFLA_VXLAN_PROXY] = { .type = NLA_U8 }, - [IFLA_VXLAN_RSC] = { .type = NLA_U8 }, - [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 }, - [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 }, - [IFLA_VXLAN_PORT] = { .type = NLA_U16 }, - }; - NMPlatformLnkVxlan *props; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; - - if ( !info_data - || !nm_streq0 (kind, "vxlan")) - return NULL; - - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; - - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, NULL); - - props = &obj->lnk_vxlan; - - if (tb[IFLA_VXLAN_LINK]) - props->parent_ifindex = nla_get_u32 (tb[IFLA_VXLAN_LINK]); - if (tb[IFLA_VXLAN_ID]) - props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]); - if (tb[IFLA_VXLAN_GROUP]) - props->group = nla_get_u32 (tb[IFLA_VXLAN_GROUP]); - if (tb[IFLA_VXLAN_LOCAL]) - props->local = nla_get_u32 (tb[IFLA_VXLAN_LOCAL]); - if (tb[IFLA_VXLAN_LOCAL6]) - props->local6 = *nla_data_as (struct in6_addr, tb[IFLA_VXLAN_LOCAL6]); - if (tb[IFLA_VXLAN_GROUP6]) - props->group6 = *nla_data_as (struct in6_addr, tb[IFLA_VXLAN_GROUP6]); - - if (tb[IFLA_VXLAN_AGEING]) - props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]); - if (tb[IFLA_VXLAN_LIMIT]) - props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]); - if (tb[IFLA_VXLAN_TOS]) - props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]); - if (tb[IFLA_VXLAN_TTL]) - props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]); - - if (tb[IFLA_VXLAN_PORT]) - props->dst_port = ntohs (nla_get_u16 (tb[IFLA_VXLAN_PORT])); - - if (tb[IFLA_VXLAN_PORT_RANGE]) { - struct nm_ifla_vxlan_port_range *range; - - range = nla_data_as (struct nm_ifla_vxlan_port_range, tb[IFLA_VXLAN_PORT_RANGE]); - props->src_port_min = ntohs (range->low); - props->src_port_max = ntohs (range->high); - } - - if (tb[IFLA_VXLAN_LEARNING]) - props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]); - if (tb[IFLA_VXLAN_PROXY]) - props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]); - if (tb[IFLA_VXLAN_RSC]) - props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]); - if (tb[IFLA_VXLAN_L2MISS]) - props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]); - if (tb[IFLA_VXLAN_L3MISS]) - props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]); - - return obj; +_parse_lnk_vxlan(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_VXLAN_ID] = {.type = NLA_U32}, + [IFLA_VXLAN_GROUP] = {.type = NLA_U32}, + [IFLA_VXLAN_GROUP6] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, + [IFLA_VXLAN_LINK] = {.type = NLA_U32}, + [IFLA_VXLAN_LOCAL] = {.type = NLA_U32}, + [IFLA_VXLAN_LOCAL6] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, + [IFLA_VXLAN_TOS] = {.type = NLA_U8}, + [IFLA_VXLAN_TTL] = {.type = NLA_U8}, + [IFLA_VXLAN_LEARNING] = {.type = NLA_U8}, + [IFLA_VXLAN_AGEING] = {.type = NLA_U32}, + [IFLA_VXLAN_LIMIT] = {.type = NLA_U32}, + [IFLA_VXLAN_PORT_RANGE] = {.type = NLA_UNSPEC, + .minlen = sizeof(struct nm_ifla_vxlan_port_range)}, + [IFLA_VXLAN_PROXY] = {.type = NLA_U8}, + [IFLA_VXLAN_RSC] = {.type = NLA_U8}, + [IFLA_VXLAN_L2MISS] = {.type = NLA_U8}, + [IFLA_VXLAN_L3MISS] = {.type = NLA_U8}, + [IFLA_VXLAN_PORT] = {.type = NLA_U16}, + }; + NMPlatformLnkVxlan *props; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; + + if (!info_data || !nm_streq0(kind, "vxlan")) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_VXLAN, NULL); + + props = &obj->lnk_vxlan; + + if (tb[IFLA_VXLAN_LINK]) + props->parent_ifindex = nla_get_u32(tb[IFLA_VXLAN_LINK]); + if (tb[IFLA_VXLAN_ID]) + props->id = nla_get_u32(tb[IFLA_VXLAN_ID]); + if (tb[IFLA_VXLAN_GROUP]) + props->group = nla_get_u32(tb[IFLA_VXLAN_GROUP]); + if (tb[IFLA_VXLAN_LOCAL]) + props->local = nla_get_u32(tb[IFLA_VXLAN_LOCAL]); + if (tb[IFLA_VXLAN_LOCAL6]) + props->local6 = *nla_data_as(struct in6_addr, tb[IFLA_VXLAN_LOCAL6]); + if (tb[IFLA_VXLAN_GROUP6]) + props->group6 = *nla_data_as(struct in6_addr, tb[IFLA_VXLAN_GROUP6]); + + if (tb[IFLA_VXLAN_AGEING]) + props->ageing = nla_get_u32(tb[IFLA_VXLAN_AGEING]); + if (tb[IFLA_VXLAN_LIMIT]) + props->limit = nla_get_u32(tb[IFLA_VXLAN_LIMIT]); + if (tb[IFLA_VXLAN_TOS]) + props->tos = nla_get_u8(tb[IFLA_VXLAN_TOS]); + if (tb[IFLA_VXLAN_TTL]) + props->ttl = nla_get_u8(tb[IFLA_VXLAN_TTL]); + + if (tb[IFLA_VXLAN_PORT]) + props->dst_port = ntohs(nla_get_u16(tb[IFLA_VXLAN_PORT])); + + if (tb[IFLA_VXLAN_PORT_RANGE]) { + struct nm_ifla_vxlan_port_range *range; + + range = nla_data_as(struct nm_ifla_vxlan_port_range, tb[IFLA_VXLAN_PORT_RANGE]); + props->src_port_min = ntohs(range->low); + props->src_port_max = ntohs(range->high); + } + + if (tb[IFLA_VXLAN_LEARNING]) + props->learning = !!nla_get_u8(tb[IFLA_VXLAN_LEARNING]); + if (tb[IFLA_VXLAN_PROXY]) + props->proxy = !!nla_get_u8(tb[IFLA_VXLAN_PROXY]); + if (tb[IFLA_VXLAN_RSC]) + props->rsc = !!nla_get_u8(tb[IFLA_VXLAN_RSC]); + if (tb[IFLA_VXLAN_L2MISS]) + props->l2miss = !!nla_get_u8(tb[IFLA_VXLAN_L2MISS]); + if (tb[IFLA_VXLAN_L3MISS]) + props->l3miss = !!nla_get_u8(tb[IFLA_VXLAN_L3MISS]); + + return obj; } static NMPObject * -_parse_lnk_vrf (const char *kind, struct nlattr *info_data) +_parse_lnk_vrf(const char *kind, struct nlattr *info_data) { - static const struct nla_policy policy[] = { - [IFLA_VRF_TABLE] = { .type = NLA_U32 }, - }; - NMPlatformLnkVrf *props; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj; + static const struct nla_policy policy[] = { + [IFLA_VRF_TABLE] = {.type = NLA_U32}, + }; + NMPlatformLnkVrf *props; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj; - if ( !info_data - || !nm_streq0 (kind, "vrf")) - return NULL; + if (!info_data || !nm_streq0(kind, "vrf")) + return NULL; - if (nla_parse_nested_arr (tb, info_data, policy) < 0) - return NULL; + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_VRF, NULL); + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_VRF, NULL); - props = &obj->lnk_vrf; + props = &obj->lnk_vrf; - if (tb[IFLA_VRF_TABLE]) - props->table = nla_get_u32 (tb[IFLA_VRF_TABLE]); + if (tb[IFLA_VRF_TABLE]) + props->table = nla_get_u32(tb[IFLA_VRF_TABLE]); - return obj; + return obj; } /*****************************************************************************/ static gboolean -_wireguard_update_from_allowed_ips_nla (NMPWireGuardAllowedIP *allowed_ip, - struct nlattr *nlattr) +_wireguard_update_from_allowed_ips_nla(NMPWireGuardAllowedIP *allowed_ip, struct nlattr *nlattr) { - static const struct nla_policy policy[] = { - [WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16 }, - [WGALLOWEDIP_A_IPADDR] = { .minlen = sizeof (struct in_addr) }, - [WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - int family; - int addr_len; + static const struct nla_policy policy[] = { + [WGALLOWEDIP_A_FAMILY] = {.type = NLA_U16}, + [WGALLOWEDIP_A_IPADDR] = {.minlen = sizeof(struct in_addr)}, + [WGALLOWEDIP_A_CIDR_MASK] = {.type = NLA_U8}, + }; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + int family; + int addr_len; - if (nla_parse_nested_arr (tb, nlattr, policy) < 0) - return FALSE; + if (nla_parse_nested_arr(tb, nlattr, policy) < 0) + return FALSE; - if (!tb[WGALLOWEDIP_A_FAMILY]) - return FALSE; + if (!tb[WGALLOWEDIP_A_FAMILY]) + return FALSE; - family = nla_get_u16 (tb[WGALLOWEDIP_A_FAMILY]); - if (family == AF_INET) - addr_len = sizeof (in_addr_t); - else if (family == AF_INET6) - addr_len = sizeof (struct in6_addr); - else - return FALSE; + family = nla_get_u16(tb[WGALLOWEDIP_A_FAMILY]); + if (family == AF_INET) + addr_len = sizeof(in_addr_t); + else if (family == AF_INET6) + addr_len = sizeof(struct in6_addr); + else + return FALSE; - _check_addr_or_return_val (tb, WGALLOWEDIP_A_IPADDR, addr_len, FALSE); + _check_addr_or_return_val(tb, WGALLOWEDIP_A_IPADDR, addr_len, FALSE); - *allowed_ip = (NMPWireGuardAllowedIP) { - .family = family, - }; + *allowed_ip = (NMPWireGuardAllowedIP){ + .family = family, + }; - nm_assert ((int) allowed_ip->family == family); + nm_assert((int) allowed_ip->family == family); - if (tb[WGALLOWEDIP_A_IPADDR]) - nla_memcpy (&allowed_ip->addr, tb[WGALLOWEDIP_A_IPADDR], addr_len); - if (tb[WGALLOWEDIP_A_CIDR_MASK]) - allowed_ip->mask = nla_get_u8 (tb[WGALLOWEDIP_A_CIDR_MASK]); + if (tb[WGALLOWEDIP_A_IPADDR]) + nla_memcpy(&allowed_ip->addr, tb[WGALLOWEDIP_A_IPADDR], addr_len); + if (tb[WGALLOWEDIP_A_CIDR_MASK]) + allowed_ip->mask = nla_get_u8(tb[WGALLOWEDIP_A_CIDR_MASK]); - return TRUE; + return TRUE; } typedef struct { - CList lst; - NMPWireGuardPeer data; + CList lst; + NMPWireGuardPeer data; } WireGuardPeerConstruct; static gboolean -_wireguard_update_from_peers_nla (CList *peers, - GArray **p_allowed_ips, - struct nlattr *peer_attr) -{ - static const struct nla_policy policy[] = { - [WGPEER_A_PUBLIC_KEY] = { .minlen = NMP_WIREGUARD_PUBLIC_KEY_LEN }, - [WGPEER_A_PRESHARED_KEY] = { }, - [WGPEER_A_FLAGS] = { .type = NLA_U32 }, - [WGPEER_A_ENDPOINT] = { }, - [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 }, - [WGPEER_A_LAST_HANDSHAKE_TIME] = { }, - [WGPEER_A_RX_BYTES] = { .type = NLA_U64 }, - [WGPEER_A_TX_BYTES] = { .type = NLA_U64 }, - [WGPEER_A_ALLOWEDIPS] = { .type = NLA_NESTED }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - WireGuardPeerConstruct *peer_c; - - if (nla_parse_nested_arr (tb, peer_attr, policy) < 0) - return FALSE; - - if (!tb[WGPEER_A_PUBLIC_KEY]) - return FALSE; - - /* a peer with the same public key as last peer is just a continuation for extra AllowedIPs */ - peer_c = c_list_last_entry (peers, WireGuardPeerConstruct, lst); - if ( peer_c - && !memcmp (nla_data (tb[WGPEER_A_PUBLIC_KEY]), peer_c->data.public_key, NMP_WIREGUARD_PUBLIC_KEY_LEN)) { - G_STATIC_ASSERT_EXPR (NMP_WIREGUARD_PUBLIC_KEY_LEN == sizeof (peer_c->data.public_key)); - /* this message is a continuation of the previous peer. - * Only parse WGPEER_A_ALLOWEDIPS below. */ - } - else { - /* otherwise, start a new peer */ - peer_c = g_slice_new0 (WireGuardPeerConstruct); - c_list_link_tail (peers, &peer_c->lst); - - nla_memcpy (&peer_c->data.public_key, tb[WGPEER_A_PUBLIC_KEY], sizeof (peer_c->data.public_key)); - - if (tb[WGPEER_A_PRESHARED_KEY]) { - nla_memcpy (&peer_c->data.preshared_key, tb[WGPEER_A_PRESHARED_KEY], sizeof (peer_c->data.preshared_key)); - /* FIXME(netlink-bzero-secret) */ - nm_explicit_bzero (nla_data (tb[WGPEER_A_PRESHARED_KEY]), - nla_len (tb[WGPEER_A_PRESHARED_KEY])); - } - - nm_sock_addr_union_cpy_untrusted (&peer_c->data.endpoint, - tb[WGPEER_A_ENDPOINT] ? nla_data (tb[WGPEER_A_ENDPOINT]) : NULL, - tb[WGPEER_A_ENDPOINT] ? nla_len (tb[WGPEER_A_ENDPOINT]) : 0); - - if (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]) - peer_c->data.persistent_keepalive_interval = nla_get_u16 (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]); - if (tb[WGPEER_A_LAST_HANDSHAKE_TIME]) { - if (nla_len (tb[WGPEER_A_LAST_HANDSHAKE_TIME]) >= sizeof (peer_c->data.last_handshake_time)) - nla_memcpy (&peer_c->data.last_handshake_time, tb[WGPEER_A_LAST_HANDSHAKE_TIME], sizeof (peer_c->data.last_handshake_time)); - } - if (tb[WGPEER_A_RX_BYTES]) - peer_c->data.rx_bytes = nla_get_u64 (tb[WGPEER_A_RX_BYTES]); - if (tb[WGPEER_A_TX_BYTES]) - peer_c->data.tx_bytes = nla_get_u64 (tb[WGPEER_A_TX_BYTES]); - } - - if (tb[WGPEER_A_ALLOWEDIPS]) { - struct nlattr *attr; - int rem; - GArray *allowed_ips = *p_allowed_ips; - - nla_for_each_nested (attr, tb[WGPEER_A_ALLOWEDIPS], rem) { - if (!allowed_ips) { - allowed_ips = g_array_new (FALSE, FALSE, sizeof (NMPWireGuardAllowedIP)); - *p_allowed_ips = allowed_ips; - g_array_set_size (allowed_ips, 1); - } else - g_array_set_size (allowed_ips, allowed_ips->len + 1); - - if (!_wireguard_update_from_allowed_ips_nla (&g_array_index (allowed_ips, - NMPWireGuardAllowedIP, - allowed_ips->len - 1), - attr)) { - /* we ignore the error of parsing one allowed-ip. */ - g_array_set_size (allowed_ips, allowed_ips->len - 1); - continue; - } - - if (!peer_c->data._construct_idx_end) - peer_c->data._construct_idx_start = allowed_ips->len - 1; - peer_c->data._construct_idx_end = allowed_ips->len; - } - } - - return TRUE; +_wireguard_update_from_peers_nla(CList *peers, GArray **p_allowed_ips, struct nlattr *peer_attr) +{ + static const struct nla_policy policy[] = { + [WGPEER_A_PUBLIC_KEY] = {.minlen = NMP_WIREGUARD_PUBLIC_KEY_LEN}, + [WGPEER_A_PRESHARED_KEY] = {}, + [WGPEER_A_FLAGS] = {.type = NLA_U32}, + [WGPEER_A_ENDPOINT] = {}, + [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = {.type = NLA_U16}, + [WGPEER_A_LAST_HANDSHAKE_TIME] = {}, + [WGPEER_A_RX_BYTES] = {.type = NLA_U64}, + [WGPEER_A_TX_BYTES] = {.type = NLA_U64}, + [WGPEER_A_ALLOWEDIPS] = {.type = NLA_NESTED}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + WireGuardPeerConstruct *peer_c; + + if (nla_parse_nested_arr(tb, peer_attr, policy) < 0) + return FALSE; + + if (!tb[WGPEER_A_PUBLIC_KEY]) + return FALSE; + + /* a peer with the same public key as last peer is just a continuation for extra AllowedIPs */ + peer_c = c_list_last_entry(peers, WireGuardPeerConstruct, lst); + if (peer_c + && !memcmp(nla_data(tb[WGPEER_A_PUBLIC_KEY]), + peer_c->data.public_key, + NMP_WIREGUARD_PUBLIC_KEY_LEN)) { + G_STATIC_ASSERT_EXPR(NMP_WIREGUARD_PUBLIC_KEY_LEN == sizeof(peer_c->data.public_key)); + /* this message is a continuation of the previous peer. + * Only parse WGPEER_A_ALLOWEDIPS below. */ + } else { + /* otherwise, start a new peer */ + peer_c = g_slice_new0(WireGuardPeerConstruct); + c_list_link_tail(peers, &peer_c->lst); + + nla_memcpy(&peer_c->data.public_key, + tb[WGPEER_A_PUBLIC_KEY], + sizeof(peer_c->data.public_key)); + + if (tb[WGPEER_A_PRESHARED_KEY]) { + nla_memcpy(&peer_c->data.preshared_key, + tb[WGPEER_A_PRESHARED_KEY], + sizeof(peer_c->data.preshared_key)); + /* FIXME(netlink-bzero-secret) */ + nm_explicit_bzero(nla_data(tb[WGPEER_A_PRESHARED_KEY]), + nla_len(tb[WGPEER_A_PRESHARED_KEY])); + } + + nm_sock_addr_union_cpy_untrusted( + &peer_c->data.endpoint, + tb[WGPEER_A_ENDPOINT] ? nla_data(tb[WGPEER_A_ENDPOINT]) : NULL, + tb[WGPEER_A_ENDPOINT] ? nla_len(tb[WGPEER_A_ENDPOINT]) : 0); + + if (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]) + peer_c->data.persistent_keepalive_interval = + nla_get_u16(tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]); + if (tb[WGPEER_A_LAST_HANDSHAKE_TIME]) { + if (nla_len(tb[WGPEER_A_LAST_HANDSHAKE_TIME]) + >= sizeof(peer_c->data.last_handshake_time)) + nla_memcpy(&peer_c->data.last_handshake_time, + tb[WGPEER_A_LAST_HANDSHAKE_TIME], + sizeof(peer_c->data.last_handshake_time)); + } + if (tb[WGPEER_A_RX_BYTES]) + peer_c->data.rx_bytes = nla_get_u64(tb[WGPEER_A_RX_BYTES]); + if (tb[WGPEER_A_TX_BYTES]) + peer_c->data.tx_bytes = nla_get_u64(tb[WGPEER_A_TX_BYTES]); + } + + if (tb[WGPEER_A_ALLOWEDIPS]) { + struct nlattr *attr; + int rem; + GArray * allowed_ips = *p_allowed_ips; + + nla_for_each_nested (attr, tb[WGPEER_A_ALLOWEDIPS], rem) { + if (!allowed_ips) { + allowed_ips = g_array_new(FALSE, FALSE, sizeof(NMPWireGuardAllowedIP)); + *p_allowed_ips = allowed_ips; + g_array_set_size(allowed_ips, 1); + } else + g_array_set_size(allowed_ips, allowed_ips->len + 1); + + if (!_wireguard_update_from_allowed_ips_nla( + &g_array_index(allowed_ips, NMPWireGuardAllowedIP, allowed_ips->len - 1), + attr)) { + /* we ignore the error of parsing one allowed-ip. */ + g_array_set_size(allowed_ips, allowed_ips->len - 1); + continue; + } + + if (!peer_c->data._construct_idx_end) + peer_c->data._construct_idx_start = allowed_ips->len - 1; + peer_c->data._construct_idx_end = allowed_ips->len; + } + } + + return TRUE; } typedef struct { - const int ifindex; - NMPObject *obj; - CList peers; - GArray *allowed_ips; + const int ifindex; + NMPObject *obj; + CList peers; + GArray * allowed_ips; } WireGuardParseData; static int -_wireguard_get_device_cb (struct nl_msg *msg, void *arg) -{ - static const struct nla_policy policy[] = { - [WGDEVICE_A_IFINDEX] = { .type = NLA_U32 }, - [WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .maxlen = IFNAMSIZ }, - [WGDEVICE_A_PRIVATE_KEY] = { }, - [WGDEVICE_A_PUBLIC_KEY] = { }, - [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, - [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 }, - [WGDEVICE_A_FWMARK] = { .type = NLA_U32 }, - [WGDEVICE_A_PEERS] = { .type = NLA_NESTED }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - WireGuardParseData *parse_data = arg; - - if (genlmsg_parse_arr (nlmsg_hdr (msg), 0, tb, policy) < 0) - return NL_SKIP; - - if (tb[WGDEVICE_A_IFINDEX]) { - int ifindex; - - ifindex = (int) nla_get_u32 (tb[WGDEVICE_A_IFINDEX]); - if ( ifindex <= 0 - || parse_data->ifindex != ifindex) - return NL_SKIP; - } else { - if (!parse_data->obj) - return NL_SKIP; - } - - if (parse_data->obj) { - /* we already have an object instance. This means the netlink message - * is a continuation, only providing more WGDEVICE_A_PEERS data below. */ - } else { - NMPObject *obj; - NMPlatformLnkWireGuard *props; - - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_WIREGUARD, NULL); - props = &obj->lnk_wireguard; - - if (tb[WGDEVICE_A_PRIVATE_KEY]) { - nla_memcpy (props->private_key, tb[WGDEVICE_A_PRIVATE_KEY], sizeof (props->private_key)); - /* FIXME(netlink-bzero-secret): extend netlink library to wipe memory. For now, - * just hack it here (yes, this does not cover all places where the - * private key was copied). */ - nm_explicit_bzero (nla_data (tb[WGDEVICE_A_PRIVATE_KEY]), - nla_len (tb[WGDEVICE_A_PRIVATE_KEY])); - } - if (tb[WGDEVICE_A_PUBLIC_KEY]) - nla_memcpy (props->public_key, tb[WGDEVICE_A_PUBLIC_KEY], sizeof (props->public_key)); - if (tb[WGDEVICE_A_LISTEN_PORT]) - props->listen_port = nla_get_u16 (tb[WGDEVICE_A_LISTEN_PORT]); - if (tb[WGDEVICE_A_FWMARK]) - props->fwmark = nla_get_u32 (tb[WGDEVICE_A_FWMARK]); - - parse_data->obj = obj; - } - - if (tb[WGDEVICE_A_PEERS]) { - struct nlattr *attr; - int rem; - - nla_for_each_nested (attr, tb[WGDEVICE_A_PEERS], rem) { - if (!_wireguard_update_from_peers_nla (&parse_data->peers, &parse_data->allowed_ips, attr)) { - /* we ignore the error of parsing one peer. - * _wireguard_update_from_peers_nla() leaves the @peers array in the - * desired state. */ - } - } - } - - return NL_OK; +_wireguard_get_device_cb(struct nl_msg *msg, void *arg) +{ + static const struct nla_policy policy[] = { + [WGDEVICE_A_IFINDEX] = {.type = NLA_U32}, + [WGDEVICE_A_IFNAME] = {.type = NLA_NUL_STRING, .maxlen = IFNAMSIZ}, + [WGDEVICE_A_PRIVATE_KEY] = {}, + [WGDEVICE_A_PUBLIC_KEY] = {}, + [WGDEVICE_A_FLAGS] = {.type = NLA_U32}, + [WGDEVICE_A_LISTEN_PORT] = {.type = NLA_U16}, + [WGDEVICE_A_FWMARK] = {.type = NLA_U32}, + [WGDEVICE_A_PEERS] = {.type = NLA_NESTED}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + WireGuardParseData *parse_data = arg; + + if (genlmsg_parse_arr(nlmsg_hdr(msg), 0, tb, policy) < 0) + return NL_SKIP; + + if (tb[WGDEVICE_A_IFINDEX]) { + int ifindex; + + ifindex = (int) nla_get_u32(tb[WGDEVICE_A_IFINDEX]); + if (ifindex <= 0 || parse_data->ifindex != ifindex) + return NL_SKIP; + } else { + if (!parse_data->obj) + return NL_SKIP; + } + + if (parse_data->obj) { + /* we already have an object instance. This means the netlink message + * is a continuation, only providing more WGDEVICE_A_PEERS data below. */ + } else { + NMPObject * obj; + NMPlatformLnkWireGuard *props; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_WIREGUARD, NULL); + props = &obj->lnk_wireguard; + + if (tb[WGDEVICE_A_PRIVATE_KEY]) { + nla_memcpy(props->private_key, tb[WGDEVICE_A_PRIVATE_KEY], sizeof(props->private_key)); + /* FIXME(netlink-bzero-secret): extend netlink library to wipe memory. For now, + * just hack it here (yes, this does not cover all places where the + * private key was copied). */ + nm_explicit_bzero(nla_data(tb[WGDEVICE_A_PRIVATE_KEY]), + nla_len(tb[WGDEVICE_A_PRIVATE_KEY])); + } + if (tb[WGDEVICE_A_PUBLIC_KEY]) + nla_memcpy(props->public_key, tb[WGDEVICE_A_PUBLIC_KEY], sizeof(props->public_key)); + if (tb[WGDEVICE_A_LISTEN_PORT]) + props->listen_port = nla_get_u16(tb[WGDEVICE_A_LISTEN_PORT]); + if (tb[WGDEVICE_A_FWMARK]) + props->fwmark = nla_get_u32(tb[WGDEVICE_A_FWMARK]); + + parse_data->obj = obj; + } + + if (tb[WGDEVICE_A_PEERS]) { + struct nlattr *attr; + int rem; + + nla_for_each_nested (attr, tb[WGDEVICE_A_PEERS], rem) { + if (!_wireguard_update_from_peers_nla(&parse_data->peers, + &parse_data->allowed_ips, + attr)) { + /* we ignore the error of parsing one peer. + * _wireguard_update_from_peers_nla() leaves the @peers array in the + * desired state. */ + } + } + } + + return NL_OK; } static const NMPObject * -_wireguard_read_info (NMPlatform *platform /* used only as logging context */, - struct nl_sock *genl, - int wireguard_family_id, - int ifindex) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - NMPObject *obj = NULL; - WireGuardPeerConstruct *peer_c; - WireGuardPeerConstruct *peer_c_safe; - gs_unref_array GArray *allowed_ips = NULL; - WireGuardParseData parse_data = { - .ifindex = ifindex, - }; - guint i; - - nm_assert (genl); - nm_assert (wireguard_family_id >= 0); - nm_assert (ifindex > 0); - - _LOGT ("wireguard: fetching information for ifindex %d (genl-id %d)...", ifindex, wireguard_family_id); - - msg = nlmsg_alloc (); - - if (!genlmsg_put (msg, - NL_AUTO_PORT, - NL_AUTO_SEQ, - wireguard_family_id, - 0, - NLM_F_DUMP, - WG_CMD_GET_DEVICE, - 1)) - return NULL; - - NLA_PUT_U32 (msg, WGDEVICE_A_IFINDEX, (guint32) ifindex); - - if (nl_send_auto (genl, msg) < 0) - return NULL; - - c_list_init (&parse_data.peers); - - /* we ignore errors, and return whatever we could successfully - * parse. */ - nl_recvmsgs (genl, - &((const struct nl_cb) { - .valid_cb = _wireguard_get_device_cb, - .valid_arg = (gpointer) &parse_data, - })); - - /* unpack: transfer ownership */ - obj = parse_data.obj; - allowed_ips = parse_data.allowed_ips; - - if (!obj) { - while ((peer_c = c_list_first_entry (&parse_data.peers, WireGuardPeerConstruct, lst))) { - c_list_unlink_stale (&peer_c->lst); - nm_explicit_bzero (&peer_c->data.preshared_key, sizeof (peer_c->data.preshared_key)); - g_slice_free (WireGuardPeerConstruct, peer_c); - } - return NULL; - } - - /* we receive peers/allowed-ips possibly in separate netlink messages. Hence, while - * parsing the dump, we don't know upfront how many peers/allowed-ips we will receive. - * - * We solve that, by collecting all peers with a CList. It's done this way, - * because a GArray would require growing the array, but we want to bzero() - * the preshared-key of each peer while reallocating. The CList apprach avoids - * that. - * - * For allowed-ips, we instead track one GArray, which are all appended - * there. The realloc/resize of the GArray is fine there. However, - * while we build the GArray, we don't yet have the final pointers. - * Hence, while constructing, we track the indexes with peer->_construct_idx_* - * fields. These indexes must be converted to actual pointers blow. - * - * This is all done during parsing. In the final NMPObjectLnkWireGuard we - * don't want the CList anymore and repackage the NMPObject tightly. The - * reason is, that NMPObject instances are immutable and long-living. Spend - * a bit effort below during construction to obtain a most suitable representation - * in this regard. */ - obj->_lnk_wireguard.peers_len = c_list_length (&parse_data.peers); - obj->_lnk_wireguard.peers = obj->_lnk_wireguard.peers_len > 0 - ? g_new (NMPWireGuardPeer, obj->_lnk_wireguard.peers_len) - : NULL; - - /* duplicate allowed_ips instead of using the pointer. The GArray possibly has more - * space allocated then we need, and we want to get rid of this excess buffer. - * Note that NMPObject instance is possibly put into the cache and long-living. */ - obj->_lnk_wireguard._allowed_ips_buf_len = allowed_ips ? allowed_ips->len : 0u; - obj->_lnk_wireguard._allowed_ips_buf = obj->_lnk_wireguard._allowed_ips_buf_len > 0 - ? (NMPWireGuardAllowedIP *) nm_memdup (allowed_ips->data, - sizeof (NMPWireGuardAllowedIP) * allowed_ips->len) - : NULL; - - i = 0; - c_list_for_each_entry_safe (peer_c, peer_c_safe, &parse_data.peers, lst) { - NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &obj->_lnk_wireguard.peers[i++]; - - *peer = peer_c->data; - - c_list_unlink_stale (&peer_c->lst); - nm_explicit_bzero (&peer_c->data.preshared_key, sizeof (peer_c->data.preshared_key)); - g_slice_free (WireGuardPeerConstruct, peer_c); - - if (peer->_construct_idx_end != 0) { - guint len; - - nm_assert (obj->_lnk_wireguard._allowed_ips_buf); - nm_assert (peer->_construct_idx_end > peer->_construct_idx_start); - nm_assert (peer->_construct_idx_start < obj->_lnk_wireguard._allowed_ips_buf_len); - nm_assert (peer->_construct_idx_end <= obj->_lnk_wireguard._allowed_ips_buf_len); - - len = peer->_construct_idx_end - peer->_construct_idx_start; - peer->allowed_ips = &obj->_lnk_wireguard._allowed_ips_buf[peer->_construct_idx_start]; - peer->allowed_ips_len = len; - } else { - nm_assert (!peer->_construct_idx_start); - nm_assert (!peer->_construct_idx_end); - peer->allowed_ips = NULL; - peer->allowed_ips_len = 0; - } - } - - return obj; +_wireguard_read_info(NMPlatform * platform /* used only as logging context */, + struct nl_sock *genl, + int wireguard_family_id, + int ifindex) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + NMPObject * obj = NULL; + WireGuardPeerConstruct * peer_c; + WireGuardPeerConstruct * peer_c_safe; + gs_unref_array GArray *allowed_ips = NULL; + WireGuardParseData parse_data = { + .ifindex = ifindex, + }; + guint i; + + nm_assert(genl); + nm_assert(wireguard_family_id >= 0); + nm_assert(ifindex > 0); + + _LOGT("wireguard: fetching information for ifindex %d (genl-id %d)...", + ifindex, + wireguard_family_id); + + msg = nlmsg_alloc(); + + if (!genlmsg_put(msg, + NL_AUTO_PORT, + NL_AUTO_SEQ, + wireguard_family_id, + 0, + NLM_F_DUMP, + WG_CMD_GET_DEVICE, + 1)) + return NULL; + + NLA_PUT_U32(msg, WGDEVICE_A_IFINDEX, (guint32) ifindex); + + if (nl_send_auto(genl, msg) < 0) + return NULL; + + c_list_init(&parse_data.peers); + + /* we ignore errors, and return whatever we could successfully + * parse. */ + nl_recvmsgs(genl, + &((const struct nl_cb){ + .valid_cb = _wireguard_get_device_cb, + .valid_arg = (gpointer) &parse_data, + })); + + /* unpack: transfer ownership */ + obj = parse_data.obj; + allowed_ips = parse_data.allowed_ips; + + if (!obj) { + while ((peer_c = c_list_first_entry(&parse_data.peers, WireGuardPeerConstruct, lst))) { + c_list_unlink_stale(&peer_c->lst); + nm_explicit_bzero(&peer_c->data.preshared_key, sizeof(peer_c->data.preshared_key)); + g_slice_free(WireGuardPeerConstruct, peer_c); + } + return NULL; + } + + /* we receive peers/allowed-ips possibly in separate netlink messages. Hence, while + * parsing the dump, we don't know upfront how many peers/allowed-ips we will receive. + * + * We solve that, by collecting all peers with a CList. It's done this way, + * because a GArray would require growing the array, but we want to bzero() + * the preshared-key of each peer while reallocating. The CList apprach avoids + * that. + * + * For allowed-ips, we instead track one GArray, which are all appended + * there. The realloc/resize of the GArray is fine there. However, + * while we build the GArray, we don't yet have the final pointers. + * Hence, while constructing, we track the indexes with peer->_construct_idx_* + * fields. These indexes must be converted to actual pointers blow. + * + * This is all done during parsing. In the final NMPObjectLnkWireGuard we + * don't want the CList anymore and repackage the NMPObject tightly. The + * reason is, that NMPObject instances are immutable and long-living. Spend + * a bit effort below during construction to obtain a most suitable representation + * in this regard. */ + obj->_lnk_wireguard.peers_len = c_list_length(&parse_data.peers); + obj->_lnk_wireguard.peers = obj->_lnk_wireguard.peers_len > 0 + ? g_new(NMPWireGuardPeer, obj->_lnk_wireguard.peers_len) + : NULL; + + /* duplicate allowed_ips instead of using the pointer. The GArray possibly has more + * space allocated then we need, and we want to get rid of this excess buffer. + * Note that NMPObject instance is possibly put into the cache and long-living. */ + obj->_lnk_wireguard._allowed_ips_buf_len = allowed_ips ? allowed_ips->len : 0u; + obj->_lnk_wireguard._allowed_ips_buf = + obj->_lnk_wireguard._allowed_ips_buf_len > 0 + ? (NMPWireGuardAllowedIP *) nm_memdup(allowed_ips->data, + sizeof(NMPWireGuardAllowedIP) * allowed_ips->len) + : NULL; + + i = 0; + c_list_for_each_entry_safe (peer_c, peer_c_safe, &parse_data.peers, lst) { + NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &obj->_lnk_wireguard.peers[i++]; + + *peer = peer_c->data; + + c_list_unlink_stale(&peer_c->lst); + nm_explicit_bzero(&peer_c->data.preshared_key, sizeof(peer_c->data.preshared_key)); + g_slice_free(WireGuardPeerConstruct, peer_c); + + if (peer->_construct_idx_end != 0) { + guint len; + + nm_assert(obj->_lnk_wireguard._allowed_ips_buf); + nm_assert(peer->_construct_idx_end > peer->_construct_idx_start); + nm_assert(peer->_construct_idx_start < obj->_lnk_wireguard._allowed_ips_buf_len); + nm_assert(peer->_construct_idx_end <= obj->_lnk_wireguard._allowed_ips_buf_len); + + len = peer->_construct_idx_end - peer->_construct_idx_start; + peer->allowed_ips = &obj->_lnk_wireguard._allowed_ips_buf[peer->_construct_idx_start]; + peer->allowed_ips_len = len; + } else { + nm_assert(!peer->_construct_idx_start); + nm_assert(!peer->_construct_idx_end); + peer->allowed_ips = NULL; + peer->allowed_ips_len = 0; + } + } + + return obj; nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static int -_wireguard_get_family_id (NMPlatform *platform, int ifindex_try) +_wireguard_get_family_id(NMPlatform *platform, int ifindex_try) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - int wireguard_family_id = -1; + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + int wireguard_family_id = -1; - if (ifindex_try > 0) { - const NMPlatformLink *plink; + if (ifindex_try > 0) { + const NMPlatformLink *plink; - if (nm_platform_link_get_lnk_wireguard (platform, ifindex_try, &plink)) - wireguard_family_id = NMP_OBJECT_UP_CAST (plink)->_link.wireguard_family_id; - } - if (wireguard_family_id < 0) - wireguard_family_id = genl_ctrl_resolve (priv->genl, "wireguard"); - return wireguard_family_id; + if (nm_platform_link_get_lnk_wireguard(platform, ifindex_try, &plink)) + wireguard_family_id = NMP_OBJECT_UP_CAST(plink)->_link.wireguard_family_id; + } + if (wireguard_family_id < 0) + wireguard_family_id = genl_ctrl_resolve(priv->genl, "wireguard"); + return wireguard_family_id; } static const NMPObject * -_wireguard_refresh_link (NMPlatform *platform, - int wireguard_family_id, - int ifindex) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - nm_auto_nmpobj const NMPObject *lnk_new = NULL; - NMPCacheOpsType cache_op; - const NMPObject *plink = NULL; - nm_auto_nmpobj NMPObject *obj = NULL; - - nm_assert (wireguard_family_id >= 0); - nm_assert (ifindex > 0); - - nm_platform_process_events (platform); - - plink = nm_platform_link_get_obj (platform, ifindex, TRUE); - - if ( !plink - || plink->link.type != NM_LINK_TYPE_WIREGUARD) { - nm_platform_link_refresh (platform, ifindex); - plink = nm_platform_link_get_obj (platform, ifindex, TRUE); - if ( !plink - || plink->link.type != NM_LINK_TYPE_WIREGUARD) - return NULL; - if (NMP_OBJECT_GET_TYPE (plink->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_WIREGUARD) - lnk_new = nmp_object_ref (plink->_link.netlink.lnk); - } else { - lnk_new = _wireguard_read_info (platform, - priv->genl, - wireguard_family_id, - ifindex); - if (!lnk_new) { - if (NMP_OBJECT_GET_TYPE (plink->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_WIREGUARD) - lnk_new = nmp_object_ref (plink->_link.netlink.lnk); - } else if (nmp_object_equal (plink->_link.netlink.lnk, lnk_new)) { - nmp_object_unref (lnk_new); - lnk_new = nmp_object_ref (plink->_link.netlink.lnk); - } - } - - if ( plink->_link.wireguard_family_id == wireguard_family_id - && plink->_link.netlink.lnk == lnk_new) - return plink; - - /* we use nmp_cache_update_netlink() to re-inject the new object into the cache. - * For that, we need to clone it, and tweak it so that it's suitable. It's a bit - * of a hack, in particular that we need to clear driver and udev-device. */ - obj = nmp_object_clone (plink, FALSE); - obj->_link.wireguard_family_id = wireguard_family_id; - nmp_object_unref (obj->_link.netlink.lnk); - obj->_link.netlink.lnk = g_steal_pointer (&lnk_new); - obj->link.driver = NULL; - nm_clear_pointer (&obj->_link.udev.device, udev_device_unref); - - cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform), - obj, - FALSE, - &obj_old, - &obj_new); - nm_assert (NM_IN_SET (cache_op, NMP_CACHE_OPS_UPDATED)); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - cache_on_change (platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); - } - - nm_assert ( !obj_new - || ( NMP_OBJECT_GET_TYPE (obj_new) == NMP_OBJECT_TYPE_LINK - && obj_new->link.type == NM_LINK_TYPE_WIREGUARD - && ( !obj_new->_link.netlink.lnk - || NMP_OBJECT_GET_TYPE (obj_new->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_WIREGUARD))); - return obj_new; +_wireguard_refresh_link(NMPlatform *platform, int wireguard_family_id, int ifindex) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + nm_auto_nmpobj const NMPObject *lnk_new = NULL; + NMPCacheOpsType cache_op; + const NMPObject * plink = NULL; + nm_auto_nmpobj NMPObject *obj = NULL; + + nm_assert(wireguard_family_id >= 0); + nm_assert(ifindex > 0); + + nm_platform_process_events(platform); + + plink = nm_platform_link_get_obj(platform, ifindex, TRUE); + + if (!plink || plink->link.type != NM_LINK_TYPE_WIREGUARD) { + nm_platform_link_refresh(platform, ifindex); + plink = nm_platform_link_get_obj(platform, ifindex, TRUE); + if (!plink || plink->link.type != NM_LINK_TYPE_WIREGUARD) + return NULL; + if (NMP_OBJECT_GET_TYPE(plink->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_WIREGUARD) + lnk_new = nmp_object_ref(plink->_link.netlink.lnk); + } else { + lnk_new = _wireguard_read_info(platform, priv->genl, wireguard_family_id, ifindex); + if (!lnk_new) { + if (NMP_OBJECT_GET_TYPE(plink->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_WIREGUARD) + lnk_new = nmp_object_ref(plink->_link.netlink.lnk); + } else if (nmp_object_equal(plink->_link.netlink.lnk, lnk_new)) { + nmp_object_unref(lnk_new); + lnk_new = nmp_object_ref(plink->_link.netlink.lnk); + } + } + + if (plink->_link.wireguard_family_id == wireguard_family_id + && plink->_link.netlink.lnk == lnk_new) + return plink; + + /* we use nmp_cache_update_netlink() to re-inject the new object into the cache. + * For that, we need to clone it, and tweak it so that it's suitable. It's a bit + * of a hack, in particular that we need to clear driver and udev-device. */ + obj = nmp_object_clone(plink, FALSE); + obj->_link.wireguard_family_id = wireguard_family_id; + nmp_object_unref(obj->_link.netlink.lnk); + obj->_link.netlink.lnk = g_steal_pointer(&lnk_new); + obj->link.driver = NULL; + nm_clear_pointer(&obj->_link.udev.device, udev_device_unref); + + cache_op = + nmp_cache_update_netlink(nm_platform_get_cache(platform), obj, FALSE, &obj_old, &obj_new); + nm_assert(NM_IN_SET(cache_op, NMP_CACHE_OPS_UPDATED)); + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + cache_on_change(platform, cache_op, obj_old, obj_new); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); + } + + nm_assert(!obj_new + || (NMP_OBJECT_GET_TYPE(obj_new) == NMP_OBJECT_TYPE_LINK + && obj_new->link.type == NM_LINK_TYPE_WIREGUARD + && (!obj_new->_link.netlink.lnk + || NMP_OBJECT_GET_TYPE(obj_new->_link.netlink.lnk) + == NMP_OBJECT_TYPE_LNK_WIREGUARD))); + return obj_new; } static int -_wireguard_create_change_nlmsgs (NMPlatform *platform, - int ifindex, - int wireguard_family_id, - const NMPlatformLnkWireGuard *lnk_wireguard, - const NMPWireGuardPeer *peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags, - GPtrArray **out_msgs) -{ - gs_unref_ptrarray GPtrArray *msgs = NULL; - nm_auto_nlmsg struct nl_msg *msg = NULL; - const guint IDX_NIL = G_MAXUINT; - guint idx_peer_curr; - guint idx_allowed_ips_curr; - struct nlattr *nest_peers; - struct nlattr *nest_curr_peer; - struct nlattr *nest_allowed_ips; - struct nlattr *nest_curr_allowed_ip; - NMPlatformWireGuardChangePeerFlags p_flags = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT; - -#define _nla_nest_end(msg, nest_start) \ - G_STMT_START { \ - if (nla_nest_end ((msg), (nest_start)) < 0) \ - g_return_val_if_reached (-NME_BUG); \ - } G_STMT_END - - /* Adapted from LGPL-2.1+ code [1]. - * - * [1] https://git.zx2c4.com/WireGuard/tree/contrib/examples/embeddable-wg-library/wireguard.c?id=5e99a6d43fe2351adf36c786f5ea2086a8fe7ab8#n1073 */ - - idx_peer_curr = IDX_NIL; - idx_allowed_ips_curr = IDX_NIL; - - /* TODO: for the moment, we always reset all peers and allowed-ips (WGDEVICE_F_REPLACE_PEERS, WGPEER_F_REPLACE_ALLOWEDIPS). - * The platform API should be extended to also support partial updates. In particular, configuring the same configuration - * multiple times, should not clear and re-add all settings, but rather sync the existing settings with the desired configuration. */ +_wireguard_create_change_nlmsgs(NMPlatform * platform, + int ifindex, + int wireguard_family_id, + const NMPlatformLnkWireGuard * lnk_wireguard, + const NMPWireGuardPeer * peers, + const NMPlatformWireGuardChangePeerFlags *peer_flags, + guint peers_len, + NMPlatformWireGuardChangeFlags change_flags, + GPtrArray ** out_msgs) +{ + gs_unref_ptrarray GPtrArray * msgs = NULL; + nm_auto_nlmsg struct nl_msg * msg = NULL; + const guint IDX_NIL = G_MAXUINT; + guint idx_peer_curr; + guint idx_allowed_ips_curr; + struct nlattr * nest_peers; + struct nlattr * nest_curr_peer; + struct nlattr * nest_allowed_ips; + struct nlattr * nest_curr_allowed_ip; + NMPlatformWireGuardChangePeerFlags p_flags = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT; + +#define _nla_nest_end(msg, nest_start) \ + G_STMT_START \ + { \ + if (nla_nest_end((msg), (nest_start)) < 0) \ + g_return_val_if_reached(-NME_BUG); \ + } \ + G_STMT_END + + /* Adapted from LGPL-2.1+ code [1]. + * + * [1] https://git.zx2c4.com/WireGuard/tree/contrib/examples/embeddable-wg-library/wireguard.c?id=5e99a6d43fe2351adf36c786f5ea2086a8fe7ab8#n1073 */ + + idx_peer_curr = IDX_NIL; + idx_allowed_ips_curr = IDX_NIL; + + /* TODO: for the moment, we always reset all peers and allowed-ips (WGDEVICE_F_REPLACE_PEERS, WGPEER_F_REPLACE_ALLOWEDIPS). + * The platform API should be extended to also support partial updates. In particular, configuring the same configuration + * multiple times, should not clear and re-add all settings, but rather sync the existing settings with the desired configuration. */ again: - msg = nlmsg_alloc (); - if (!genlmsg_put (msg, - NL_AUTO_PORT, - NL_AUTO_SEQ, - wireguard_family_id, - 0, - NLM_F_REQUEST, - WG_CMD_SET_DEVICE, - 1)) - g_return_val_if_reached (-NME_BUG); - - NLA_PUT_U32 (msg, WGDEVICE_A_IFINDEX, (guint32) ifindex); - - if (idx_peer_curr == IDX_NIL) { - guint32 flags; - - if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY)) - NLA_PUT (msg, WGDEVICE_A_PRIVATE_KEY, sizeof (lnk_wireguard->private_key), lnk_wireguard->private_key); - if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT)) - NLA_PUT_U16 (msg, WGDEVICE_A_LISTEN_PORT, lnk_wireguard->listen_port); - if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK)) - NLA_PUT_U32 (msg, WGDEVICE_A_FWMARK, lnk_wireguard->fwmark); - - flags = 0; - if (NM_FLAGS_HAS (change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS)) - flags |= WGDEVICE_F_REPLACE_PEERS; - NLA_PUT_U32 (msg, WGDEVICE_A_FLAGS, flags); - } - - if (peers_len == 0) - goto send; - - nest_curr_peer = NULL; - nest_allowed_ips = NULL; - nest_curr_allowed_ip = NULL; - - nest_peers = nla_nest_start (msg, WGDEVICE_A_PEERS); - if (!nest_peers) - g_return_val_if_reached (-NME_BUG); - - if (idx_peer_curr == IDX_NIL) - idx_peer_curr = 0; - for (; idx_peer_curr < peers_len; idx_peer_curr++) { - const NMPWireGuardPeer *p = &peers[idx_peer_curr]; - - if (peer_flags) { - p_flags = peer_flags[idx_peer_curr]; - if (!NM_FLAGS_ANY (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS)) { - /* no flags set. We take that as indication to skip configuring the peer - * entirely. */ - nm_assert (p_flags == NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE); - continue; - } - } - - nest_curr_peer = nla_nest_start (msg, 0); - if (!nest_curr_peer) - goto toobig_peers; - - if (nla_put (msg, WGPEER_A_PUBLIC_KEY, NMP_WIREGUARD_PUBLIC_KEY_LEN, p->public_key) < 0) - goto toobig_peers; - - if (NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME)) { - /* all other p_flags are silently ignored. */ - if (nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REMOVE_ME) < 0) - goto toobig_peers; - } else { - - if (idx_allowed_ips_curr == IDX_NIL) { - if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY) - && nla_put (msg, WGPEER_A_PRESHARED_KEY, sizeof (p->preshared_key), p->preshared_key) < 0) - goto toobig_peers; - - if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL) - && nla_put_uint16 (msg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, p->persistent_keepalive_interval) < 0) - goto toobig_peers; - - if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS) - && nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0) - goto toobig_peers; - - if (NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT)) { - if (NM_IN_SET (p->endpoint.sa.sa_family, AF_INET, AF_INET6)) { - if (nla_put (msg, - WGPEER_A_ENDPOINT, - p->endpoint.sa.sa_family == AF_INET - ? sizeof (p->endpoint.in) - : sizeof (p->endpoint.in6), - &p->endpoint) < 0) - goto toobig_peers; - } else { - /* I think there is no way to clear an endpoint, though there shold be. */ - nm_assert (p->endpoint.sa.sa_family == AF_UNSPEC); - } - } - } - - if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS) - && p->allowed_ips_len > 0) { - if (idx_allowed_ips_curr == IDX_NIL) - idx_allowed_ips_curr = 0; - - nest_allowed_ips = nla_nest_start (msg, WGPEER_A_ALLOWEDIPS); - if (!nest_allowed_ips) - goto toobig_allowedips; - - for (; idx_allowed_ips_curr < p->allowed_ips_len; idx_allowed_ips_curr++) { - const NMPWireGuardAllowedIP *aip = &p->allowed_ips[idx_allowed_ips_curr]; - - nest_curr_allowed_ip = nla_nest_start (msg, 0); - if (!nest_curr_allowed_ip) - goto toobig_allowedips; - - g_return_val_if_fail (NM_IN_SET (aip->family, AF_INET, AF_INET6), -NME_BUG); - - if (nla_put_uint16 (msg, WGALLOWEDIP_A_FAMILY, aip->family) < 0) - goto toobig_allowedips; - if (nla_put (msg, - WGALLOWEDIP_A_IPADDR, - nm_utils_addr_family_to_size (aip->family), - &aip->addr) < 0) - goto toobig_allowedips; - if (nla_put_uint8 (msg, WGALLOWEDIP_A_CIDR_MASK, aip->mask) < 0) - goto toobig_allowedips; - - _nla_nest_end (msg, nest_curr_allowed_ip); - nest_curr_allowed_ip = NULL; - } - idx_allowed_ips_curr = IDX_NIL; - - _nla_nest_end (msg, nest_allowed_ips); - nest_allowed_ips = NULL; - } - } - - _nla_nest_end (msg, nest_curr_peer); - nest_curr_peer = NULL; - } - - _nla_nest_end (msg, nest_peers); - goto send; + msg = nlmsg_alloc(); + if (!genlmsg_put(msg, + NL_AUTO_PORT, + NL_AUTO_SEQ, + wireguard_family_id, + 0, + NLM_F_REQUEST, + WG_CMD_SET_DEVICE, + 1)) + g_return_val_if_reached(-NME_BUG); + + NLA_PUT_U32(msg, WGDEVICE_A_IFINDEX, (guint32) ifindex); + + if (idx_peer_curr == IDX_NIL) { + guint32 flags; + + if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY)) + NLA_PUT(msg, + WGDEVICE_A_PRIVATE_KEY, + sizeof(lnk_wireguard->private_key), + lnk_wireguard->private_key); + if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT)) + NLA_PUT_U16(msg, WGDEVICE_A_LISTEN_PORT, lnk_wireguard->listen_port); + if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK)) + NLA_PUT_U32(msg, WGDEVICE_A_FWMARK, lnk_wireguard->fwmark); + + flags = 0; + if (NM_FLAGS_HAS(change_flags, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS)) + flags |= WGDEVICE_F_REPLACE_PEERS; + NLA_PUT_U32(msg, WGDEVICE_A_FLAGS, flags); + } + + if (peers_len == 0) + goto send; + + nest_curr_peer = NULL; + nest_allowed_ips = NULL; + nest_curr_allowed_ip = NULL; + + nest_peers = nla_nest_start(msg, WGDEVICE_A_PEERS); + if (!nest_peers) + g_return_val_if_reached(-NME_BUG); + + if (idx_peer_curr == IDX_NIL) + idx_peer_curr = 0; + for (; idx_peer_curr < peers_len; idx_peer_curr++) { + const NMPWireGuardPeer *p = &peers[idx_peer_curr]; + + if (peer_flags) { + p_flags = peer_flags[idx_peer_curr]; + if (!NM_FLAGS_ANY(p_flags, + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS)) { + /* no flags set. We take that as indication to skip configuring the peer + * entirely. */ + nm_assert(p_flags == NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE); + continue; + } + } + + nest_curr_peer = nla_nest_start(msg, 0); + if (!nest_curr_peer) + goto toobig_peers; + + if (nla_put(msg, WGPEER_A_PUBLIC_KEY, NMP_WIREGUARD_PUBLIC_KEY_LEN, p->public_key) < 0) + goto toobig_peers; + + if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME)) { + /* all other p_flags are silently ignored. */ + if (nla_put_uint32(msg, WGPEER_A_FLAGS, WGPEER_F_REMOVE_ME) < 0) + goto toobig_peers; + } else { + if (idx_allowed_ips_curr == IDX_NIL) { + if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY) + && nla_put(msg, + WGPEER_A_PRESHARED_KEY, + sizeof(p->preshared_key), + p->preshared_key) + < 0) + goto toobig_peers; + + if (NM_FLAGS_HAS(p_flags, + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL) + && nla_put_uint16(msg, + WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, + p->persistent_keepalive_interval) + < 0) + goto toobig_peers; + + if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS) + && nla_put_uint32(msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0) + goto toobig_peers; + + if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT)) { + if (NM_IN_SET(p->endpoint.sa.sa_family, AF_INET, AF_INET6)) { + if (nla_put(msg, + WGPEER_A_ENDPOINT, + p->endpoint.sa.sa_family == AF_INET ? sizeof(p->endpoint.in) + : sizeof(p->endpoint.in6), + &p->endpoint) + < 0) + goto toobig_peers; + } else { + /* I think there is no way to clear an endpoint, though there should be. */ + nm_assert(p->endpoint.sa.sa_family == AF_UNSPEC); + } + } + } + + if (NM_FLAGS_HAS(p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS) + && p->allowed_ips_len > 0) { + if (idx_allowed_ips_curr == IDX_NIL) + idx_allowed_ips_curr = 0; + + nest_allowed_ips = nla_nest_start(msg, WGPEER_A_ALLOWEDIPS); + if (!nest_allowed_ips) + goto toobig_allowedips; + + for (; idx_allowed_ips_curr < p->allowed_ips_len; idx_allowed_ips_curr++) { + const NMPWireGuardAllowedIP *aip = &p->allowed_ips[idx_allowed_ips_curr]; + + nest_curr_allowed_ip = nla_nest_start(msg, 0); + if (!nest_curr_allowed_ip) + goto toobig_allowedips; + + g_return_val_if_fail(NM_IN_SET(aip->family, AF_INET, AF_INET6), -NME_BUG); + + if (nla_put_uint16(msg, WGALLOWEDIP_A_FAMILY, aip->family) < 0) + goto toobig_allowedips; + if (nla_put(msg, + WGALLOWEDIP_A_IPADDR, + nm_utils_addr_family_to_size(aip->family), + &aip->addr) + < 0) + goto toobig_allowedips; + if (nla_put_uint8(msg, WGALLOWEDIP_A_CIDR_MASK, aip->mask) < 0) + goto toobig_allowedips; + + _nla_nest_end(msg, nest_curr_allowed_ip); + nest_curr_allowed_ip = NULL; + } + idx_allowed_ips_curr = IDX_NIL; + + _nla_nest_end(msg, nest_allowed_ips); + nest_allowed_ips = NULL; + } + } + + _nla_nest_end(msg, nest_curr_peer); + nest_curr_peer = NULL; + } + + _nla_nest_end(msg, nest_peers); + goto send; toobig_allowedips: - if (nest_curr_allowed_ip) - nla_nest_cancel (msg, nest_curr_allowed_ip); - if (nest_allowed_ips) - nla_nest_cancel (msg, nest_allowed_ips); - _nla_nest_end (msg, nest_curr_peer); - _nla_nest_end (msg, nest_peers); - goto send; + if (nest_curr_allowed_ip) + nla_nest_cancel(msg, nest_curr_allowed_ip); + if (nest_allowed_ips) + nla_nest_cancel(msg, nest_allowed_ips); + _nla_nest_end(msg, nest_curr_peer); + _nla_nest_end(msg, nest_peers); + goto send; toobig_peers: - if (nest_curr_peer) - nla_nest_cancel (msg, nest_curr_peer); - _nla_nest_end (msg, nest_peers); - goto send; + if (nest_curr_peer) + nla_nest_cancel(msg, nest_curr_peer); + _nla_nest_end(msg, nest_peers); + goto send; send: - if (!msgs) - msgs = g_ptr_array_new_with_free_func ((GDestroyNotify) nlmsg_free); - g_ptr_array_add (msgs, g_steal_pointer (&msg)); + if (!msgs) + msgs = g_ptr_array_new_with_free_func((GDestroyNotify) nlmsg_free); + g_ptr_array_add(msgs, g_steal_pointer(&msg)); - if ( idx_peer_curr != IDX_NIL - && idx_peer_curr < peers_len) - goto again; + if (idx_peer_curr != IDX_NIL && idx_peer_curr < peers_len) + goto again; - NM_SET_OUT (out_msgs, g_steal_pointer (&msgs)); - return 0; + NM_SET_OUT(out_msgs, g_steal_pointer(&msgs)); + return 0; nla_put_failure: - g_return_val_if_reached (-NME_BUG); + g_return_val_if_reached(-NME_BUG); #undef _nla_nest_end } static int -link_wireguard_change (NMPlatform *platform, - int ifindex, - const NMPlatformLnkWireGuard *lnk_wireguard, - const NMPWireGuardPeer *peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - gs_unref_ptrarray GPtrArray *msgs = NULL; - int wireguard_family_id; - guint i; - int r; - - wireguard_family_id = _wireguard_get_family_id (platform, ifindex); - if (wireguard_family_id < 0) - return -NME_PL_NO_FIRMWARE; - - r = _wireguard_create_change_nlmsgs (platform, - ifindex, - wireguard_family_id, - lnk_wireguard, - peers, - peer_flags, - peers_len, - change_flags, - &msgs); - if (r < 0) { - _LOGW ("wireguard: set-device, cannot construct netlink message: %s", nm_strerror (r)); - return r; - } - - for (i = 0; i < msgs->len; i++) { - r = nl_send_auto (priv->genl, msgs->pdata[i]); - if (r < 0) { - _LOGW ("wireguard: set-device, send netlink message #%u failed: %s", i, nm_strerror (r)); - return r; - } - - do { - r = nl_recvmsgs (priv->genl, NULL); - } while (r == -EAGAIN); - if (r < 0) { - _LOGW ("wireguard: set-device, message #%u was rejected: %s", i, nm_strerror (r)); - return r; - } - - _LOGT ("wireguard: set-device, message #%u sent and confirmed", i); - } - - _wireguard_refresh_link (platform, wireguard_family_id, ifindex); - - return 0; +link_wireguard_change(NMPlatform * platform, + int ifindex, + const NMPlatformLnkWireGuard * lnk_wireguard, + const NMPWireGuardPeer * peers, + const NMPlatformWireGuardChangePeerFlags *peer_flags, + guint peers_len, + NMPlatformWireGuardChangeFlags change_flags) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + gs_unref_ptrarray GPtrArray *msgs = NULL; + int wireguard_family_id; + guint i; + int r; + + wireguard_family_id = _wireguard_get_family_id(platform, ifindex); + if (wireguard_family_id < 0) + return -NME_PL_NO_FIRMWARE; + + r = _wireguard_create_change_nlmsgs(platform, + ifindex, + wireguard_family_id, + lnk_wireguard, + peers, + peer_flags, + peers_len, + change_flags, + &msgs); + if (r < 0) { + _LOGW("wireguard: set-device, cannot construct netlink message: %s", nm_strerror(r)); + return r; + } + + for (i = 0; i < msgs->len; i++) { + r = nl_send_auto(priv->genl, msgs->pdata[i]); + if (r < 0) { + _LOGW("wireguard: set-device, send netlink message #%u failed: %s", i, nm_strerror(r)); + return r; + } + + do { + r = nl_recvmsgs(priv->genl, NULL); + } while (r == -EAGAIN); + if (r < 0) { + _LOGW("wireguard: set-device, message #%u was rejected: %s", i, nm_strerror(r)); + return r; + } + + _LOGT("wireguard: set-device, message #%u sent and confirmed", i); + } + + _wireguard_refresh_link(platform, wireguard_family_id, ifindex); + + return 0; } /*****************************************************************************/ static void -_nmp_link_address_set (NMPLinkAddress *dst, - const struct nlattr *nla) +_nmp_link_address_set(NMPLinkAddress *dst, const struct nlattr *nla) { - *dst = (NMPLinkAddress) { - .len = 0, - }; - if (nla) { - int l = nla_len (nla); + *dst = (NMPLinkAddress){ + .len = 0, + }; + if (nla) { + int l = nla_len(nla); - if ( l > 0 - && l <= NM_UTILS_HWADDR_LEN_MAX) { - G_STATIC_ASSERT_EXPR (sizeof (dst->data) == NM_UTILS_HWADDR_LEN_MAX); - memcpy (dst->data, nla_data (nla), l); - dst->len = l; - } - } + if (l > 0 && l <= NM_UTILS_HWADDR_LEN_MAX) { + G_STATIC_ASSERT_EXPR(sizeof(dst->data) == NM_UTILS_HWADDR_LEN_MAX); + memcpy(dst->data, nla_data(nla), l); + dst->len = l; + } + } } /* Copied and heavily modified from libnl3's link_msg_parser(). */ static NMPObject * -_new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [IFLA_IFNAME] = { .type = NLA_STRING, - .maxlen = IFNAMSIZ }, - [IFLA_MTU] = { .type = NLA_U32 }, - [IFLA_TXQLEN] = { .type = NLA_U32 }, - [IFLA_LINK] = { .type = NLA_U32 }, - [IFLA_WEIGHT] = { .type = NLA_U32 }, - [IFLA_MASTER] = { .type = NLA_U32 }, - [IFLA_OPERSTATE] = { .type = NLA_U8 }, - [IFLA_LINKMODE] = { .type = NLA_U8 }, - [IFLA_LINKINFO] = { .type = NLA_NESTED }, - [IFLA_QDISC] = { .type = NLA_STRING, - .maxlen = IFQDISCSIZ }, - [IFLA_STATS] = { .minlen = nm_offsetofend (struct rtnl_link_stats, tx_compressed) }, - [IFLA_STATS64] = { .minlen = nm_offsetofend (struct rtnl_link_stats64, tx_compressed)}, - [IFLA_MAP] = { .minlen = nm_offsetofend (struct rtnl_link_ifmap, port) }, - [IFLA_IFALIAS] = { .type = NLA_STRING, .maxlen = IFALIASZ }, - [IFLA_NUM_VF] = { .type = NLA_U32 }, - [IFLA_AF_SPEC] = { .type = NLA_NESTED }, - [IFLA_PROMISCUITY] = { .type = NLA_U32 }, - [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, - [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, - [IFLA_GROUP] = { .type = NLA_U32 }, - [IFLA_CARRIER] = { .type = NLA_U8 }, - [IFLA_PHYS_PORT_ID] = { .type = NLA_UNSPEC }, - [IFLA_NET_NS_PID] = { .type = NLA_U32 }, - [IFLA_NET_NS_FD] = { .type = NLA_U32 }, - [IFLA_LINK_NETNSID] = { }, - }; - const struct ifinfomsg *ifi; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - struct nlattr *nl_info_data = NULL; - const char *nl_info_kind = NULL; - nm_auto_nmpobj NMPObject *obj = NULL; - gboolean completed_from_cache_val = FALSE; - gboolean *completed_from_cache = cache ? &completed_from_cache_val : NULL; - const NMPObject *link_cached = NULL; - const NMPObject *lnk_data = NULL; - gboolean address_complete_from_cache = TRUE; - gboolean broadcast_complete_from_cache = TRUE; - gboolean lnk_data_complete_from_cache = TRUE; - gboolean need_ext_data = FALSE; - gboolean af_inet6_token_valid = FALSE; - gboolean af_inet6_addr_gen_mode_valid = FALSE; - - if (!nlmsg_valid_hdr (nlh, sizeof (*ifi))) - return NULL; - - ifi = nlmsg_data (nlh); - - if (ifi->ifi_family != AF_UNSPEC) - return NULL; - if (ifi->ifi_index <= 0) - return NULL; - - obj = nmp_object_new_link (ifi->ifi_index); - - if (id_only) - return g_steal_pointer (&obj); - - if (nlmsg_parse_arr (nlh, sizeof (*ifi), tb, policy) < 0) - return NULL; - - if (!tb[IFLA_IFNAME]) - return NULL; - nla_strlcpy (obj->link.name, tb[IFLA_IFNAME], IFNAMSIZ); - if (!obj->link.name[0]) - return NULL; - - if (!tb[IFLA_MTU]) { - /* Kernel has two places that send RTM_GETLINK messages: - * net/core/rtnetlink.c and net/wireless/ext-core.c. - * Unfotunatelly ext-core.c sets only IFLA_WIRELESS and - * IFLA_IFNAME. This confuses code in this function, because - * it cannot get complete set of data for the interface and - * later incomplete object this function creates is used to - * overwrite existing data in NM's cache. - * Since ext-core.c doesn't set IFLA_MTU we can use it as a - * signal to ignore incoming message. - * To some extent this is a hack and correct approach is to - * merge objects per-field. - */ - return NULL; - } - obj->link.mtu = nla_get_u32 (tb[IFLA_MTU]); - - if (tb[IFLA_LINKINFO]) { - static const struct nla_policy policy_link_info[] = { - [IFLA_INFO_KIND] = { .type = NLA_STRING }, - [IFLA_INFO_DATA] = { .type = NLA_NESTED }, - [IFLA_INFO_XSTATS] = { .type = NLA_NESTED }, - }; - struct nlattr *li[G_N_ELEMENTS (policy_link_info)]; - - if (nla_parse_nested_arr (li, tb[IFLA_LINKINFO], policy_link_info) < 0) - return NULL; - - if (li[IFLA_INFO_KIND]) - nl_info_kind = nla_get_string (li[IFLA_INFO_KIND]); - - nl_info_data = li[IFLA_INFO_DATA]; - } - - if (tb[IFLA_STATS64]) { - const char *stats = nla_data (tb[IFLA_STATS64]); - - obj->link.rx_packets = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, rx_packets)]); - obj->link.rx_bytes = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, rx_bytes)]); - obj->link.tx_packets = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, tx_packets)]); - obj->link.tx_bytes = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, tx_bytes)]); - } - - obj->link.n_ifi_flags = ifi->ifi_flags; - obj->link.connected = NM_FLAGS_HAS (obj->link.n_ifi_flags, IFF_LOWER_UP); - obj->link.arptype = ifi->ifi_type; - - obj->link.type = _linktype_get_type (platform, - cache, - nl_info_kind, - obj->link.ifindex, - obj->link.name, - obj->link.n_ifi_flags, - obj->link.arptype, - completed_from_cache, - &link_cached, - &obj->link.kind); - - if (tb[IFLA_MASTER]) - obj->link.master = nla_get_u32 (tb[IFLA_MASTER]); - - if (tb[IFLA_LINK]) { - if (!tb[IFLA_LINK_NETNSID]) - obj->link.parent = nla_get_u32 (tb[IFLA_LINK]); - else - obj->link.parent = NM_PLATFORM_LINK_OTHER_NETNS; - } - - if (tb[IFLA_ADDRESS]) { - _nmp_link_address_set (&obj->link.l_address, tb[IFLA_ADDRESS]); - address_complete_from_cache = FALSE; - } - - if (tb[IFLA_BROADCAST]) { - _nmp_link_address_set (&obj->link.l_broadcast, tb[IFLA_BROADCAST]); - broadcast_complete_from_cache = FALSE; - } - - if (tb[IFLA_AF_SPEC]) { - struct nlattr *af_attr; - int remaining; - - nla_for_each_nested (af_attr, tb[IFLA_AF_SPEC], remaining) { - switch (nla_type (af_attr)) { - case AF_INET6: - _parse_af_inet6 (platform, - af_attr, - &obj->link.inet6_token, - &af_inet6_token_valid, - &obj->link.inet6_addr_gen_mode_inv, - &af_inet6_addr_gen_mode_valid); - break; - } - } - } - - switch (obj->link.type) { - case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: - lnk_data = _parse_lnk_gre (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_INFINIBAND: - lnk_data = _parse_lnk_infiniband (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_IP6TNL: - lnk_data = _parse_lnk_ip6tnl (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_IP6GRE: - case NM_LINK_TYPE_IP6GRETAP: - lnk_data = _parse_lnk_ip6gre (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_IPIP: - lnk_data = _parse_lnk_ipip (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_MACSEC: - lnk_data = _parse_lnk_macsec (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_MACVLAN: - case NM_LINK_TYPE_MACVTAP: - lnk_data = _parse_lnk_macvlan (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_SIT: - lnk_data = _parse_lnk_sit (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_TUN: - lnk_data = _parse_lnk_tun (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_VLAN: - lnk_data = _parse_lnk_vlan (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_VRF: - lnk_data = _parse_lnk_vrf (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_VXLAN: - lnk_data = _parse_lnk_vxlan (nl_info_kind, nl_info_data); - break; - case NM_LINK_TYPE_WIFI: - case NM_LINK_TYPE_OLPC_MESH: - case NM_LINK_TYPE_WPAN: - need_ext_data = TRUE; - lnk_data_complete_from_cache = FALSE; - break; - case NM_LINK_TYPE_WIREGUARD: - lnk_data_complete_from_cache = TRUE; - break; - default: - lnk_data_complete_from_cache = FALSE; - break; - } - - if ( completed_from_cache - && ( lnk_data_complete_from_cache - || need_ext_data - || address_complete_from_cache - || broadcast_complete_from_cache - || !af_inet6_token_valid - || !af_inet6_addr_gen_mode_valid - || !tb[IFLA_STATS64])) { - _lookup_cached_link (cache, obj->link.ifindex, completed_from_cache, &link_cached); - if ( link_cached - && link_cached->_link.netlink.is_in_netlink) { - if ( lnk_data_complete_from_cache - && link_cached->link.type == obj->link.type - && link_cached->_link.netlink.lnk - && ( !lnk_data - || nmp_object_equal (lnk_data, link_cached->_link.netlink.lnk))) { - /* We always try to look into the cache and reuse the object there. - * We do that, because we consider the lnk object as immutable and don't - * modify it after creating. Hence we can share it and reuse. - * - * Also, sometimes the info-data is missing for updates. In this case - * we want to keep the previously received lnk_data. */ - nmp_object_unref (lnk_data); - lnk_data = nmp_object_ref (link_cached->_link.netlink.lnk); - } - - if ( need_ext_data - && link_cached->link.type == obj->link.type - && link_cached->_link.ext_data) { - /* Prefer reuse of existing ext_data object */ - obj->_link.ext_data = g_object_ref (link_cached->_link.ext_data); - } - - if (address_complete_from_cache) - obj->link.l_address = link_cached->link.l_address; - if (broadcast_complete_from_cache) - obj->link.l_broadcast = link_cached->link.l_broadcast; - if (!af_inet6_token_valid) - obj->link.inet6_token = link_cached->link.inet6_token; - if (!af_inet6_addr_gen_mode_valid) - obj->link.inet6_addr_gen_mode_inv = link_cached->link.inet6_addr_gen_mode_inv; - if (!tb[IFLA_STATS64]) { - obj->link.rx_packets = link_cached->link.rx_packets; - obj->link.rx_bytes = link_cached->link.rx_bytes; - obj->link.tx_packets = link_cached->link.tx_packets; - obj->link.tx_bytes = link_cached->link.tx_bytes; - } - } - } - - obj->_link.netlink.lnk = lnk_data; - - if ( need_ext_data - && obj->_link.ext_data == NULL) { - switch (obj->link.type) { - case NM_LINK_TYPE_WIFI: - case NM_LINK_TYPE_OLPC_MESH: - obj->_link.ext_data = (GObject *) nm_wifi_utils_new (ifi->ifi_index, - _genl_sock (NM_LINUX_PLATFORM (platform)), - TRUE); - break; - case NM_LINK_TYPE_WPAN: - obj->_link.ext_data = (GObject *) nm_wpan_utils_new (ifi->ifi_index, - _genl_sock (NM_LINUX_PLATFORM (platform)), - TRUE); - break; - default: - g_assert_not_reached (); - } - } - - if (obj->link.type == NM_LINK_TYPE_WIREGUARD) { - const NMPObject *lnk_data_new = NULL; - struct nl_sock *genl = NM_LINUX_PLATFORM_GET_PRIVATE (platform)->genl; - - /* The WireGuard kernel module does not yet send link update - * notifications, so we don't actually update the cache. For - * now, always refetch link data here. */ - - _lookup_cached_link (cache, obj->link.ifindex, completed_from_cache, &link_cached); - if ( link_cached - && link_cached->_link.netlink.is_in_netlink - && link_cached->link.type == NM_LINK_TYPE_WIREGUARD) - obj->_link.wireguard_family_id = link_cached->_link.wireguard_family_id; - else - obj->_link.wireguard_family_id = -1; - - if (obj->_link.wireguard_family_id < 0) - obj->_link.wireguard_family_id = genl_ctrl_resolve (genl, "wireguard"); - - if (obj->_link.wireguard_family_id >= 0) { - lnk_data_new = _wireguard_read_info (platform, - genl, - obj->_link.wireguard_family_id, - obj->link.ifindex); - } - - if ( lnk_data_new - && obj->_link.netlink.lnk - && nmp_object_equal (obj->_link.netlink.lnk, lnk_data_new)) - nmp_object_unref (lnk_data_new); - else { - nmp_object_unref (obj->_link.netlink.lnk); - obj->_link.netlink.lnk = lnk_data_new; - } - } - - obj->_link.netlink.is_in_netlink = TRUE; - return g_steal_pointer (&obj); +_new_from_nl_link(NMPlatform * platform, + const NMPCache * cache, + struct nlmsghdr *nlh, + gboolean id_only) +{ + static const struct nla_policy policy[] = { + [IFLA_IFNAME] = {.type = NLA_STRING, .maxlen = IFNAMSIZ}, + [IFLA_MTU] = {.type = NLA_U32}, + [IFLA_TXQLEN] = {.type = NLA_U32}, + [IFLA_LINK] = {.type = NLA_U32}, + [IFLA_WEIGHT] = {.type = NLA_U32}, + [IFLA_MASTER] = {.type = NLA_U32}, + [IFLA_OPERSTATE] = {.type = NLA_U8}, + [IFLA_LINKMODE] = {.type = NLA_U8}, + [IFLA_LINKINFO] = {.type = NLA_NESTED}, + [IFLA_QDISC] = {.type = NLA_STRING, .maxlen = IFQDISCSIZ}, + [IFLA_STATS] = {.minlen = nm_offsetofend(struct rtnl_link_stats, tx_compressed)}, + [IFLA_STATS64] = {.minlen = nm_offsetofend(struct rtnl_link_stats64, tx_compressed)}, + [IFLA_MAP] = {.minlen = nm_offsetofend(struct rtnl_link_ifmap, port)}, + [IFLA_IFALIAS] = {.type = NLA_STRING, .maxlen = IFALIASZ}, + [IFLA_NUM_VF] = {.type = NLA_U32}, + [IFLA_AF_SPEC] = {.type = NLA_NESTED}, + [IFLA_PROMISCUITY] = {.type = NLA_U32}, + [IFLA_NUM_TX_QUEUES] = {.type = NLA_U32}, + [IFLA_NUM_RX_QUEUES] = {.type = NLA_U32}, + [IFLA_GROUP] = {.type = NLA_U32}, + [IFLA_CARRIER] = {.type = NLA_U8}, + [IFLA_PHYS_PORT_ID] = {.type = NLA_UNSPEC}, + [IFLA_NET_NS_PID] = {.type = NLA_U32}, + [IFLA_NET_NS_FD] = {.type = NLA_U32}, + [IFLA_LINK_NETNSID] = {}, + }; + const struct ifinfomsg *ifi; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + struct nlattr * nl_info_data = NULL; + const char * nl_info_kind = NULL; + nm_auto_nmpobj NMPObject *obj = NULL; + gboolean completed_from_cache_val = FALSE; + gboolean * completed_from_cache = cache ? &completed_from_cache_val : NULL; + const NMPObject * link_cached = NULL; + const NMPObject * lnk_data = NULL; + gboolean address_complete_from_cache = TRUE; + gboolean broadcast_complete_from_cache = TRUE; + gboolean lnk_data_complete_from_cache = TRUE; + gboolean need_ext_data = FALSE; + gboolean af_inet6_token_valid = FALSE; + gboolean af_inet6_addr_gen_mode_valid = FALSE; + + if (!nlmsg_valid_hdr(nlh, sizeof(*ifi))) + return NULL; + + ifi = nlmsg_data(nlh); + + if (ifi->ifi_family != AF_UNSPEC) + return NULL; + if (ifi->ifi_index <= 0) + return NULL; + + obj = nmp_object_new_link(ifi->ifi_index); + + if (id_only) + return g_steal_pointer(&obj); + + if (nlmsg_parse_arr(nlh, sizeof(*ifi), tb, policy) < 0) + return NULL; + + if (!tb[IFLA_IFNAME]) + return NULL; + nla_strlcpy(obj->link.name, tb[IFLA_IFNAME], IFNAMSIZ); + if (!obj->link.name[0]) + return NULL; + + if (!tb[IFLA_MTU]) { + /* Kernel has two places that send RTM_GETLINK messages: + * net/core/rtnetlink.c and net/wireless/ext-core.c. + * Unfortunately ext-core.c sets only IFLA_WIRELESS and + * IFLA_IFNAME. This confuses code in this function, because + * it cannot get complete set of data for the interface and + * later incomplete object this function creates is used to + * overwrite existing data in NM's cache. + * Since ext-core.c doesn't set IFLA_MTU we can use it as a + * signal to ignore incoming message. + * To some extent this is a hack and correct approach is to + * merge objects per-field. + */ + return NULL; + } + obj->link.mtu = nla_get_u32(tb[IFLA_MTU]); + + if (tb[IFLA_LINKINFO]) { + static const struct nla_policy policy_link_info[] = { + [IFLA_INFO_KIND] = {.type = NLA_STRING}, + [IFLA_INFO_DATA] = {.type = NLA_NESTED}, + [IFLA_INFO_XSTATS] = {.type = NLA_NESTED}, + }; + struct nlattr *li[G_N_ELEMENTS(policy_link_info)]; + + if (nla_parse_nested_arr(li, tb[IFLA_LINKINFO], policy_link_info) < 0) + return NULL; + + if (li[IFLA_INFO_KIND]) + nl_info_kind = nla_get_string(li[IFLA_INFO_KIND]); + + nl_info_data = li[IFLA_INFO_DATA]; + } + + if (tb[IFLA_STATS64]) { + const char *stats = nla_data(tb[IFLA_STATS64]); + + obj->link.rx_packets = + unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, rx_packets)]); + obj->link.rx_bytes = + unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, rx_bytes)]); + obj->link.tx_packets = + unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, tx_packets)]); + obj->link.tx_bytes = + unaligned_read_ne64(&stats[G_STRUCT_OFFSET(struct rtnl_link_stats64, tx_bytes)]); + } + + obj->link.n_ifi_flags = ifi->ifi_flags; + obj->link.connected = NM_FLAGS_HAS(obj->link.n_ifi_flags, IFF_LOWER_UP); + obj->link.arptype = ifi->ifi_type; + + obj->link.type = _linktype_get_type(platform, + cache, + nl_info_kind, + obj->link.ifindex, + obj->link.name, + obj->link.n_ifi_flags, + obj->link.arptype, + completed_from_cache, + &link_cached, + &obj->link.kind); + + if (tb[IFLA_MASTER]) + obj->link.master = nla_get_u32(tb[IFLA_MASTER]); + + if (tb[IFLA_LINK]) { + if (!tb[IFLA_LINK_NETNSID]) + obj->link.parent = nla_get_u32(tb[IFLA_LINK]); + else + obj->link.parent = NM_PLATFORM_LINK_OTHER_NETNS; + } + + if (tb[IFLA_ADDRESS]) { + _nmp_link_address_set(&obj->link.l_address, tb[IFLA_ADDRESS]); + address_complete_from_cache = FALSE; + } + + if (tb[IFLA_BROADCAST]) { + _nmp_link_address_set(&obj->link.l_broadcast, tb[IFLA_BROADCAST]); + broadcast_complete_from_cache = FALSE; + } + + if (tb[IFLA_AF_SPEC]) { + struct nlattr *af_attr; + int remaining; + + nla_for_each_nested (af_attr, tb[IFLA_AF_SPEC], remaining) { + switch (nla_type(af_attr)) { + case AF_INET6: + _parse_af_inet6(platform, + af_attr, + &obj->link.inet6_token, + &af_inet6_token_valid, + &obj->link.inet6_addr_gen_mode_inv, + &af_inet6_addr_gen_mode_valid); + break; + } + } + } + + switch (obj->link.type) { + case NM_LINK_TYPE_BRIDGE: + lnk_data = _parse_lnk_bridge(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_GRETAP: + lnk_data = _parse_lnk_gre(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_INFINIBAND: + lnk_data = _parse_lnk_infiniband(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_IP6TNL: + lnk_data = _parse_lnk_ip6tnl(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_IP6GRE: + case NM_LINK_TYPE_IP6GRETAP: + lnk_data = _parse_lnk_ip6gre(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_IPIP: + lnk_data = _parse_lnk_ipip(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_MACSEC: + lnk_data = _parse_lnk_macsec(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_MACVLAN: + case NM_LINK_TYPE_MACVTAP: + lnk_data = _parse_lnk_macvlan(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_SIT: + lnk_data = _parse_lnk_sit(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_TUN: + lnk_data = _parse_lnk_tun(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_VLAN: + lnk_data = _parse_lnk_vlan(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_VRF: + lnk_data = _parse_lnk_vrf(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_VXLAN: + lnk_data = _parse_lnk_vxlan(nl_info_kind, nl_info_data); + break; + case NM_LINK_TYPE_WIFI: + case NM_LINK_TYPE_OLPC_MESH: + case NM_LINK_TYPE_WPAN: + need_ext_data = TRUE; + lnk_data_complete_from_cache = FALSE; + break; + case NM_LINK_TYPE_WIREGUARD: + lnk_data_complete_from_cache = TRUE; + break; + default: + lnk_data_complete_from_cache = FALSE; + break; + } + + if (completed_from_cache + && (lnk_data_complete_from_cache || need_ext_data || address_complete_from_cache + || broadcast_complete_from_cache || !af_inet6_token_valid + || !af_inet6_addr_gen_mode_valid || !tb[IFLA_STATS64])) { + _lookup_cached_link(cache, obj->link.ifindex, completed_from_cache, &link_cached); + if (link_cached && link_cached->_link.netlink.is_in_netlink) { + if (lnk_data_complete_from_cache && link_cached->link.type == obj->link.type + && link_cached->_link.netlink.lnk + && (!lnk_data || nmp_object_equal(lnk_data, link_cached->_link.netlink.lnk))) { + /* We always try to look into the cache and reuse the object there. + * We do that, because we consider the lnk object as immutable and don't + * modify it after creating. Hence we can share it and reuse. + * + * Also, sometimes the info-data is missing for updates. In this case + * we want to keep the previously received lnk_data. */ + nmp_object_unref(lnk_data); + lnk_data = nmp_object_ref(link_cached->_link.netlink.lnk); + } + + if (need_ext_data && link_cached->link.type == obj->link.type + && link_cached->_link.ext_data) { + /* Prefer reuse of existing ext_data object */ + obj->_link.ext_data = g_object_ref(link_cached->_link.ext_data); + } + + if (address_complete_from_cache) + obj->link.l_address = link_cached->link.l_address; + if (broadcast_complete_from_cache) + obj->link.l_broadcast = link_cached->link.l_broadcast; + if (!af_inet6_token_valid) + obj->link.inet6_token = link_cached->link.inet6_token; + if (!af_inet6_addr_gen_mode_valid) + obj->link.inet6_addr_gen_mode_inv = link_cached->link.inet6_addr_gen_mode_inv; + if (!tb[IFLA_STATS64]) { + obj->link.rx_packets = link_cached->link.rx_packets; + obj->link.rx_bytes = link_cached->link.rx_bytes; + obj->link.tx_packets = link_cached->link.tx_packets; + obj->link.tx_bytes = link_cached->link.tx_bytes; + } + } + } + + obj->_link.netlink.lnk = lnk_data; + + if (need_ext_data && obj->_link.ext_data == NULL) { + switch (obj->link.type) { + case NM_LINK_TYPE_WIFI: + case NM_LINK_TYPE_OLPC_MESH: + obj->_link.ext_data = + (GObject *) nm_wifi_utils_new(ifi->ifi_index, + _genl_sock(NM_LINUX_PLATFORM(platform)), + TRUE); + break; + case NM_LINK_TYPE_WPAN: + obj->_link.ext_data = + (GObject *) nm_wpan_utils_new(ifi->ifi_index, + _genl_sock(NM_LINUX_PLATFORM(platform)), + TRUE); + break; + default: + g_assert_not_reached(); + } + } + + if (obj->link.type == NM_LINK_TYPE_WIREGUARD) { + const NMPObject *lnk_data_new = NULL; + struct nl_sock * genl = NM_LINUX_PLATFORM_GET_PRIVATE(platform)->genl; + + /* The WireGuard kernel module does not yet send link update + * notifications, so we don't actually update the cache. For + * now, always refetch link data here. */ + + _lookup_cached_link(cache, obj->link.ifindex, completed_from_cache, &link_cached); + if (link_cached && link_cached->_link.netlink.is_in_netlink + && link_cached->link.type == NM_LINK_TYPE_WIREGUARD) + obj->_link.wireguard_family_id = link_cached->_link.wireguard_family_id; + else + obj->_link.wireguard_family_id = -1; + + if (obj->_link.wireguard_family_id < 0) + obj->_link.wireguard_family_id = genl_ctrl_resolve(genl, "wireguard"); + + if (obj->_link.wireguard_family_id >= 0) { + lnk_data_new = _wireguard_read_info(platform, + genl, + obj->_link.wireguard_family_id, + obj->link.ifindex); + } + + if (lnk_data_new && obj->_link.netlink.lnk + && nmp_object_equal(obj->_link.netlink.lnk, lnk_data_new)) + nmp_object_unref(lnk_data_new); + else { + nmp_object_unref(obj->_link.netlink.lnk); + obj->_link.netlink.lnk = lnk_data_new; + } + } + + obj->_link.netlink.is_in_netlink = TRUE; + return g_steal_pointer(&obj); } /* Copied and heavily modified from libnl3's addr_msg_parser(). */ static NMPObject * -_new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [IFA_LABEL] = { .type = NLA_STRING, - .maxlen = IFNAMSIZ }, - [IFA_CACHEINFO] = { .minlen = nm_offsetofend (struct ifa_cacheinfo, tstamp) }, - [IFA_FLAGS] = { }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - const struct ifaddrmsg *ifa; - gboolean is_v4; - nm_auto_nmpobj NMPObject *obj = NULL; - int addr_len; - guint32 lifetime, preferred, timestamp; - - if (!nlmsg_valid_hdr (nlh, sizeof (*ifa))) - return NULL; - - ifa = nlmsg_data (nlh); - - if (!NM_IN_SET (ifa->ifa_family, AF_INET, AF_INET6)) - return NULL; - - is_v4 = ifa->ifa_family == AF_INET; - - if (nlmsg_parse_arr (nlh, sizeof (*ifa), tb, policy) < 0) - return NULL; - - addr_len = is_v4 - ? sizeof (in_addr_t) - : sizeof (struct in6_addr); - - if (ifa->ifa_prefixlen > (is_v4 ? 32 : 128)) - return NULL; - - /*****************************************************************/ - - obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, NULL); - - obj->ip_address.ifindex = ifa->ifa_index; - obj->ip_address.plen = ifa->ifa_prefixlen; - - _check_addr_or_return_null (tb, IFA_ADDRESS, addr_len); - _check_addr_or_return_null (tb, IFA_LOCAL, addr_len); - if (is_v4) { - /* For IPv4, kernel omits IFA_LOCAL/IFA_ADDRESS if (and only if) they - * are effectively 0.0.0.0 (all-zero). */ - if (tb[IFA_LOCAL]) - memcpy (&obj->ip4_address.address, nla_data (tb[IFA_LOCAL]), addr_len); - if (tb[IFA_ADDRESS]) - memcpy (&obj->ip4_address.peer_address, nla_data (tb[IFA_ADDRESS]), addr_len); - - _check_addr_or_return_null (tb, IFA_BROADCAST, addr_len); - obj->ip4_address.broadcast_address = tb[IFA_BROADCAST] - ? nla_get_u32 (tb[IFA_BROADCAST]) - : 0u; - obj->ip4_address.use_ip4_broadcast_address = TRUE; - } else { - /* For IPv6, IFA_ADDRESS is always present. - * - * If IFA_LOCAL is missing, IFA_ADDRESS is @address and @peer_address - * is :: (all-zero). - * - * If unexpectely IFA_ADDRESS is missing, make the best of it -- but it _should_ - * actually be there. */ - if (tb[IFA_ADDRESS] || tb[IFA_LOCAL]) { - if (tb[IFA_LOCAL]) { - memcpy (&obj->ip6_address.address, nla_data (tb[IFA_LOCAL]), addr_len); - if (tb[IFA_ADDRESS]) - memcpy (&obj->ip6_address.peer_address, nla_data (tb[IFA_ADDRESS]), addr_len); - else - obj->ip6_address.peer_address = obj->ip6_address.address; - } else - memcpy (&obj->ip6_address.address, nla_data (tb[IFA_ADDRESS]), addr_len); - } - } - - obj->ip_address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; - - obj->ip_address.n_ifa_flags = tb[IFA_FLAGS] - ? nla_get_u32 (tb[IFA_FLAGS]) - : ifa->ifa_flags; - - if (is_v4) { - if (tb[IFA_LABEL]) { - char label[IFNAMSIZ]; - - nla_strlcpy (label, tb[IFA_LABEL], IFNAMSIZ); - - /* Check for ':'; we're only interested in labels used as interface aliases */ - if (strchr (label, ':')) - g_strlcpy (obj->ip4_address.label, label, sizeof (obj->ip4_address.label)); - } - } - - lifetime = NM_PLATFORM_LIFETIME_PERMANENT; - preferred = NM_PLATFORM_LIFETIME_PERMANENT; - timestamp = 0; - /* IPv6 only */ - if (tb[IFA_CACHEINFO]) { - const struct ifa_cacheinfo *ca; - - ca = nla_data_as (struct ifa_cacheinfo, tb[IFA_CACHEINFO]); - lifetime = ca->ifa_valid; - preferred = ca->ifa_prefered; - timestamp = ca->tstamp; - } - _addrtime_get_lifetimes (timestamp, - lifetime, - preferred, - &obj->ip_address.timestamp, - &obj->ip_address.lifetime, - &obj->ip_address.preferred); - - return g_steal_pointer (&obj); +_new_from_nl_addr(struct nlmsghdr *nlh, gboolean id_only) +{ + static const struct nla_policy policy[] = { + [IFA_LABEL] = {.type = NLA_STRING, .maxlen = IFNAMSIZ}, + [IFA_CACHEINFO] = {.minlen = nm_offsetofend(struct ifa_cacheinfo, tstamp)}, + [IFA_FLAGS] = {}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + const struct ifaddrmsg *ifa; + gboolean is_v4; + nm_auto_nmpobj NMPObject *obj = NULL; + int addr_len; + guint32 lifetime, preferred, timestamp; + + if (!nlmsg_valid_hdr(nlh, sizeof(*ifa))) + return NULL; + + ifa = nlmsg_data(nlh); + + if (!NM_IN_SET(ifa->ifa_family, AF_INET, AF_INET6)) + return NULL; + + is_v4 = ifa->ifa_family == AF_INET; + + if (nlmsg_parse_arr(nlh, sizeof(*ifa), tb, policy) < 0) + return NULL; + + addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); + + if (ifa->ifa_prefixlen > (is_v4 ? 32 : 128)) + return NULL; + + /*****************************************************************/ + + obj = nmp_object_new(is_v4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, NULL); + + obj->ip_address.ifindex = ifa->ifa_index; + obj->ip_address.plen = ifa->ifa_prefixlen; + + _check_addr_or_return_null(tb, IFA_ADDRESS, addr_len); + _check_addr_or_return_null(tb, IFA_LOCAL, addr_len); + if (is_v4) { + /* For IPv4, kernel omits IFA_LOCAL/IFA_ADDRESS if (and only if) they + * are effectively 0.0.0.0 (all-zero). */ + if (tb[IFA_LOCAL]) + memcpy(&obj->ip4_address.address, nla_data(tb[IFA_LOCAL]), addr_len); + if (tb[IFA_ADDRESS]) + memcpy(&obj->ip4_address.peer_address, nla_data(tb[IFA_ADDRESS]), addr_len); + + _check_addr_or_return_null(tb, IFA_BROADCAST, addr_len); + obj->ip4_address.broadcast_address = + tb[IFA_BROADCAST] ? nla_get_u32(tb[IFA_BROADCAST]) : 0u; + obj->ip4_address.use_ip4_broadcast_address = TRUE; + } else { + /* For IPv6, IFA_ADDRESS is always present. + * + * If IFA_LOCAL is missing, IFA_ADDRESS is @address and @peer_address + * is :: (all-zero). + * + * If unexpectedly IFA_ADDRESS is missing, make the best of it -- but it _should_ + * actually be there. */ + if (tb[IFA_ADDRESS] || tb[IFA_LOCAL]) { + if (tb[IFA_LOCAL]) { + memcpy(&obj->ip6_address.address, nla_data(tb[IFA_LOCAL]), addr_len); + if (tb[IFA_ADDRESS]) + memcpy(&obj->ip6_address.peer_address, nla_data(tb[IFA_ADDRESS]), addr_len); + else + obj->ip6_address.peer_address = obj->ip6_address.address; + } else + memcpy(&obj->ip6_address.address, nla_data(tb[IFA_ADDRESS]), addr_len); + } + } + + obj->ip_address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; + + obj->ip_address.n_ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifa->ifa_flags; + + if (is_v4) { + if (tb[IFA_LABEL]) { + char label[IFNAMSIZ]; + + nla_strlcpy(label, tb[IFA_LABEL], IFNAMSIZ); + + /* Check for ':'; we're only interested in labels used as interface aliases */ + if (strchr(label, ':')) + g_strlcpy(obj->ip4_address.label, label, sizeof(obj->ip4_address.label)); + } + } + + lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + preferred = NM_PLATFORM_LIFETIME_PERMANENT; + timestamp = 0; + /* IPv6 only */ + if (tb[IFA_CACHEINFO]) { + const struct ifa_cacheinfo *ca; + + ca = nla_data_as(struct ifa_cacheinfo, tb[IFA_CACHEINFO]); + lifetime = ca->ifa_valid; + preferred = ca->ifa_prefered; + timestamp = ca->tstamp; + } + _addrtime_get_lifetimes(timestamp, + lifetime, + preferred, + &obj->ip_address.timestamp, + &obj->ip_address.lifetime, + &obj->ip_address.preferred); + + return g_steal_pointer(&obj); } /* Copied and heavily modified from libnl3's rtnl_route_parse() and parse_multipath(). */ static NMPObject * -_new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [RTA_TABLE] = { .type = NLA_U32 }, - [RTA_IIF] = { .type = NLA_U32 }, - [RTA_OIF] = { .type = NLA_U32 }, - [RTA_PRIORITY] = { .type = NLA_U32 }, - [RTA_PREF] = { .type = NLA_U8 }, - [RTA_FLOW] = { .type = NLA_U32 }, - [RTA_CACHEINFO] = { .minlen = nm_offsetofend (struct rta_cacheinfo, rta_tsage) }, - [RTA_METRICS] = { .type = NLA_NESTED }, - [RTA_MULTIPATH] = { .type = NLA_NESTED }, - }; - const struct rtmsg *rtm; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - gboolean is_v4; - nm_auto_nmpobj NMPObject *obj = NULL; - int addr_len; - struct { - gboolean is_present; - int ifindex; - NMIPAddr gateway; - } nh = { - .is_present = FALSE, - }; - guint32 mss; - guint32 window = 0; - guint32 cwnd = 0; - guint32 initcwnd = 0; - guint32 initrwnd = 0; - guint32 mtu = 0; - guint32 lock = 0; - - if (!nlmsg_valid_hdr (nlh, sizeof (*rtm))) - return NULL; - - rtm = nlmsg_data (nlh); - - /***************************************************************** - * only handle ~supported~ routes. - *****************************************************************/ - - if (!NM_IN_SET (rtm->rtm_family, AF_INET, AF_INET6)) - return NULL; - - if (!NM_IN_SET (rtm->rtm_type, - RTN_UNICAST, - RTN_LOCAL)) - return NULL; - - if (nlmsg_parse_arr (nlh, - sizeof (struct rtmsg), - tb, - policy) < 0) - return NULL; - - /*****************************************************************/ - - is_v4 = rtm->rtm_family == AF_INET; - addr_len = is_v4 - ? sizeof (in_addr_t) - : sizeof (struct in6_addr); - - if (rtm->rtm_dst_len > (is_v4 ? 32 : 128)) - return NULL; - - /***************************************************************** - * parse nexthops. Only handle routes with one nh. - *****************************************************************/ - - if (tb[RTA_MULTIPATH]) { - size_t tlen = nla_len (tb[RTA_MULTIPATH]); - struct rtnexthop *rtnh; - - if (tlen < sizeof (*rtnh)) - goto rta_multipath_done; - - rtnh = nla_data_as (struct rtnexthop, tb[RTA_MULTIPATH]); - - if (tlen < rtnh->rtnh_len) - goto rta_multipath_done; - - while (TRUE) { - - if (nh.is_present) { - /* we don't support multipath routes. */ - return NULL; - } - - nh.is_present = TRUE; - nh.ifindex = rtnh->rtnh_ifindex; - - if (rtnh->rtnh_len > sizeof (*rtnh)) { - struct nlattr *ntb[G_N_ELEMENTS (policy)]; - - if (nla_parse_arr (ntb, - (struct nlattr *) RTNH_DATA (rtnh), - rtnh->rtnh_len - sizeof (*rtnh), - policy) < 0) - return NULL; - - if (_check_addr_or_return_null (ntb, RTA_GATEWAY, addr_len)) - memcpy (&nh.gateway, nla_data (ntb[RTA_GATEWAY]), addr_len); - } - - if (tlen < RTNH_ALIGN (rtnh->rtnh_len) + sizeof (*rtnh)) - goto rta_multipath_done; - - tlen -= RTNH_ALIGN (rtnh->rtnh_len); - rtnh = RTNH_NEXT (rtnh); - } -rta_multipath_done: - ; - } - - if ( tb[RTA_OIF] - || tb[RTA_GATEWAY] - || tb[RTA_FLOW]) { - int ifindex = 0; - NMIPAddr gateway = { }; - - if (tb[RTA_OIF]) - ifindex = nla_get_u32 (tb[RTA_OIF]); - if (_check_addr_or_return_null (tb, RTA_GATEWAY, addr_len)) - memcpy (&gateway, nla_data (tb[RTA_GATEWAY]), addr_len); - - if (!nh.is_present) { - /* If no nexthops have been provided via RTA_MULTIPATH - * we add it as regular nexthop to maintain backwards - * compatibility */ - nh.ifindex = ifindex; - nh.gateway = gateway; - } else { - /* Kernel supports new style nexthop configuration, - * verify that it is a duplicate and ignore old-style nexthop. */ - if ( nh.ifindex != ifindex - || memcmp (&nh.gateway, &gateway, addr_len) != 0) - return NULL; - } - } else if (!nh.is_present) - return NULL; - - /*****************************************************************/ - - mss = 0; - if (tb[RTA_METRICS]) { - static const struct nla_policy rtax_policy[] = { - [RTAX_LOCK] = { .type = NLA_U32 }, - [RTAX_ADVMSS] = { .type = NLA_U32 }, - [RTAX_WINDOW] = { .type = NLA_U32 }, - [RTAX_CWND] = { .type = NLA_U32 }, - [RTAX_INITCWND] = { .type = NLA_U32 }, - [RTAX_INITRWND] = { .type = NLA_U32 }, - [RTAX_MTU] = { .type = NLA_U32 }, - }; - struct nlattr *mtb[G_N_ELEMENTS (rtax_policy)]; - - if (nla_parse_nested_arr (mtb, tb[RTA_METRICS], rtax_policy) < 0) - return NULL; - - if (mtb[RTAX_LOCK]) - lock = nla_get_u32 (mtb[RTAX_LOCK]); - if (mtb[RTAX_ADVMSS]) - mss = nla_get_u32 (mtb[RTAX_ADVMSS]); - if (mtb[RTAX_WINDOW]) - window = nla_get_u32 (mtb[RTAX_WINDOW]); - if (mtb[RTAX_CWND]) - cwnd = nla_get_u32 (mtb[RTAX_CWND]); - if (mtb[RTAX_INITCWND]) - initcwnd = nla_get_u32 (mtb[RTAX_INITCWND]); - if (mtb[RTAX_INITRWND]) - initrwnd = nla_get_u32 (mtb[RTAX_INITRWND]); - if (mtb[RTAX_MTU]) - mtu = nla_get_u32 (mtb[RTAX_MTU]); - } - - /*****************************************************************/ - - obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL); - - obj->ip_route.type_coerced = nm_platform_route_type_coerce (rtm->rtm_type); - obj->ip_route.table_coerced = nm_platform_route_table_coerce ( tb[RTA_TABLE] - ? nla_get_u32 (tb[RTA_TABLE]) - : (guint32) rtm->rtm_table); - - obj->ip_route.ifindex = nh.ifindex; - - if (_check_addr_or_return_null (tb, RTA_DST, addr_len)) - memcpy (obj->ip_route.network_ptr, nla_data (tb[RTA_DST]), addr_len); - - obj->ip_route.plen = rtm->rtm_dst_len; - - if (tb[RTA_PRIORITY]) - obj->ip_route.metric = nla_get_u32 (tb[RTA_PRIORITY]); - - if (is_v4) - obj->ip4_route.gateway = nh.gateway.addr4; - else - obj->ip6_route.gateway = nh.gateway.addr6; - - if (is_v4) - obj->ip4_route.scope_inv = nm_platform_route_scope_inv (rtm->rtm_scope); - - if (_check_addr_or_return_null (tb, RTA_PREFSRC, addr_len)) { - if (is_v4) - memcpy (&obj->ip4_route.pref_src, nla_data (tb[RTA_PREFSRC]), addr_len); - else - memcpy (&obj->ip6_route.pref_src, nla_data (tb[RTA_PREFSRC]), addr_len); - } - - if (is_v4) - obj->ip4_route.tos = rtm->rtm_tos; - else { - if (tb[RTA_SRC]) { - _check_addr_or_return_null (tb, RTA_SRC, addr_len); - memcpy (&obj->ip6_route.src, nla_data (tb[RTA_SRC]), addr_len); - } - obj->ip6_route.src_plen = rtm->rtm_src_len; - } - - obj->ip_route.mss = mss; - obj->ip_route.window = window; - obj->ip_route.cwnd = cwnd; - obj->ip_route.initcwnd = initcwnd; - obj->ip_route.initrwnd = initrwnd; - obj->ip_route.mtu = mtu; - obj->ip_route.lock_window = NM_FLAGS_HAS (lock, 1 << RTAX_WINDOW); - obj->ip_route.lock_cwnd = NM_FLAGS_HAS (lock, 1 << RTAX_CWND); - obj->ip_route.lock_initcwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITCWND); - obj->ip_route.lock_initrwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITRWND); - obj->ip_route.lock_mtu = NM_FLAGS_HAS (lock, 1 << RTAX_MTU); - - if (!is_v4) { - - if (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)) { - /* Detect support for RTA_PREF by inspecting the netlink message. - * RTA_PREF was added in kernel 4.1, dated 21 June, 2015. */ - _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF, - tb[RTA_PREF] ? 1 : -1); - } - - if (tb[RTA_PREF]) - obj->ip6_route.rt_pref = nla_get_u8 (tb[RTA_PREF]); - } - - obj->ip_route.r_rtm_flags = rtm->rtm_flags; - obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol); - - return g_steal_pointer (&obj); +_new_from_nl_route(struct nlmsghdr *nlh, gboolean id_only) +{ + static const struct nla_policy policy[] = { + [RTA_TABLE] = {.type = NLA_U32}, + [RTA_IIF] = {.type = NLA_U32}, + [RTA_OIF] = {.type = NLA_U32}, + [RTA_PRIORITY] = {.type = NLA_U32}, + [RTA_PREF] = {.type = NLA_U8}, + [RTA_FLOW] = {.type = NLA_U32}, + [RTA_CACHEINFO] = {.minlen = nm_offsetofend(struct rta_cacheinfo, rta_tsage)}, + [RTA_METRICS] = {.type = NLA_NESTED}, + [RTA_MULTIPATH] = {.type = NLA_NESTED}, + }; + const struct rtmsg *rtm; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + gboolean is_v4; + nm_auto_nmpobj NMPObject *obj = NULL; + int addr_len; + struct { + gboolean is_present; + int ifindex; + NMIPAddr gateway; + } nh = { + .is_present = FALSE, + }; + guint32 mss; + guint32 window = 0; + guint32 cwnd = 0; + guint32 initcwnd = 0; + guint32 initrwnd = 0; + guint32 mtu = 0; + guint32 lock = 0; + + if (!nlmsg_valid_hdr(nlh, sizeof(*rtm))) + return NULL; + + rtm = nlmsg_data(nlh); + + /***************************************************************** + * only handle ~supported~ routes. + *****************************************************************/ + + if (!NM_IN_SET(rtm->rtm_family, AF_INET, AF_INET6)) + return NULL; + + if (!NM_IN_SET(rtm->rtm_type, RTN_UNICAST, RTN_LOCAL)) + return NULL; + + if (nlmsg_parse_arr(nlh, sizeof(struct rtmsg), tb, policy) < 0) + return NULL; + + /*****************************************************************/ + + is_v4 = rtm->rtm_family == AF_INET; + addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); + + if (rtm->rtm_dst_len > (is_v4 ? 32 : 128)) + return NULL; + + /***************************************************************** + * parse nexthops. Only handle routes with one nh. + *****************************************************************/ + + if (tb[RTA_MULTIPATH]) { + size_t tlen = nla_len(tb[RTA_MULTIPATH]); + struct rtnexthop *rtnh; + + if (tlen < sizeof(*rtnh)) + goto rta_multipath_done; + + rtnh = nla_data_as(struct rtnexthop, tb[RTA_MULTIPATH]); + + if (tlen < rtnh->rtnh_len) + goto rta_multipath_done; + + while (TRUE) { + if (nh.is_present) { + /* we don't support multipath routes. */ + return NULL; + } + + nh.is_present = TRUE; + nh.ifindex = rtnh->rtnh_ifindex; + + if (rtnh->rtnh_len > sizeof(*rtnh)) { + struct nlattr *ntb[G_N_ELEMENTS(policy)]; + + if (nla_parse_arr(ntb, + (struct nlattr *) RTNH_DATA(rtnh), + rtnh->rtnh_len - sizeof(*rtnh), + policy) + < 0) + return NULL; + + if (_check_addr_or_return_null(ntb, RTA_GATEWAY, addr_len)) + memcpy(&nh.gateway, nla_data(ntb[RTA_GATEWAY]), addr_len); + } + + if (tlen < RTNH_ALIGN(rtnh->rtnh_len) + sizeof(*rtnh)) + goto rta_multipath_done; + + tlen -= RTNH_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } +rta_multipath_done:; + } + + if (tb[RTA_OIF] || tb[RTA_GATEWAY] || tb[RTA_FLOW]) { + int ifindex = 0; + NMIPAddr gateway = {}; + + if (tb[RTA_OIF]) + ifindex = nla_get_u32(tb[RTA_OIF]); + if (_check_addr_or_return_null(tb, RTA_GATEWAY, addr_len)) + memcpy(&gateway, nla_data(tb[RTA_GATEWAY]), addr_len); + + if (!nh.is_present) { + /* If no nexthops have been provided via RTA_MULTIPATH + * we add it as regular nexthop to maintain backwards + * compatibility */ + nh.ifindex = ifindex; + nh.gateway = gateway; + } else { + /* Kernel supports new style nexthop configuration, + * verify that it is a duplicate and ignore old-style nexthop. */ + if (nh.ifindex != ifindex || memcmp(&nh.gateway, &gateway, addr_len) != 0) + return NULL; + } + } else if (!nh.is_present) + return NULL; + + /*****************************************************************/ + + mss = 0; + if (tb[RTA_METRICS]) { + static const struct nla_policy rtax_policy[] = { + [RTAX_LOCK] = {.type = NLA_U32}, + [RTAX_ADVMSS] = {.type = NLA_U32}, + [RTAX_WINDOW] = {.type = NLA_U32}, + [RTAX_CWND] = {.type = NLA_U32}, + [RTAX_INITCWND] = {.type = NLA_U32}, + [RTAX_INITRWND] = {.type = NLA_U32}, + [RTAX_MTU] = {.type = NLA_U32}, + }; + struct nlattr *mtb[G_N_ELEMENTS(rtax_policy)]; + + if (nla_parse_nested_arr(mtb, tb[RTA_METRICS], rtax_policy) < 0) + return NULL; + + if (mtb[RTAX_LOCK]) + lock = nla_get_u32(mtb[RTAX_LOCK]); + if (mtb[RTAX_ADVMSS]) + mss = nla_get_u32(mtb[RTAX_ADVMSS]); + if (mtb[RTAX_WINDOW]) + window = nla_get_u32(mtb[RTAX_WINDOW]); + if (mtb[RTAX_CWND]) + cwnd = nla_get_u32(mtb[RTAX_CWND]); + if (mtb[RTAX_INITCWND]) + initcwnd = nla_get_u32(mtb[RTAX_INITCWND]); + if (mtb[RTAX_INITRWND]) + initrwnd = nla_get_u32(mtb[RTAX_INITRWND]); + if (mtb[RTAX_MTU]) + mtu = nla_get_u32(mtb[RTAX_MTU]); + } + + /*****************************************************************/ + + obj = nmp_object_new(is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL); + + obj->ip_route.type_coerced = nm_platform_route_type_coerce(rtm->rtm_type); + obj->ip_route.table_coerced = nm_platform_route_table_coerce( + tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : (guint32) rtm->rtm_table); + + obj->ip_route.ifindex = nh.ifindex; + + if (_check_addr_or_return_null(tb, RTA_DST, addr_len)) + memcpy(obj->ip_route.network_ptr, nla_data(tb[RTA_DST]), addr_len); + + obj->ip_route.plen = rtm->rtm_dst_len; + + if (tb[RTA_PRIORITY]) + obj->ip_route.metric = nla_get_u32(tb[RTA_PRIORITY]); + + if (is_v4) + obj->ip4_route.gateway = nh.gateway.addr4; + else + obj->ip6_route.gateway = nh.gateway.addr6; + + if (is_v4) + obj->ip4_route.scope_inv = nm_platform_route_scope_inv(rtm->rtm_scope); + + if (_check_addr_or_return_null(tb, RTA_PREFSRC, addr_len)) { + if (is_v4) + memcpy(&obj->ip4_route.pref_src, nla_data(tb[RTA_PREFSRC]), addr_len); + else + memcpy(&obj->ip6_route.pref_src, nla_data(tb[RTA_PREFSRC]), addr_len); + } + + if (is_v4) + obj->ip4_route.tos = rtm->rtm_tos; + else { + if (tb[RTA_SRC]) { + _check_addr_or_return_null(tb, RTA_SRC, addr_len); + memcpy(&obj->ip6_route.src, nla_data(tb[RTA_SRC]), addr_len); + } + obj->ip6_route.src_plen = rtm->rtm_src_len; + } + + obj->ip_route.mss = mss; + obj->ip_route.window = window; + obj->ip_route.cwnd = cwnd; + obj->ip_route.initcwnd = initcwnd; + obj->ip_route.initrwnd = initrwnd; + obj->ip_route.mtu = mtu; + obj->ip_route.lock_window = NM_FLAGS_HAS(lock, 1 << RTAX_WINDOW); + obj->ip_route.lock_cwnd = NM_FLAGS_HAS(lock, 1 << RTAX_CWND); + obj->ip_route.lock_initcwnd = NM_FLAGS_HAS(lock, 1 << RTAX_INITCWND); + obj->ip_route.lock_initrwnd = NM_FLAGS_HAS(lock, 1 << RTAX_INITRWND); + obj->ip_route.lock_mtu = NM_FLAGS_HAS(lock, 1 << RTAX_MTU); + + if (!is_v4) { + if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF)) { + /* Detect support for RTA_PREF by inspecting the netlink message. + * RTA_PREF was added in kernel 4.1, dated 21 June, 2015. */ + _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF, + tb[RTA_PREF] ? 1 : -1); + } + + if (tb[RTA_PREF]) + obj->ip6_route.rt_pref = nla_get_u8(tb[RTA_PREF]); + } + + obj->ip_route.r_rtm_flags = rtm->rtm_flags; + obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot(rtm->rtm_protocol); + + return g_steal_pointer(&obj); } static NMPObject * -_new_from_nl_routing_rule (struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [FRA_UNSPEC] = { }, - [FRA_DST] = { /* struct in_addr, struct in6_addr */ }, - [FRA_SRC] = { /* struct in_addr, struct in6_addr */ }, - [FRA_IIFNAME] = { .type = NLA_STRING, - .maxlen = IFNAMSIZ, }, - [FRA_GOTO] = { .type = NLA_U32, }, - [FRA_UNUSED2] = { }, - [FRA_PRIORITY] = { .type = NLA_U32, }, - [FRA_UNUSED3] = { }, - [FRA_UNUSED4] = { }, - [FRA_UNUSED5] = { }, - [FRA_FWMARK] = { .type = NLA_U32, }, - [FRA_FLOW] = { .type = NLA_U32, }, - [FRA_TUN_ID] = { .type = NLA_U64, }, - [FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32, }, - [FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32, }, - [FRA_TABLE] = { .type = NLA_U32, }, - [FRA_FWMASK] = { .type = NLA_U32, }, - [FRA_OIFNAME] = { .type = NLA_STRING, - .maxlen = IFNAMSIZ, }, - [FRA_PAD] = { .type = NLA_U32, }, - [FRA_L3MDEV] = { .type = NLA_U8, }, - [FRA_UID_RANGE] = { .minlen = sizeof(NMFibRuleUidRange), - .maxlen = sizeof(NMFibRuleUidRange), }, - [FRA_PROTOCOL] = { .type = NLA_U8, }, - [FRA_IP_PROTO] = { .type = NLA_U8, }, - [FRA_SPORT_RANGE] = { .minlen = sizeof(NMFibRulePortRange), - .maxlen = sizeof(NMFibRulePortRange), }, - [FRA_DPORT_RANGE] = { .minlen = sizeof(NMFibRulePortRange), - .maxlen = sizeof(NMFibRulePortRange), }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - const struct fib_rule_hdr *frh; - NMPlatformRoutingRule *props; - nm_auto_nmpobj NMPObject *obj = NULL; - int addr_family; - guint8 addr_size; - - if (nlmsg_parse_arr (nlh, sizeof (*frh), tb, policy) < 0) - return NULL; - - frh = nlmsg_data (nlh); - - addr_family = frh->family; - - if (!NM_IN_SET (addr_family, AF_INET, AF_INET6)) { - /* we don't care about other address families. */ - return NULL; - } - - addr_size = nm_utils_addr_family_to_size (addr_family); - - obj = nmp_object_new (NMP_OBJECT_TYPE_ROUTING_RULE, NULL); - props = &obj->routing_rule; - - props->addr_family = addr_family; - props->action = frh->action; - props->flags = frh->flags; - props->tos = frh->tos; - - props->table = tb[FRA_TABLE] - ? nla_get_u32 (tb[FRA_TABLE]) - : frh->table; - - if (tb[FRA_SUPPRESS_PREFIXLEN]) - props->suppress_prefixlen_inverse = ~nla_get_u32 (tb[FRA_SUPPRESS_PREFIXLEN]); - - if (tb[FRA_SUPPRESS_IFGROUP]) - props->suppress_ifgroup_inverse = ~nla_get_u32 (tb[FRA_SUPPRESS_IFGROUP]); - - if (tb[FRA_IIFNAME]) - nla_strlcpy (props->iifname, tb[FRA_IIFNAME], sizeof (props->iifname)); - - if (tb[FRA_OIFNAME]) - nla_strlcpy (props->oifname, tb[FRA_OIFNAME], sizeof (props->oifname)); - - if (tb[FRA_PRIORITY]) - props->priority = nla_get_u32 (tb[FRA_PRIORITY]); - - if (tb[FRA_FWMARK]) - props->fwmark = nla_get_u32 (tb[FRA_FWMARK]); - - if (tb[FRA_FWMASK]) - props->fwmask = nla_get_u32 (tb[FRA_FWMASK]); - - if (tb[FRA_GOTO]) - props->goto_target = nla_get_u32 (tb[FRA_GOTO]); - - props->src_len = frh->src_len; - if (props->src_len > addr_size * 8) - return NULL; - if (!tb[FRA_SRC]) { - if (props->src_len > 0) - return NULL; - } else if (!nm_ip_addr_set_from_untrusted (addr_family, - &props->src, - nla_data (tb[FRA_SRC]), - nla_len (tb[FRA_SRC]), - NULL)) - return NULL; - - props->dst_len = frh->dst_len; - if (props->dst_len > addr_size * 8) - return NULL; - if (!tb[FRA_DST]) { - if (props->dst_len > 0) - return NULL; - } else if (!nm_ip_addr_set_from_untrusted (addr_family, - &props->dst, - nla_data (tb[FRA_DST]), - nla_len (tb[FRA_DST]), - NULL)) - return NULL; - - if (tb[FRA_FLOW]) - props->flow = nla_get_u32 (tb[FRA_FLOW]); - - if (tb[FRA_TUN_ID]) - props->tun_id = nla_get_be64 (tb[FRA_TUN_ID]); - - if (tb[FRA_L3MDEV]) { - - if (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV)) { - /* support for FRA_L3MDEV was added in 96c63fa7393d0a346acfe5a91e0c7d4c7782641b, - * kernel 4.8, 3 October 2017. - * - * We can only detect support if the attribute is present. A missing attribute - * is not conclusive. */ - _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, 1); - } - - /* actually, kernel only allows this attribute to be missing or - * "1". Still, encode it as full uint8. - * - * Note that FRA_L3MDEV and FRA_TABLE are mutally exclusive. */ - props->l3mdev = nla_get_u8 (tb[FRA_L3MDEV]); - } - - if (tb[FRA_PROTOCOL]) - props->protocol = nla_get_u8 (tb[FRA_PROTOCOL]); - else - nm_assert (props->protocol == RTPROT_UNSPEC); - - if (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL)) { - /* FRA_PROTOCOL was added in kernel 4.17, dated 3 June, 2018. - * See commit 1b71af6053af1bd2f849e9fda4f71c1e3f145dcf. */ - _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL, - tb[FRA_PROTOCOL] ? 1 : -1); - } - - if (tb[FRA_IP_PROTO]) - props->ip_proto = nla_get_u8 (tb[FRA_IP_PROTO]); - - G_STATIC_ASSERT_EXPR (sizeof (NMFibRulePortRange) == 4); - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMFibRulePortRange, start) == 0); - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMFibRulePortRange, end) == 2); - - nla_memcpy_checked_size (&props->sport_range, tb[FRA_SPORT_RANGE], sizeof (props->sport_range)); - nla_memcpy_checked_size (&props->dport_range, tb[FRA_DPORT_RANGE], sizeof (props->dport_range)); - - if (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { - /* support for FRA_IP_PROTO, FRA_SPORT_RANGE, and FRA_DPORT_RANGE was added together - * by bfff4862653bb96001ab57c1edd6d03f48e5f035, kernel 4.17, 4 June 2018. - * - * Unfortunately, a missing attribute does not tell us anything about support. - * We can only tell for sure when we have support, but not when we don't have. */ - if ( tb[FRA_IP_PROTO] - || tb[FRA_SPORT_RANGE] - || tb[FRA_DPORT_RANGE]) - _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO, 1); - } - - G_STATIC_ASSERT_EXPR (sizeof (NMFibRuleUidRange) == 8); - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMFibRuleUidRange, start) == 0); - G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMFibRuleUidRange, end) == 4); - - if (tb[FRA_UID_RANGE]) { - - if (!_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { - /* support for FRA_UID_RANGE was added in 622ec2c9d52405973c9f1ca5116eb1c393adfc7d, - * kernel 4.10, 19 February 2017. - * - * We can only detect support if the attribute is present. A missing attribute - * is not conclusive. */ - _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, 1); - } - - nla_memcpy_checked_size (&props->uid_range, tb[FRA_UID_RANGE], sizeof (props->uid_range)); - props->uid_range_has = TRUE; - } - - return g_steal_pointer (&obj); +_new_from_nl_routing_rule(struct nlmsghdr *nlh, gboolean id_only) +{ + static const struct nla_policy policy[] = { + [FRA_UNSPEC] = {}, + [FRA_DST] = {/* struct in_addr, struct in6_addr */}, + [FRA_SRC] = {/* struct in_addr, struct in6_addr */}, + [FRA_IIFNAME] = + { + .type = NLA_STRING, + .maxlen = IFNAMSIZ, + }, + [FRA_GOTO] = + { + .type = NLA_U32, + }, + [FRA_UNUSED2] = {}, + [FRA_PRIORITY] = + { + .type = NLA_U32, + }, + [FRA_UNUSED3] = {}, + [FRA_UNUSED4] = {}, + [FRA_UNUSED5] = {}, + [FRA_FWMARK] = + { + .type = NLA_U32, + }, + [FRA_FLOW] = + { + .type = NLA_U32, + }, + [FRA_TUN_ID] = + { + .type = NLA_U64, + }, + [FRA_SUPPRESS_IFGROUP] = + { + .type = NLA_U32, + }, + [FRA_SUPPRESS_PREFIXLEN] = + { + .type = NLA_U32, + }, + [FRA_TABLE] = + { + .type = NLA_U32, + }, + [FRA_FWMASK] = + { + .type = NLA_U32, + }, + [FRA_OIFNAME] = + { + .type = NLA_STRING, + .maxlen = IFNAMSIZ, + }, + [FRA_PAD] = + { + .type = NLA_U32, + }, + [FRA_L3MDEV] = + { + .type = NLA_U8, + }, + [FRA_UID_RANGE] = + { + .minlen = sizeof(NMFibRuleUidRange), + .maxlen = sizeof(NMFibRuleUidRange), + }, + [FRA_PROTOCOL] = + { + .type = NLA_U8, + }, + [FRA_IP_PROTO] = + { + .type = NLA_U8, + }, + [FRA_SPORT_RANGE] = + { + .minlen = sizeof(NMFibRulePortRange), + .maxlen = sizeof(NMFibRulePortRange), + }, + [FRA_DPORT_RANGE] = + { + .minlen = sizeof(NMFibRulePortRange), + .maxlen = sizeof(NMFibRulePortRange), + }, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + const struct fib_rule_hdr *frh; + NMPlatformRoutingRule * props; + nm_auto_nmpobj NMPObject *obj = NULL; + int addr_family; + guint8 addr_size; + + if (nlmsg_parse_arr(nlh, sizeof(*frh), tb, policy) < 0) + return NULL; + + frh = nlmsg_data(nlh); + + addr_family = frh->family; + + if (!NM_IN_SET(addr_family, AF_INET, AF_INET6)) { + /* we don't care about other address families. */ + return NULL; + } + + addr_size = nm_utils_addr_family_to_size(addr_family); + + obj = nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, NULL); + props = &obj->routing_rule; + + props->addr_family = addr_family; + props->action = frh->action; + props->flags = frh->flags; + props->tos = frh->tos; + + props->table = tb[FRA_TABLE] ? nla_get_u32(tb[FRA_TABLE]) : frh->table; + + if (tb[FRA_SUPPRESS_PREFIXLEN]) + props->suppress_prefixlen_inverse = ~nla_get_u32(tb[FRA_SUPPRESS_PREFIXLEN]); + + if (tb[FRA_SUPPRESS_IFGROUP]) + props->suppress_ifgroup_inverse = ~nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]); + + if (tb[FRA_IIFNAME]) + nla_strlcpy(props->iifname, tb[FRA_IIFNAME], sizeof(props->iifname)); + + if (tb[FRA_OIFNAME]) + nla_strlcpy(props->oifname, tb[FRA_OIFNAME], sizeof(props->oifname)); + + if (tb[FRA_PRIORITY]) + props->priority = nla_get_u32(tb[FRA_PRIORITY]); + + if (tb[FRA_FWMARK]) + props->fwmark = nla_get_u32(tb[FRA_FWMARK]); + + if (tb[FRA_FWMASK]) + props->fwmask = nla_get_u32(tb[FRA_FWMASK]); + + if (tb[FRA_GOTO]) + props->goto_target = nla_get_u32(tb[FRA_GOTO]); + + props->src_len = frh->src_len; + if (props->src_len > addr_size * 8) + return NULL; + if (!tb[FRA_SRC]) { + if (props->src_len > 0) + return NULL; + } else if (!nm_ip_addr_set_from_untrusted(addr_family, + &props->src, + nla_data(tb[FRA_SRC]), + nla_len(tb[FRA_SRC]), + NULL)) + return NULL; + + props->dst_len = frh->dst_len; + if (props->dst_len > addr_size * 8) + return NULL; + if (!tb[FRA_DST]) { + if (props->dst_len > 0) + return NULL; + } else if (!nm_ip_addr_set_from_untrusted(addr_family, + &props->dst, + nla_data(tb[FRA_DST]), + nla_len(tb[FRA_DST]), + NULL)) + return NULL; + + if (tb[FRA_FLOW]) + props->flow = nla_get_u32(tb[FRA_FLOW]); + + if (tb[FRA_TUN_ID]) + props->tun_id = nla_get_be64(tb[FRA_TUN_ID]); + + if (tb[FRA_L3MDEV]) { + if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV)) { + /* support for FRA_L3MDEV was added in 96c63fa7393d0a346acfe5a91e0c7d4c7782641b, + * kernel 4.8, 3 October 2017. + * + * We can only detect support if the attribute is present. A missing attribute + * is not conclusive. */ + _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, 1); + } + + /* actually, kernel only allows this attribute to be missing or + * "1". Still, encode it as full uint8. + * + * Note that FRA_L3MDEV and FRA_TABLE are mutally exclusive. */ + props->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); + } + + if (tb[FRA_PROTOCOL]) + props->protocol = nla_get_u8(tb[FRA_PROTOCOL]); + else + nm_assert(props->protocol == RTPROT_UNSPEC); + + if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL)) { + /* FRA_PROTOCOL was added in kernel 4.17, dated 3 June, 2018. + * See commit 1b71af6053af1bd2f849e9fda4f71c1e3f145dcf. */ + _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL, + tb[FRA_PROTOCOL] ? 1 : -1); + } + + if (tb[FRA_IP_PROTO]) + props->ip_proto = nla_get_u8(tb[FRA_IP_PROTO]); + + G_STATIC_ASSERT_EXPR(sizeof(NMFibRulePortRange) == 4); + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRulePortRange, start) == 0); + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRulePortRange, end) == 2); + + nla_memcpy_checked_size(&props->sport_range, tb[FRA_SPORT_RANGE], sizeof(props->sport_range)); + nla_memcpy_checked_size(&props->dport_range, tb[FRA_DPORT_RANGE], sizeof(props->dport_range)); + + if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { + /* support for FRA_IP_PROTO, FRA_SPORT_RANGE, and FRA_DPORT_RANGE was added together + * by bfff4862653bb96001ab57c1edd6d03f48e5f035, kernel 4.17, 4 June 2018. + * + * Unfortunately, a missing attribute does not tell us anything about support. + * We can only tell for sure when we have support, but not when we don't have. */ + if (tb[FRA_IP_PROTO] || tb[FRA_SPORT_RANGE] || tb[FRA_DPORT_RANGE]) + _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO, 1); + } + + G_STATIC_ASSERT_EXPR(sizeof(NMFibRuleUidRange) == 8); + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRuleUidRange, start) == 0); + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMFibRuleUidRange, end) == 4); + + if (tb[FRA_UID_RANGE]) { + if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { + /* support for FRA_UID_RANGE was added in 622ec2c9d52405973c9f1ca5116eb1c393adfc7d, + * kernel 4.10, 19 February 2017. + * + * We can only detect support if the attribute is present. A missing attribute + * is not conclusive. */ + _nm_platform_kernel_support_init(NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, 1); + } + + nla_memcpy_checked_size(&props->uid_range, tb[FRA_UID_RANGE], sizeof(props->uid_range)); + props->uid_range_has = TRUE; + } + + return g_steal_pointer(&obj); } static guint32 -psched_tick_to_time (NMPlatform *platform, guint32 tick) +psched_tick_to_time(NMPlatform *platform, guint32 tick) { - static gboolean initialized; - static double tick_in_usec = 1; + static gboolean initialized; + static double tick_in_usec = 1; - if (!initialized) { - gs_free char *params = NULL; - double clock_factor = 1; - guint32 clock_res; - guint32 t2us; - guint32 us2t; + if (!initialized) { + gs_free char *params = NULL; + double clock_factor = 1; + guint32 clock_res; + guint32 t2us; + guint32 us2t; - initialized = TRUE; - params = nm_platform_sysctl_get (platform, NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/net/psched")); - if ( !params - || sscanf (params, "%08x%08x%08x", &t2us, &us2t, &clock_res) != 3) { - _LOGW ("packet scheduler parameters not available"); - } else { - /* See tc_core_init() in iproute2 */ - if (clock_res == 1000000000) - t2us = us2t; + initialized = TRUE; + params = nm_platform_sysctl_get(platform, NMP_SYSCTL_PATHID_ABSOLUTE("/proc/net/psched")); + if (!params || sscanf(params, "%08x%08x%08x", &t2us, &us2t, &clock_res) != 3) { + _LOGW("packet scheduler parameters not available"); + } else { + /* See tc_core_init() in iproute2 */ + if (clock_res == 1000000000) + t2us = us2t; - clock_factor = (double) clock_res / PSCHED_TIME_UNITS_PER_SEC; - tick_in_usec = (double) t2us / us2t * clock_factor; - } - } + clock_factor = (double) clock_res / PSCHED_TIME_UNITS_PER_SEC; + tick_in_usec = (double) t2us / us2t * clock_factor; + } + } - return tick / tick_in_usec; + return tick / tick_in_usec; } static NMPObject * -_new_from_nl_qdisc (NMPlatform *platform, struct nlmsghdr *nlh, gboolean id_only) -{ - static const struct nla_policy policy[] = { - [TCA_KIND] = { .type = NLA_STRING }, - [TCA_OPTIONS] = { .type = NLA_NESTED }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - const struct tcmsg *tcm; - nm_auto_nmpobj NMPObject *obj = NULL; - - if (nlmsg_parse_arr (nlh, - sizeof (*tcm), - tb, - policy) < 0) - return NULL; - - if (!tb[TCA_KIND]) - return NULL; - - tcm = nlmsg_data (nlh); - - obj = nmp_object_new (NMP_OBJECT_TYPE_QDISC, NULL); - - obj->qdisc.kind = g_intern_string (nla_get_string (tb[TCA_KIND])); - obj->qdisc.ifindex = tcm->tcm_ifindex; - obj->qdisc.addr_family = tcm->tcm_family; - obj->qdisc.handle = tcm->tcm_handle; - obj->qdisc.parent = tcm->tcm_parent; - obj->qdisc.info = tcm->tcm_info; - - if (nm_streq0 (obj->qdisc.kind, "fq_codel")) { - obj->qdisc.fq_codel.memory_limit = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET; - obj->qdisc.fq_codel.ce_threshold = NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED; - } - - if (tb[TCA_OPTIONS]) { - struct nlattr *options_attr; - int remaining; - - if (nm_streq0 (obj->qdisc.kind, "sfq")) { - struct tc_sfq_qopt_v1 opt; - - if (tb[TCA_OPTIONS]->nla_len >= nla_attr_size (sizeof (opt))) { - memcpy (&opt, nla_data (tb[TCA_OPTIONS]), sizeof (opt)); - obj->qdisc.sfq.quantum = opt.v0.quantum; - obj->qdisc.sfq.perturb_period = opt.v0.perturb_period; - obj->qdisc.sfq.limit = opt.v0.limit; - obj->qdisc.sfq.divisor = opt.v0.divisor; - obj->qdisc.sfq.flows = opt.v0.flows; - obj->qdisc.sfq.depth = opt.depth; - } - } else if (nm_streq0 (obj->qdisc.kind, "tbf")) { - static const struct nla_policy tbf_policy[] = { - [TCA_TBF_PARMS] = { .minlen = sizeof (struct tc_tbf_qopt) }, - [TCA_TBF_RATE64] = { .type = NLA_U64 }, - }; - struct nlattr *tbf_tb[G_N_ELEMENTS (tbf_policy)]; - struct tc_tbf_qopt opt; - - if (nla_parse_nested_arr (tbf_tb, tb[TCA_OPTIONS], tbf_policy) < 0) - return NULL; - if (!tbf_tb[TCA_TBF_PARMS]) - return NULL; - - nla_memcpy_checked_size (&opt, tbf_tb[TCA_TBF_PARMS], sizeof (opt)); - obj->qdisc.tbf.rate = opt.rate.rate; - if (tbf_tb[TCA_TBF_RATE64]) - obj->qdisc.tbf.rate = nla_get_u64 (tbf_tb[TCA_TBF_RATE64]); - obj->qdisc.tbf.burst = ((double) obj->qdisc.tbf.rate * - psched_tick_to_time (platform, opt.buffer)) / - PSCHED_TIME_UNITS_PER_SEC; - obj->qdisc.tbf.limit = opt.limit; - } else { - nla_for_each_nested (options_attr, tb[TCA_OPTIONS], remaining) { - if (nla_len (options_attr) < sizeof (uint32_t)) - continue; - - if (nm_streq0 (obj->qdisc.kind, "fq_codel")) { - switch (nla_type (options_attr)) { - case TCA_FQ_CODEL_LIMIT: - obj->qdisc.fq_codel.limit = nla_get_u32 (options_attr); - break; - case TCA_FQ_CODEL_FLOWS: - obj->qdisc.fq_codel.flows = nla_get_u32 (options_attr); - break; - case TCA_FQ_CODEL_TARGET: - obj->qdisc.fq_codel.target = nla_get_u32 (options_attr); - break; - case TCA_FQ_CODEL_INTERVAL: - obj->qdisc.fq_codel.interval = nla_get_u32 (options_attr); - break; - case TCA_FQ_CODEL_QUANTUM: - obj->qdisc.fq_codel.quantum = nla_get_u32 (options_attr); - break; - case TCA_FQ_CODEL_CE_THRESHOLD: - obj->qdisc.fq_codel.ce_threshold = nla_get_u32 (options_attr); - break; - case TCA_FQ_CODEL_MEMORY_LIMIT: - obj->qdisc.fq_codel.memory_limit = nla_get_u32 (options_attr); - break; - case TCA_FQ_CODEL_ECN: - obj->qdisc.fq_codel.ecn = !!nla_get_u32 (options_attr); - break; - } - } - } - } - } - - return g_steal_pointer (&obj); +_new_from_nl_qdisc(NMPlatform *platform, struct nlmsghdr *nlh, gboolean id_only) +{ + static const struct nla_policy policy[] = { + [TCA_KIND] = {.type = NLA_STRING}, + [TCA_OPTIONS] = {.type = NLA_NESTED}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + const struct tcmsg *tcm; + nm_auto_nmpobj NMPObject *obj = NULL; + + if (nlmsg_parse_arr(nlh, sizeof(*tcm), tb, policy) < 0) + return NULL; + + if (!tb[TCA_KIND]) + return NULL; + + tcm = nlmsg_data(nlh); + + obj = nmp_object_new(NMP_OBJECT_TYPE_QDISC, NULL); + + obj->qdisc.kind = g_intern_string(nla_get_string(tb[TCA_KIND])); + obj->qdisc.ifindex = tcm->tcm_ifindex; + obj->qdisc.addr_family = tcm->tcm_family; + obj->qdisc.handle = tcm->tcm_handle; + obj->qdisc.parent = tcm->tcm_parent; + obj->qdisc.info = tcm->tcm_info; + + if (nm_streq0(obj->qdisc.kind, "fq_codel")) { + obj->qdisc.fq_codel.memory_limit = NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET; + obj->qdisc.fq_codel.ce_threshold = NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED; + } + + if (tb[TCA_OPTIONS]) { + struct nlattr *options_attr; + int remaining; + + if (nm_streq0(obj->qdisc.kind, "sfq")) { + struct tc_sfq_qopt_v1 opt; + + if (tb[TCA_OPTIONS]->nla_len >= nla_attr_size(sizeof(opt))) { + memcpy(&opt, nla_data(tb[TCA_OPTIONS]), sizeof(opt)); + obj->qdisc.sfq.quantum = opt.v0.quantum; + obj->qdisc.sfq.perturb_period = opt.v0.perturb_period; + obj->qdisc.sfq.limit = opt.v0.limit; + obj->qdisc.sfq.divisor = opt.v0.divisor; + obj->qdisc.sfq.flows = opt.v0.flows; + obj->qdisc.sfq.depth = opt.depth; + } + } else if (nm_streq0(obj->qdisc.kind, "tbf")) { + static const struct nla_policy tbf_policy[] = { + [TCA_TBF_PARMS] = {.minlen = sizeof(struct tc_tbf_qopt)}, + [TCA_TBF_RATE64] = {.type = NLA_U64}, + }; + struct nlattr * tbf_tb[G_N_ELEMENTS(tbf_policy)]; + struct tc_tbf_qopt opt; + + if (nla_parse_nested_arr(tbf_tb, tb[TCA_OPTIONS], tbf_policy) < 0) + return NULL; + if (!tbf_tb[TCA_TBF_PARMS]) + return NULL; + + nla_memcpy_checked_size(&opt, tbf_tb[TCA_TBF_PARMS], sizeof(opt)); + obj->qdisc.tbf.rate = opt.rate.rate; + if (tbf_tb[TCA_TBF_RATE64]) + obj->qdisc.tbf.rate = nla_get_u64(tbf_tb[TCA_TBF_RATE64]); + obj->qdisc.tbf.burst = + ((double) obj->qdisc.tbf.rate * psched_tick_to_time(platform, opt.buffer)) + / PSCHED_TIME_UNITS_PER_SEC; + obj->qdisc.tbf.limit = opt.limit; + } else { + nla_for_each_nested (options_attr, tb[TCA_OPTIONS], remaining) { + if (nla_len(options_attr) < sizeof(uint32_t)) + continue; + + if (nm_streq0(obj->qdisc.kind, "fq_codel")) { + switch (nla_type(options_attr)) { + case TCA_FQ_CODEL_LIMIT: + obj->qdisc.fq_codel.limit = nla_get_u32(options_attr); + break; + case TCA_FQ_CODEL_FLOWS: + obj->qdisc.fq_codel.flows = nla_get_u32(options_attr); + break; + case TCA_FQ_CODEL_TARGET: + obj->qdisc.fq_codel.target = nla_get_u32(options_attr); + break; + case TCA_FQ_CODEL_INTERVAL: + obj->qdisc.fq_codel.interval = nla_get_u32(options_attr); + break; + case TCA_FQ_CODEL_QUANTUM: + obj->qdisc.fq_codel.quantum = nla_get_u32(options_attr); + break; + case TCA_FQ_CODEL_CE_THRESHOLD: + obj->qdisc.fq_codel.ce_threshold = nla_get_u32(options_attr); + break; + case TCA_FQ_CODEL_MEMORY_LIMIT: + obj->qdisc.fq_codel.memory_limit = nla_get_u32(options_attr); + break; + case TCA_FQ_CODEL_ECN: + obj->qdisc.fq_codel.ecn = !!nla_get_u32(options_attr); + break; + } + } + } + } + } + + return g_steal_pointer(&obj); } static NMPObject * -_new_from_nl_tfilter (struct nlmsghdr *nlh, gboolean id_only) +_new_from_nl_tfilter(struct nlmsghdr *nlh, gboolean id_only) { - static const struct nla_policy policy[] = { - [TCA_KIND] = { .type = NLA_STRING }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - NMPObject *obj = NULL; - const struct tcmsg *tcm; + static const struct nla_policy policy[] = { + [TCA_KIND] = {.type = NLA_STRING}, + }; + struct nlattr * tb[G_N_ELEMENTS(policy)]; + NMPObject * obj = NULL; + const struct tcmsg *tcm; - if (nlmsg_parse_arr (nlh, sizeof (*tcm), tb, policy) < 0) - return NULL; + if (nlmsg_parse_arr(nlh, sizeof(*tcm), tb, policy) < 0) + return NULL; - if (!tb[TCA_KIND]) - return NULL; + if (!tb[TCA_KIND]) + return NULL; - tcm = nlmsg_data (nlh); + tcm = nlmsg_data(nlh); - obj = nmp_object_new (NMP_OBJECT_TYPE_TFILTER, NULL); + obj = nmp_object_new(NMP_OBJECT_TYPE_TFILTER, NULL); - obj->tfilter.kind = g_intern_string (nla_get_string (tb[TCA_KIND])); - obj->tfilter.ifindex = tcm->tcm_ifindex; - obj->tfilter.addr_family = tcm->tcm_family; - obj->tfilter.handle = tcm->tcm_handle; - obj->tfilter.parent = tcm->tcm_parent; - obj->tfilter.info = tcm->tcm_info; + obj->tfilter.kind = g_intern_string(nla_get_string(tb[TCA_KIND])); + obj->tfilter.ifindex = tcm->tcm_ifindex; + obj->tfilter.addr_family = tcm->tcm_family; + obj->tfilter.handle = tcm->tcm_handle; + obj->tfilter.parent = tcm->tcm_parent; + obj->tfilter.info = tcm->tcm_info; - return obj; + return obj; } /** @@ -3854,1057 +4003,1085 @@ _new_from_nl_tfilter (struct nlmsghdr *nlh, gboolean id_only) * Returns: %NULL or a newly created NMPObject instance. **/ static NMPObject * -nmp_object_new_from_nl (NMPlatform *platform, const NMPCache *cache, struct nl_msg *msg, gboolean id_only) -{ - struct nlmsghdr *msghdr; - - if (nlmsg_get_proto (msg) != NETLINK_ROUTE) - return NULL; - - msghdr = nlmsg_hdr (msg); - - switch (msghdr->nlmsg_type) { - case RTM_NEWLINK: - case RTM_DELLINK: - case RTM_GETLINK: - case RTM_SETLINK: - return _new_from_nl_link (platform, cache, msghdr, id_only); - case RTM_NEWADDR: - case RTM_DELADDR: - case RTM_GETADDR: - return _new_from_nl_addr (msghdr, id_only); - case RTM_NEWROUTE: - case RTM_DELROUTE: - case RTM_GETROUTE: - return _new_from_nl_route (msghdr, id_only); - case RTM_NEWRULE: - case RTM_DELRULE: - case RTM_GETRULE: - return _new_from_nl_routing_rule (msghdr, id_only); - case RTM_NEWQDISC: - case RTM_DELQDISC: - case RTM_GETQDISC: - return _new_from_nl_qdisc (platform, msghdr, id_only); - case RTM_NEWTFILTER: - case RTM_DELTFILTER: - case RTM_GETTFILTER: - return _new_from_nl_tfilter (msghdr, id_only); - default: - return NULL; - } +nmp_object_new_from_nl(NMPlatform * platform, + const NMPCache *cache, + struct nl_msg * msg, + gboolean id_only) +{ + struct nlmsghdr *msghdr; + + if (nlmsg_get_proto(msg) != NETLINK_ROUTE) + return NULL; + + msghdr = nlmsg_hdr(msg); + + switch (msghdr->nlmsg_type) { + case RTM_NEWLINK: + case RTM_DELLINK: + case RTM_GETLINK: + case RTM_SETLINK: + return _new_from_nl_link(platform, cache, msghdr, id_only); + case RTM_NEWADDR: + case RTM_DELADDR: + case RTM_GETADDR: + return _new_from_nl_addr(msghdr, id_only); + case RTM_NEWROUTE: + case RTM_DELROUTE: + case RTM_GETROUTE: + return _new_from_nl_route(msghdr, id_only); + case RTM_NEWRULE: + case RTM_DELRULE: + case RTM_GETRULE: + return _new_from_nl_routing_rule(msghdr, id_only); + case RTM_NEWQDISC: + case RTM_DELQDISC: + case RTM_GETQDISC: + return _new_from_nl_qdisc(platform, msghdr, id_only); + case RTM_NEWTFILTER: + case RTM_DELTFILTER: + case RTM_GETTFILTER: + return _new_from_nl_tfilter(msghdr, id_only); + default: + return NULL; + } } /*****************************************************************************/ static gboolean -_nl_msg_new_link_set_afspec (struct nl_msg *msg, - int addr_gen_mode, - NMUtilsIPv6IfaceId *iid) +_nl_msg_new_link_set_afspec(struct nl_msg *msg, int addr_gen_mode, NMUtilsIPv6IfaceId *iid) { - struct nlattr *af_spec; - struct nlattr *af_attr; + struct nlattr *af_spec; + struct nlattr *af_attr; - nm_assert (msg); + nm_assert(msg); - if (!(af_spec = nla_nest_start (msg, IFLA_AF_SPEC))) - goto nla_put_failure; + if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC))) + goto nla_put_failure; - if (addr_gen_mode >= 0 || iid) { - if (!(af_attr = nla_nest_start (msg, AF_INET6))) - goto nla_put_failure; + if (addr_gen_mode >= 0 || iid) { + if (!(af_attr = nla_nest_start(msg, AF_INET6))) + goto nla_put_failure; - if (addr_gen_mode >= 0) - NLA_PUT_U8 (msg, IFLA_INET6_ADDR_GEN_MODE, addr_gen_mode); + if (addr_gen_mode >= 0) + NLA_PUT_U8(msg, IFLA_INET6_ADDR_GEN_MODE, addr_gen_mode); - if (iid) { - struct in6_addr i6_token = { .s6_addr = { 0, } }; + if (iid) { + struct in6_addr i6_token = {.s6_addr = { + 0, + }}; - nm_utils_ipv6_addr_set_interface_identifier (&i6_token, *iid); - NLA_PUT (msg, IFLA_INET6_TOKEN, sizeof (struct in6_addr), &i6_token); - } + nm_utils_ipv6_addr_set_interface_identifier(&i6_token, *iid); + NLA_PUT(msg, IFLA_INET6_TOKEN, sizeof(struct in6_addr), &i6_token); + } - nla_nest_end (msg, af_attr); - } + nla_nest_end(msg, af_attr); + } - nla_nest_end (msg, af_spec); + nla_nest_end(msg, af_spec); - return TRUE; + return TRUE; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static gboolean -_nl_msg_new_link_set_linkinfo (struct nl_msg *msg, - NMLinkType link_type, - gconstpointer extra_data) -{ - struct nlattr *info; - struct nlattr *data = NULL; - const char *kind; - - nm_assert (msg); - - kind = nm_link_type_to_rtnl_type_string (link_type); - if (!kind) - goto nla_put_failure; - - if (!(info = nla_nest_start (msg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (msg, IFLA_INFO_KIND, kind); - - switch (link_type) { - case NM_LINK_TYPE_VLAN: { - const NMPlatformLnkVlan *props = extra_data; - - nm_assert (extra_data); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U16 (msg, IFLA_VLAN_ID, props->id); - - { - struct ifla_vlan_flags flags = { - .flags = props->flags & NM_VLAN_FLAGS_ALL, - .mask = NM_VLAN_FLAGS_ALL, - }; - - NLA_PUT (msg, IFLA_VLAN_FLAGS, sizeof (flags), &flags); - } - break; - } - case NM_LINK_TYPE_VRF: { - const NMPlatformLnkVrf *props = extra_data; - - nm_assert (extra_data); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32 (msg, IFLA_VRF_TABLE, props->table); - break; - } - case NM_LINK_TYPE_VXLAN: { - const NMPlatformLnkVxlan *props = extra_data; - - nm_assert (extra_data); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32 (msg, IFLA_VXLAN_ID, props->id); - - if (props->group) - NLA_PUT (msg, IFLA_VXLAN_GROUP, sizeof (props->group), &props->group); - else if (!IN6_IS_ADDR_UNSPECIFIED (&props->group6)) - NLA_PUT (msg, IFLA_VXLAN_GROUP6, sizeof (props->group6), &props->group6); - - if (props->local) - NLA_PUT (msg, IFLA_VXLAN_LOCAL, sizeof (props->local), &props->local); - else if (!IN6_IS_ADDR_UNSPECIFIED (&props->local6)) - NLA_PUT (msg, IFLA_VXLAN_LOCAL6, sizeof (props->local6), &props->local6); - - if (props->parent_ifindex >= 0) - NLA_PUT_U32 (msg, IFLA_VXLAN_LINK, props->parent_ifindex); - - if ( props->src_port_min - || props->src_port_max) { - struct nm_ifla_vxlan_port_range port_range = { - .low = htons (props->src_port_min), - .high = htons (props->src_port_max), - }; - - NLA_PUT (msg, IFLA_VXLAN_PORT_RANGE, sizeof (port_range), &port_range); - } - - NLA_PUT_U16 (msg, IFLA_VXLAN_PORT, htons (props->dst_port)); - NLA_PUT_U8 (msg, IFLA_VXLAN_TOS, props->tos); - NLA_PUT_U8 (msg, IFLA_VXLAN_TTL, props->ttl); - NLA_PUT_U32 (msg, IFLA_VXLAN_AGEING, props->ageing); - NLA_PUT_U32 (msg, IFLA_VXLAN_LIMIT, props->limit); - NLA_PUT_U8 (msg, IFLA_VXLAN_LEARNING, !!props->learning); - NLA_PUT_U8 (msg, IFLA_VXLAN_PROXY, !!props->proxy); - NLA_PUT_U8 (msg, IFLA_VXLAN_RSC, !!props->rsc); - NLA_PUT_U8 (msg, IFLA_VXLAN_L2MISS, !!props->l2miss); - NLA_PUT_U8 (msg, IFLA_VXLAN_L3MISS, !!props->l3miss); - break; - } - case NM_LINK_TYPE_VETH: { - const char *veth_peer = extra_data; - const struct ifinfomsg ifi = { }; - struct nlattr *info_peer; - - nm_assert (veth_peer); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - if (!(info_peer = nla_nest_start (msg, 1 /*VETH_INFO_PEER*/))) - goto nla_put_failure; - if (nlmsg_append_struct (msg, &ifi) < 0) - goto nla_put_failure; - NLA_PUT_STRING (msg, IFLA_IFNAME, veth_peer); - nla_nest_end (msg, info_peer); - break; - } - case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: { - const NMPlatformLnkGre *props = extra_data; - - nm_assert (props); - nm_assert (props->is_tap == (link_type == NM_LINK_TYPE_GRETAP)); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (msg, IFLA_GRE_LINK, props->parent_ifindex); - NLA_PUT_U32 (msg, IFLA_GRE_LOCAL, props->local); - NLA_PUT_U32 (msg, IFLA_GRE_REMOTE, props->remote); - NLA_PUT_U8 (msg, IFLA_GRE_TTL, props->ttl); - NLA_PUT_U8 (msg, IFLA_GRE_TOS, props->tos); - NLA_PUT_U8 (msg, IFLA_GRE_PMTUDISC, !!props->path_mtu_discovery); - NLA_PUT_U32 (msg, IFLA_GRE_IKEY, htonl (props->input_key)); - NLA_PUT_U32 (msg, IFLA_GRE_OKEY, htonl (props->output_key)); - NLA_PUT_U16 (msg, IFLA_GRE_IFLAGS, htons (props->input_flags)); - NLA_PUT_U16 (msg, IFLA_GRE_OFLAGS, htons (props->output_flags)); - break; - } - case NM_LINK_TYPE_SIT: { - const NMPlatformLnkSit *props = extra_data; - - nm_assert (props); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (msg, IFLA_IPTUN_LINK, props->parent_ifindex); - NLA_PUT_U32 (msg, IFLA_IPTUN_LOCAL, props->local); - NLA_PUT_U32 (msg, IFLA_IPTUN_REMOTE, props->remote); - NLA_PUT_U8 (msg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8 (msg, IFLA_IPTUN_TOS, props->tos); - NLA_PUT_U8 (msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); - break; - } - case NM_LINK_TYPE_IP6TNL: { - const NMPlatformLnkIp6Tnl *props = extra_data; - guint32 flowinfo; - - nm_assert (props); - nm_assert (!props->is_gre); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (msg, IFLA_IPTUN_LINK, props->parent_ifindex); - - if (!IN6_IS_ADDR_UNSPECIFIED (&props->local)) - NLA_PUT (msg, IFLA_IPTUN_LOCAL, sizeof (props->local), &props->local); - if (!IN6_IS_ADDR_UNSPECIFIED (&props->remote)) - NLA_PUT (msg, IFLA_IPTUN_REMOTE, sizeof (props->remote), &props->remote); - - NLA_PUT_U8 (msg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8 (msg, IFLA_IPTUN_ENCAP_LIMIT, props->encap_limit); - - flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; - flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) - & IP6_FLOWINFO_TCLASS_MASK; - NLA_PUT_U32 (msg, IFLA_IPTUN_FLOWINFO, htonl (flowinfo)); - NLA_PUT_U8 (msg, IFLA_IPTUN_PROTO, props->proto); - NLA_PUT_U32 (msg, IFLA_IPTUN_FLAGS, props->flags); - break; - } - case NM_LINK_TYPE_IP6GRE: - case NM_LINK_TYPE_IP6GRETAP: { - const NMPlatformLnkIp6Tnl *props = extra_data; - guint32 flowinfo; - - nm_assert (props); - nm_assert (props->is_gre); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (msg, IFLA_GRE_LINK, props->parent_ifindex); - - NLA_PUT_U32 (msg, IFLA_GRE_IKEY, htonl (props->input_key)); - NLA_PUT_U32 (msg, IFLA_GRE_OKEY, htonl (props->output_key)); - NLA_PUT_U16 (msg, IFLA_GRE_IFLAGS, htons (props->input_flags)); - NLA_PUT_U16 (msg, IFLA_GRE_OFLAGS, htons (props->output_flags)); - - if (!IN6_IS_ADDR_UNSPECIFIED (&props->local)) - NLA_PUT (msg, IFLA_GRE_LOCAL, sizeof (props->local), &props->local); - if (!IN6_IS_ADDR_UNSPECIFIED (&props->local)) - NLA_PUT (msg, IFLA_GRE_REMOTE, sizeof (props->remote), &props->remote); - - NLA_PUT_U8 (msg, IFLA_GRE_TTL, props->ttl); - NLA_PUT_U8 (msg, IFLA_GRE_ENCAP_LIMIT, props->encap_limit); - - flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; - flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) - & IP6_FLOWINFO_TCLASS_MASK; - NLA_PUT_U32 (msg, IFLA_GRE_FLOWINFO, htonl (flowinfo)); - NLA_PUT_U32 (msg, IFLA_GRE_FLAGS, props->flags); - break; - } - case NM_LINK_TYPE_IPIP: { - const NMPlatformLnkIpIp *props = extra_data; - - nm_assert (props); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->parent_ifindex) - NLA_PUT_U32 (msg, IFLA_IPTUN_LINK, props->parent_ifindex); - NLA_PUT_U32 (msg, IFLA_IPTUN_LOCAL, props->local); - NLA_PUT_U32 (msg, IFLA_IPTUN_REMOTE, props->remote); - NLA_PUT_U8 (msg, IFLA_IPTUN_TTL, props->ttl); - NLA_PUT_U8 (msg, IFLA_IPTUN_TOS, props->tos); - NLA_PUT_U8 (msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); - break; - } - case NM_LINK_TYPE_MACSEC: { - const NMPlatformLnkMacsec *props = extra_data; - - nm_assert (props); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (props->icv_length) - NLA_PUT_U8 (msg, IFLA_MACSEC_ICV_LEN, 16); - if (props->cipher_suite) - NLA_PUT_U64 (msg, IFLA_MACSEC_CIPHER_SUITE, props->cipher_suite); - if (props->replay_protect) - NLA_PUT_U32 (msg, IFLA_MACSEC_WINDOW, props->window); - - NLA_PUT_U64 (msg, IFLA_MACSEC_SCI, htobe64 (props->sci)); - NLA_PUT_U8 (msg, IFLA_MACSEC_ENCODING_SA, props->encoding_sa); - NLA_PUT_U8 (msg, IFLA_MACSEC_ENCRYPT, props->encrypt); - NLA_PUT_U8 (msg, IFLA_MACSEC_PROTECT, props->protect); - NLA_PUT_U8 (msg, IFLA_MACSEC_INC_SCI, props->include_sci); - NLA_PUT_U8 (msg, IFLA_MACSEC_ES, props->es); - NLA_PUT_U8 (msg, IFLA_MACSEC_SCB, props->scb); - NLA_PUT_U8 (msg, IFLA_MACSEC_REPLAY_PROTECT, props->replay_protect); - NLA_PUT_U8 (msg, IFLA_MACSEC_VALIDATION, props->validation); - break; - }; - case NM_LINK_TYPE_MACVTAP: - case NM_LINK_TYPE_MACVLAN: { - const NMPlatformLnkMacvlan *props = extra_data; - - nm_assert (props); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - NLA_PUT_U32 (msg, IFLA_MACVLAN_MODE, props->mode); - NLA_PUT_U16 (msg, IFLA_MACVLAN_FLAGS, props->no_promisc ? MACVLAN_FLAG_NOPROMISC : 0); - break; - } - default: - nm_assert (!extra_data); - break; - } - - if (data) - nla_nest_end (msg, data); - - nla_nest_end (msg, info); - - return TRUE; +_nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpointer extra_data) +{ + struct nlattr *info; + struct nlattr *data = NULL; + const char * kind; + + nm_assert(msg); + + kind = nm_link_type_to_rtnl_type_string(link_type); + if (!kind) + goto nla_put_failure; + + if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING(msg, IFLA_INFO_KIND, kind); + + switch (link_type) { + case NM_LINK_TYPE_BRIDGE: + { + const NMPlatformLnkBridge *props = extra_data; + + nm_assert(extra_data); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32(msg, IFLA_BR_FORWARD_DELAY, props->forward_delay); + NLA_PUT_U32(msg, IFLA_BR_HELLO_TIME, props->hello_time); + NLA_PUT_U32(msg, IFLA_BR_MAX_AGE, props->max_age); + NLA_PUT_U32(msg, IFLA_BR_AGEING_TIME, props->ageing_time); + NLA_PUT_U32(msg, IFLA_BR_STP_STATE, !!props->stp_state); + NLA_PUT_U16(msg, IFLA_BR_PRIORITY, props->priority); + NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL, htons(props->vlan_protocol)); + if (props->vlan_stats_enabled) + NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED, !!props->vlan_stats_enabled); + NLA_PUT_U16(msg, IFLA_BR_GROUP_FWD_MASK, props->group_fwd_mask); + NLA_PUT(msg, IFLA_BR_GROUP_ADDR, sizeof(props->group_addr), &props->group_addr); + NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, !!props->mcast_snooping); + NLA_PUT_U8(msg, IFLA_BR_MCAST_ROUTER, props->mcast_router); + NLA_PUT_U8(msg, IFLA_BR_MCAST_QUERY_USE_IFADDR, !!props->mcast_query_use_ifaddr); + NLA_PUT_U8(msg, IFLA_BR_MCAST_QUERIER, !!props->mcast_querier); + NLA_PUT_U32(msg, IFLA_BR_MCAST_HASH_MAX, props->mcast_hash_max); + NLA_PUT_U32(msg, IFLA_BR_MCAST_LAST_MEMBER_CNT, props->mcast_last_member_count); + NLA_PUT_U32(msg, IFLA_BR_MCAST_STARTUP_QUERY_CNT, props->mcast_startup_query_count); + NLA_PUT_U64(msg, IFLA_BR_MCAST_LAST_MEMBER_INTVL, props->mcast_last_member_interval); + NLA_PUT_U64(msg, IFLA_BR_MCAST_MEMBERSHIP_INTVL, props->mcast_membership_interval); + NLA_PUT_U64(msg, IFLA_BR_MCAST_QUERIER_INTVL, props->mcast_querier_interval); + NLA_PUT_U64(msg, IFLA_BR_MCAST_QUERY_INTVL, props->mcast_query_interval); + NLA_PUT_U64(msg, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, props->mcast_query_response_interval); + NLA_PUT_U64(msg, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, props->mcast_startup_query_interval); + break; + } + case NM_LINK_TYPE_VLAN: + { + const NMPlatformLnkVlan *props = extra_data; + + nm_assert(extra_data); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U16(msg, IFLA_VLAN_ID, props->id); + + { + struct ifla_vlan_flags flags = { + .flags = props->flags & NM_VLAN_FLAGS_ALL, + .mask = NM_VLAN_FLAGS_ALL, + }; + + NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags); + } + break; + } + case NM_LINK_TYPE_VRF: + { + const NMPlatformLnkVrf *props = extra_data; + + nm_assert(extra_data); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32(msg, IFLA_VRF_TABLE, props->table); + break; + } + case NM_LINK_TYPE_VXLAN: + { + const NMPlatformLnkVxlan *props = extra_data; + + nm_assert(extra_data); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32(msg, IFLA_VXLAN_ID, props->id); + + if (props->group) + NLA_PUT(msg, IFLA_VXLAN_GROUP, sizeof(props->group), &props->group); + else if (!IN6_IS_ADDR_UNSPECIFIED(&props->group6)) + NLA_PUT(msg, IFLA_VXLAN_GROUP6, sizeof(props->group6), &props->group6); + + if (props->local) + NLA_PUT(msg, IFLA_VXLAN_LOCAL, sizeof(props->local), &props->local); + else if (!IN6_IS_ADDR_UNSPECIFIED(&props->local6)) + NLA_PUT(msg, IFLA_VXLAN_LOCAL6, sizeof(props->local6), &props->local6); + + if (props->parent_ifindex >= 0) + NLA_PUT_U32(msg, IFLA_VXLAN_LINK, props->parent_ifindex); + + if (props->src_port_min || props->src_port_max) { + struct nm_ifla_vxlan_port_range port_range = { + .low = htons(props->src_port_min), + .high = htons(props->src_port_max), + }; + + NLA_PUT(msg, IFLA_VXLAN_PORT_RANGE, sizeof(port_range), &port_range); + } + + NLA_PUT_U16(msg, IFLA_VXLAN_PORT, htons(props->dst_port)); + NLA_PUT_U8(msg, IFLA_VXLAN_TOS, props->tos); + NLA_PUT_U8(msg, IFLA_VXLAN_TTL, props->ttl); + NLA_PUT_U32(msg, IFLA_VXLAN_AGEING, props->ageing); + NLA_PUT_U32(msg, IFLA_VXLAN_LIMIT, props->limit); + NLA_PUT_U8(msg, IFLA_VXLAN_LEARNING, !!props->learning); + NLA_PUT_U8(msg, IFLA_VXLAN_PROXY, !!props->proxy); + NLA_PUT_U8(msg, IFLA_VXLAN_RSC, !!props->rsc); + NLA_PUT_U8(msg, IFLA_VXLAN_L2MISS, !!props->l2miss); + NLA_PUT_U8(msg, IFLA_VXLAN_L3MISS, !!props->l3miss); + break; + } + case NM_LINK_TYPE_VETH: + { + const char * veth_peer = extra_data; + const struct ifinfomsg ifi = {}; + struct nlattr * info_peer; + + nm_assert(veth_peer); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + if (!(info_peer = nla_nest_start(msg, 1 /*VETH_INFO_PEER*/))) + goto nla_put_failure; + if (nlmsg_append_struct(msg, &ifi) < 0) + goto nla_put_failure; + NLA_PUT_STRING(msg, IFLA_IFNAME, veth_peer); + nla_nest_end(msg, info_peer); + break; + } + case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_GRETAP: + { + const NMPlatformLnkGre *props = extra_data; + + nm_assert(props); + nm_assert(props->is_tap == (link_type == NM_LINK_TYPE_GRETAP)); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32(msg, IFLA_GRE_LINK, props->parent_ifindex); + NLA_PUT_U32(msg, IFLA_GRE_LOCAL, props->local); + NLA_PUT_U32(msg, IFLA_GRE_REMOTE, props->remote); + NLA_PUT_U8(msg, IFLA_GRE_TTL, props->ttl); + NLA_PUT_U8(msg, IFLA_GRE_TOS, props->tos); + NLA_PUT_U8(msg, IFLA_GRE_PMTUDISC, !!props->path_mtu_discovery); + NLA_PUT_U32(msg, IFLA_GRE_IKEY, htonl(props->input_key)); + NLA_PUT_U32(msg, IFLA_GRE_OKEY, htonl(props->output_key)); + NLA_PUT_U16(msg, IFLA_GRE_IFLAGS, htons(props->input_flags)); + NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, htons(props->output_flags)); + break; + } + case NM_LINK_TYPE_SIT: + { + const NMPlatformLnkSit *props = extra_data; + + nm_assert(props); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32(msg, IFLA_IPTUN_LINK, props->parent_ifindex); + NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, props->local); + NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, props->remote); + NLA_PUT_U8(msg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8(msg, IFLA_IPTUN_TOS, props->tos); + NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); + break; + } + case NM_LINK_TYPE_IP6TNL: + { + const NMPlatformLnkIp6Tnl *props = extra_data; + guint32 flowinfo; + + nm_assert(props); + nm_assert(!props->is_gre); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32(msg, IFLA_IPTUN_LINK, props->parent_ifindex); + + if (!IN6_IS_ADDR_UNSPECIFIED(&props->local)) + NLA_PUT(msg, IFLA_IPTUN_LOCAL, sizeof(props->local), &props->local); + if (!IN6_IS_ADDR_UNSPECIFIED(&props->remote)) + NLA_PUT(msg, IFLA_IPTUN_REMOTE, sizeof(props->remote), &props->remote); + + NLA_PUT_U8(msg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8(msg, IFLA_IPTUN_ENCAP_LIMIT, props->encap_limit); + + flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; + flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) & IP6_FLOWINFO_TCLASS_MASK; + NLA_PUT_U32(msg, IFLA_IPTUN_FLOWINFO, htonl(flowinfo)); + NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, props->proto); + NLA_PUT_U32(msg, IFLA_IPTUN_FLAGS, props->flags); + break; + } + case NM_LINK_TYPE_IP6GRE: + case NM_LINK_TYPE_IP6GRETAP: + { + const NMPlatformLnkIp6Tnl *props = extra_data; + guint32 flowinfo; + + nm_assert(props); + nm_assert(props->is_gre); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32(msg, IFLA_GRE_LINK, props->parent_ifindex); + + NLA_PUT_U32(msg, IFLA_GRE_IKEY, htonl(props->input_key)); + NLA_PUT_U32(msg, IFLA_GRE_OKEY, htonl(props->output_key)); + NLA_PUT_U16(msg, IFLA_GRE_IFLAGS, htons(props->input_flags)); + NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, htons(props->output_flags)); + + if (!IN6_IS_ADDR_UNSPECIFIED(&props->local)) + NLA_PUT(msg, IFLA_GRE_LOCAL, sizeof(props->local), &props->local); + if (!IN6_IS_ADDR_UNSPECIFIED(&props->local)) + NLA_PUT(msg, IFLA_GRE_REMOTE, sizeof(props->remote), &props->remote); + + NLA_PUT_U8(msg, IFLA_GRE_TTL, props->ttl); + NLA_PUT_U8(msg, IFLA_GRE_ENCAP_LIMIT, props->encap_limit); + + flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; + flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) & IP6_FLOWINFO_TCLASS_MASK; + NLA_PUT_U32(msg, IFLA_GRE_FLOWINFO, htonl(flowinfo)); + NLA_PUT_U32(msg, IFLA_GRE_FLAGS, props->flags); + break; + } + case NM_LINK_TYPE_IPIP: + { + const NMPlatformLnkIpIp *props = extra_data; + + nm_assert(props); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32(msg, IFLA_IPTUN_LINK, props->parent_ifindex); + NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, props->local); + NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, props->remote); + NLA_PUT_U8(msg, IFLA_IPTUN_TTL, props->ttl); + NLA_PUT_U8(msg, IFLA_IPTUN_TOS, props->tos); + NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, !!props->path_mtu_discovery); + break; + } + case NM_LINK_TYPE_MACSEC: + { + const NMPlatformLnkMacsec *props = extra_data; + + nm_assert(props); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->icv_length) + NLA_PUT_U8(msg, IFLA_MACSEC_ICV_LEN, 16); + if (props->cipher_suite) + NLA_PUT_U64(msg, IFLA_MACSEC_CIPHER_SUITE, props->cipher_suite); + if (props->replay_protect) + NLA_PUT_U32(msg, IFLA_MACSEC_WINDOW, props->window); + + NLA_PUT_U64(msg, IFLA_MACSEC_SCI, htobe64(props->sci)); + NLA_PUT_U8(msg, IFLA_MACSEC_ENCODING_SA, props->encoding_sa); + NLA_PUT_U8(msg, IFLA_MACSEC_ENCRYPT, props->encrypt); + NLA_PUT_U8(msg, IFLA_MACSEC_PROTECT, props->protect); + NLA_PUT_U8(msg, IFLA_MACSEC_INC_SCI, props->include_sci); + NLA_PUT_U8(msg, IFLA_MACSEC_ES, props->es); + NLA_PUT_U8(msg, IFLA_MACSEC_SCB, props->scb); + NLA_PUT_U8(msg, IFLA_MACSEC_REPLAY_PROTECT, props->replay_protect); + NLA_PUT_U8(msg, IFLA_MACSEC_VALIDATION, props->validation); + break; + }; + case NM_LINK_TYPE_MACVTAP: + case NM_LINK_TYPE_MACVLAN: + { + const NMPlatformLnkMacvlan *props = extra_data; + + nm_assert(props); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32(msg, IFLA_MACVLAN_MODE, props->mode); + NLA_PUT_U16(msg, IFLA_MACVLAN_FLAGS, props->no_promisc ? MACVLAN_FLAG_NOPROMISC : 0); + break; + } + default: + nm_assert(!extra_data); + break; + } + + if (data) + nla_nest_end(msg, data); + + nla_nest_end(msg, info); + + return TRUE; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static gboolean -_nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg, - int vlan_id, - guint32 flags_mask, - guint32 flags_set, - const NMVlanQosMapping *ingress_qos, - int ingress_qos_len, - const NMVlanQosMapping *egress_qos, - int egress_qos_len) -{ - struct nlattr *info; - struct nlattr *data; - guint i; - gboolean has_any_vlan_properties = FALSE; - - G_STATIC_ASSERT (NM_VLAN_FLAG_REORDER_HEADERS == (guint32) VLAN_FLAG_REORDER_HDR); - G_STATIC_ASSERT (NM_VLAN_FLAG_GVRP == (guint32) VLAN_FLAG_GVRP); - G_STATIC_ASSERT (NM_VLAN_FLAG_LOOSE_BINDING == (guint32) VLAN_FLAG_LOOSE_BINDING); - G_STATIC_ASSERT (NM_VLAN_FLAG_MVRP == (guint32) VLAN_FLAG_MVRP); +_nl_msg_new_link_set_linkinfo_vlan(struct nl_msg * msg, + int vlan_id, + guint32 flags_mask, + guint32 flags_set, + const NMVlanQosMapping *ingress_qos, + int ingress_qos_len, + const NMVlanQosMapping *egress_qos, + int egress_qos_len) +{ + struct nlattr *info; + struct nlattr *data; + guint i; + gboolean has_any_vlan_properties = FALSE; + + G_STATIC_ASSERT(NM_VLAN_FLAG_REORDER_HEADERS == (guint32) VLAN_FLAG_REORDER_HDR); + G_STATIC_ASSERT(NM_VLAN_FLAG_GVRP == (guint32) VLAN_FLAG_GVRP); + G_STATIC_ASSERT(NM_VLAN_FLAG_LOOSE_BINDING == (guint32) VLAN_FLAG_LOOSE_BINDING); + G_STATIC_ASSERT(NM_VLAN_FLAG_MVRP == (guint32) VLAN_FLAG_MVRP); #define VLAN_XGRESS_PRIO_VALID(from) (((from) & ~(guint32) 0x07) == 0) - nm_assert (msg); - - /* We must not create an empty IFLA_LINKINFO section. Otherwise, kernel - * rejects the request as invalid. */ - if ( flags_mask != 0 - || vlan_id >= 0) - has_any_vlan_properties = TRUE; - if ( !has_any_vlan_properties - && ingress_qos && ingress_qos_len > 0) { - for (i = 0; i < ingress_qos_len; i++) { - if (VLAN_XGRESS_PRIO_VALID (ingress_qos[i].from)) { - has_any_vlan_properties = TRUE; - break; - } - } - } - if ( !has_any_vlan_properties - && egress_qos && egress_qos_len > 0) { - for (i = 0; i < egress_qos_len; i++) { - if (VLAN_XGRESS_PRIO_VALID (egress_qos[i].to)) { - has_any_vlan_properties = TRUE; - break; - } - } - } - if (!has_any_vlan_properties) - return TRUE; - - if (!(info = nla_nest_start (msg, IFLA_LINKINFO))) - goto nla_put_failure; - - NLA_PUT_STRING (msg, IFLA_INFO_KIND, "vlan"); - - if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - if (vlan_id >= 0) - NLA_PUT_U16 (msg, IFLA_VLAN_ID, vlan_id); - - if (flags_mask != 0) { - struct ifla_vlan_flags flags = { - .flags = flags_mask & flags_set, - .mask = flags_mask, - }; - - NLA_PUT (msg, IFLA_VLAN_FLAGS, sizeof (flags), &flags); - } - - if (ingress_qos && ingress_qos_len > 0) { - struct nlattr *qos = NULL; - - for (i = 0; i < ingress_qos_len; i++) { - /* Silently ignore invalid mappings. Kernel would truncate - * them and modify the wrong mapping. */ - if (VLAN_XGRESS_PRIO_VALID (ingress_qos[i].from)) { - if (!qos) { - if (!(qos = nla_nest_start (msg, IFLA_VLAN_INGRESS_QOS))) - goto nla_put_failure; - } - NLA_PUT (msg, i, sizeof (ingress_qos[i]), &ingress_qos[i]); - } - } - - if (qos) - nla_nest_end (msg, qos); - } - - if (egress_qos && egress_qos_len > 0) { - struct nlattr *qos = NULL; - - for (i = 0; i < egress_qos_len; i++) { - if (VLAN_XGRESS_PRIO_VALID (egress_qos[i].to)) { - if (!qos) { - if (!(qos = nla_nest_start (msg, IFLA_VLAN_EGRESS_QOS))) - goto nla_put_failure; - } - NLA_PUT (msg, i, sizeof (egress_qos[i]), &egress_qos[i]); - } - } - - if (qos) - nla_nest_end (msg, qos); - } - - nla_nest_end (msg, data); - nla_nest_end (msg, info); - - return TRUE; + nm_assert(msg); + + /* We must not create an empty IFLA_LINKINFO section. Otherwise, kernel + * rejects the request as invalid. */ + if (flags_mask != 0 || vlan_id >= 0) + has_any_vlan_properties = TRUE; + if (!has_any_vlan_properties && ingress_qos && ingress_qos_len > 0) { + for (i = 0; i < ingress_qos_len; i++) { + if (VLAN_XGRESS_PRIO_VALID(ingress_qos[i].from)) { + has_any_vlan_properties = TRUE; + break; + } + } + } + if (!has_any_vlan_properties && egress_qos && egress_qos_len > 0) { + for (i = 0; i < egress_qos_len; i++) { + if (VLAN_XGRESS_PRIO_VALID(egress_qos[i].to)) { + has_any_vlan_properties = TRUE; + break; + } + } + } + if (!has_any_vlan_properties) + return TRUE; + + if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan"); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (vlan_id >= 0) + NLA_PUT_U16(msg, IFLA_VLAN_ID, vlan_id); + + if (flags_mask != 0) { + struct ifla_vlan_flags flags = { + .flags = flags_mask & flags_set, + .mask = flags_mask, + }; + + NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags); + } + + if (ingress_qos && ingress_qos_len > 0) { + struct nlattr *qos = NULL; + + for (i = 0; i < ingress_qos_len; i++) { + /* Silently ignore invalid mappings. Kernel would truncate + * them and modify the wrong mapping. */ + if (VLAN_XGRESS_PRIO_VALID(ingress_qos[i].from)) { + if (!qos) { + if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS))) + goto nla_put_failure; + } + NLA_PUT(msg, i, sizeof(ingress_qos[i]), &ingress_qos[i]); + } + } + + if (qos) + nla_nest_end(msg, qos); + } + + if (egress_qos && egress_qos_len > 0) { + struct nlattr *qos = NULL; + + for (i = 0; i < egress_qos_len; i++) { + if (VLAN_XGRESS_PRIO_VALID(egress_qos[i].to)) { + if (!qos) { + if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) + goto nla_put_failure; + } + NLA_PUT(msg, i, sizeof(egress_qos[i]), &egress_qos[i]); + } + } + + if (qos) + nla_nest_end(msg, qos); + } + + nla_nest_end(msg, data); + nla_nest_end(msg, info); + + return TRUE; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static struct nl_msg * -_nl_msg_new_link_full (int nlmsg_type, - int nlmsg_flags, - int ifindex, - const char *ifname, - guint8 family, - unsigned flags_mask, - unsigned flags_set) +_nl_msg_new_link_full(int nlmsg_type, + int nlmsg_flags, + int ifindex, + const char *ifname, + guint8 family, + unsigned flags_mask, + unsigned flags_set) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - const struct ifinfomsg ifi = { - .ifi_family = family, - .ifi_change = flags_mask, - .ifi_flags = flags_set, - .ifi_index = ifindex, - }; + nm_auto_nlmsg struct nl_msg *msg = NULL; + const struct ifinfomsg ifi = { + .ifi_family = family, + .ifi_change = flags_mask, + .ifi_flags = flags_set, + .ifi_index = ifindex, + }; - nm_assert (NM_IN_SET (nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK, RTM_SETLINK)); + nm_assert(NM_IN_SET(nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK, RTM_SETLINK)); - msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags); + msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); - if (nlmsg_append_struct (msg, &ifi) < 0) - goto nla_put_failure; + if (nlmsg_append_struct(msg, &ifi) < 0) + goto nla_put_failure; - if (ifname) - NLA_PUT_STRING (msg, IFLA_IFNAME, ifname); + if (ifname) + NLA_PUT_STRING(msg, IFLA_IFNAME, ifname); - return g_steal_pointer (&msg); + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static struct nl_msg * -_nl_msg_new_link (int nlmsg_type, - int nlmsg_flags, - int ifindex, - const char *ifname) +_nl_msg_new_link(int nlmsg_type, int nlmsg_flags, int ifindex, const char *ifname) { - return _nl_msg_new_link_full (nlmsg_type, nlmsg_flags, ifindex, ifname, AF_UNSPEC, 0, 0); + return _nl_msg_new_link_full(nlmsg_type, nlmsg_flags, ifindex, ifname, AF_UNSPEC, 0, 0); } /* Copied and modified from libnl3's build_addr_msg(). */ static struct nl_msg * -_nl_msg_new_address (int nlmsg_type, - int nlmsg_flags, - int family, - int ifindex, - gconstpointer address, - guint8 plen, - gconstpointer peer_address, - guint32 flags, - int scope, - guint32 lifetime, - guint32 preferred, - in_addr_t ip4_broadcast_address, - const char *label) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct ifaddrmsg am = { - .ifa_family = family, - .ifa_index = ifindex, - .ifa_prefixlen = plen, - .ifa_flags = flags, - }; - gsize addr_len; - - nm_assert (NM_IN_SET (family, AF_INET, AF_INET6)); - nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWADDR, RTM_DELADDR)); - - msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags); - - if (scope == -1) { - /* Allow having scope unset, and detect the scope (including IPv4 compatibility hack). */ - if ( family == AF_INET - && address - && *((char *) address) == 127) - scope = RT_SCOPE_HOST; - else - scope = RT_SCOPE_UNIVERSE; - } - am.ifa_scope = scope, - - addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr); - - if (nlmsg_append_struct (msg, &am) < 0) - goto nla_put_failure; - - if (address) - NLA_PUT (msg, IFA_LOCAL, addr_len, address); - - if (peer_address) - NLA_PUT (msg, IFA_ADDRESS, addr_len, peer_address); - else if (address) - NLA_PUT (msg, IFA_ADDRESS, addr_len, address); - - if (label && label[0]) - NLA_PUT_STRING (msg, IFA_LABEL, label); - - if (ip4_broadcast_address != 0) - NLA_PUT (msg, IFA_BROADCAST, sizeof (in_addr_t), &ip4_broadcast_address); - - if ( lifetime != NM_PLATFORM_LIFETIME_PERMANENT - || preferred != NM_PLATFORM_LIFETIME_PERMANENT) { - struct ifa_cacheinfo ca = { - .ifa_valid = lifetime, - .ifa_prefered = preferred, - }; - - NLA_PUT (msg, IFA_CACHEINFO, sizeof (ca), &ca); - } - - if (flags & ~((guint32) 0xFF)) { - /* only set the IFA_FLAGS attribute, if they actually contain additional - * flags that are not already set to am.ifa_flags. - * - * Older kernels refuse RTM_NEWADDR and RTM_NEWROUTE messages with EINVAL - * if they contain unknown netlink attributes. See net/core/rtnetlink.c, which - * was fixed by kernel commit 661d2967b3f1b34eeaa7e212e7b9bbe8ee072b59. */ - NLA_PUT_U32 (msg, IFA_FLAGS, flags); - } - - return g_steal_pointer (&msg); +_nl_msg_new_address(int nlmsg_type, + int nlmsg_flags, + int family, + int ifindex, + gconstpointer address, + guint8 plen, + gconstpointer peer_address, + guint32 flags, + int scope, + guint32 lifetime, + guint32 preferred, + in_addr_t ip4_broadcast_address, + const char * label) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct ifaddrmsg am = { + .ifa_family = family, + .ifa_index = ifindex, + .ifa_prefixlen = plen, + .ifa_flags = flags, + }; + gsize addr_len; + + nm_assert(NM_IN_SET(family, AF_INET, AF_INET6)); + nm_assert(NM_IN_SET(nlmsg_type, RTM_NEWADDR, RTM_DELADDR)); + + msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); + + if (scope == -1) { + /* Allow having scope unset, and detect the scope (including IPv4 compatibility hack). */ + if (family == AF_INET && address && *((char *) address) == 127) + scope = RT_SCOPE_HOST; + else + scope = RT_SCOPE_UNIVERSE; + } + am.ifa_scope = scope, + + addr_len = family == AF_INET ? sizeof(in_addr_t) : sizeof(struct in6_addr); + + if (nlmsg_append_struct(msg, &am) < 0) + goto nla_put_failure; + + if (address) + NLA_PUT(msg, IFA_LOCAL, addr_len, address); + + if (peer_address) + NLA_PUT(msg, IFA_ADDRESS, addr_len, peer_address); + else if (address) + NLA_PUT(msg, IFA_ADDRESS, addr_len, address); + + if (label && label[0]) + NLA_PUT_STRING(msg, IFA_LABEL, label); + + if (ip4_broadcast_address != 0) + NLA_PUT(msg, IFA_BROADCAST, sizeof(in_addr_t), &ip4_broadcast_address); + + if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT || preferred != NM_PLATFORM_LIFETIME_PERMANENT) { + struct ifa_cacheinfo ca = { + .ifa_valid = lifetime, + .ifa_prefered = preferred, + }; + + NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca); + } + + if (flags & ~((guint32) 0xFF)) { + /* only set the IFA_FLAGS attribute, if they actually contain additional + * flags that are not already set to am.ifa_flags. + * + * Older kernels refuse RTM_NEWADDR and RTM_NEWROUTE messages with EINVAL + * if they contain unknown netlink attributes. See net/core/rtnetlink.c, which + * was fixed by kernel commit 661d2967b3f1b34eeaa7e212e7b9bbe8ee072b59. */ + NLA_PUT_U32(msg, IFA_FLAGS, flags); + } + + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static guint32 -ip_route_get_lock_flag (const NMPlatformIPRoute *route) +ip_route_get_lock_flag(const NMPlatformIPRoute *route) { - return (((guint32) route->lock_window) << RTAX_WINDOW) - | (((guint32) route->lock_cwnd) << RTAX_CWND) - | (((guint32) route->lock_initcwnd) << RTAX_INITCWND) - | (((guint32) route->lock_initrwnd) << RTAX_INITRWND) - | (((guint32) route->lock_mtu) << RTAX_MTU); + return (((guint32) route->lock_window) << RTAX_WINDOW) + | (((guint32) route->lock_cwnd) << RTAX_CWND) + | (((guint32) route->lock_initcwnd) << RTAX_INITCWND) + | (((guint32) route->lock_initrwnd) << RTAX_INITRWND) + | (((guint32) route->lock_mtu) << RTAX_MTU); } /* Copied and modified from libnl3's build_route_msg() and rtnl_route_build_msg(). */ static struct nl_msg * -_nl_msg_new_route (int nlmsg_type, - guint16 nlmsgflags, - const NMPObject *obj) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj); - gboolean is_v4 = klass->addr_family == AF_INET; - const guint32 lock = ip_route_get_lock_flag (NMP_OBJECT_CAST_IP_ROUTE (obj)); - const guint32 table = nm_platform_route_table_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced, TRUE); - const struct rtmsg rtmsg = { - .rtm_family = klass->addr_family, - .rtm_tos = is_v4 - ? obj->ip4_route.tos - : 0, - .rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC, - .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (obj->ip_route.rt_source), - .rtm_scope = is_v4 - ? nm_platform_route_scope_inv (obj->ip4_route.scope_inv) - : RT_SCOPE_NOWHERE, - .rtm_type = nm_platform_route_type_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->type_coerced), - .rtm_flags = obj->ip_route.r_rtm_flags & ((unsigned) (RTNH_F_ONLINK)), - .rtm_dst_len = obj->ip_route.plen, - .rtm_src_len = is_v4 - ? 0 - : NMP_OBJECT_CAST_IP6_ROUTE (obj)->src_plen, - }; - - gsize addr_len; - - nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE)); - - msg = nlmsg_alloc_simple (nlmsg_type, (int) nlmsgflags); - - if (nlmsg_append_struct (msg, &rtmsg) < 0) - goto nla_put_failure; - - addr_len = is_v4 - ? sizeof (in_addr_t) - : sizeof (struct in6_addr); - - NLA_PUT (msg, RTA_DST, addr_len, - is_v4 - ? (gconstpointer) &obj->ip4_route.network - : (gconstpointer) &obj->ip6_route.network); - - if (!is_v4) { - if (!IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (obj)->src)) - NLA_PUT (msg, RTA_SRC, addr_len, &obj->ip6_route.src); - } - - NLA_PUT_U32 (msg, RTA_PRIORITY, obj->ip_route.metric); - - if (table > 0xFF) - NLA_PUT_U32 (msg, RTA_TABLE, table); - - if (is_v4) { - if (NMP_OBJECT_CAST_IP4_ROUTE (obj)->pref_src) - NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src); - } else { - if (!IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (obj)->pref_src)) - NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip6_route.pref_src); - } - - if ( obj->ip_route.mss - || obj->ip_route.window - || obj->ip_route.cwnd - || obj->ip_route.initcwnd - || obj->ip_route.initrwnd - || obj->ip_route.mtu - || lock) { - struct nlattr *metrics; - - metrics = nla_nest_start (msg, RTA_METRICS); - if (!metrics) - goto nla_put_failure; - - if (obj->ip_route.mss) - NLA_PUT_U32 (msg, RTAX_ADVMSS, obj->ip_route.mss); - if (obj->ip_route.window) - NLA_PUT_U32 (msg, RTAX_WINDOW, obj->ip_route.window); - if (obj->ip_route.cwnd) - NLA_PUT_U32 (msg, RTAX_CWND, obj->ip_route.cwnd); - if (obj->ip_route.initcwnd) - NLA_PUT_U32 (msg, RTAX_INITCWND, obj->ip_route.initcwnd); - if (obj->ip_route.initrwnd) - NLA_PUT_U32 (msg, RTAX_INITRWND, obj->ip_route.initrwnd); - if (obj->ip_route.mtu) - NLA_PUT_U32 (msg, RTAX_MTU, obj->ip_route.mtu); - if (lock) - NLA_PUT_U32 (msg, RTAX_LOCK, lock); - - nla_nest_end (msg, metrics); - } - - /* We currently don't have need for multi-hop routes... */ - if (is_v4) { - NLA_PUT (msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway); - } else { - if (!IN6_IS_ADDR_UNSPECIFIED (&obj->ip6_route.gateway)) - NLA_PUT (msg, RTA_GATEWAY, addr_len, &obj->ip6_route.gateway); - } - NLA_PUT_U32 (msg, RTA_OIF, obj->ip_route.ifindex); - - if ( !is_v4 - && obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM) - NLA_PUT_U8 (msg, RTA_PREF, obj->ip6_route.rt_pref); - - return g_steal_pointer (&msg); +_nl_msg_new_route(int nlmsg_type, guint16 nlmsgflags, const NMPObject *obj) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + const NMPClass * klass = NMP_OBJECT_GET_CLASS(obj); + gboolean is_v4 = klass->addr_family == AF_INET; + const guint32 lock = ip_route_get_lock_flag(NMP_OBJECT_CAST_IP_ROUTE(obj)); + const guint32 table = + nm_platform_route_table_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->table_coerced, TRUE); + const struct rtmsg rtmsg = { + .rtm_family = klass->addr_family, + .rtm_tos = is_v4 ? obj->ip4_route.tos : 0, + .rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC, + .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot(obj->ip_route.rt_source), + .rtm_scope = + is_v4 ? nm_platform_route_scope_inv(obj->ip4_route.scope_inv) : RT_SCOPE_NOWHERE, + .rtm_type = nm_platform_route_type_uncoerce(NMP_OBJECT_CAST_IP_ROUTE(obj)->type_coerced), + .rtm_flags = obj->ip_route.r_rtm_flags & ((unsigned) (RTNH_F_ONLINK)), + .rtm_dst_len = obj->ip_route.plen, + .rtm_src_len = is_v4 ? 0 : NMP_OBJECT_CAST_IP6_ROUTE(obj)->src_plen, + }; + + gsize addr_len; + + nm_assert( + NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); + nm_assert(NM_IN_SET(nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE)); + + msg = nlmsg_alloc_simple(nlmsg_type, (int) nlmsgflags); + + if (nlmsg_append_struct(msg, &rtmsg) < 0) + goto nla_put_failure; + + addr_len = is_v4 ? sizeof(in_addr_t) : sizeof(struct in6_addr); + + NLA_PUT(msg, + RTA_DST, + addr_len, + is_v4 ? (gconstpointer) &obj->ip4_route.network + : (gconstpointer) &obj->ip6_route.network); + + if (!is_v4) { + if (!IN6_IS_ADDR_UNSPECIFIED(&NMP_OBJECT_CAST_IP6_ROUTE(obj)->src)) + NLA_PUT(msg, RTA_SRC, addr_len, &obj->ip6_route.src); + } + + NLA_PUT_U32(msg, + RTA_PRIORITY, + is_v4 ? nm_platform_ip4_route_get_effective_metric(&obj->ip4_route) + : nm_platform_ip6_route_get_effective_metric(&obj->ip6_route)); + + if (table > 0xFF) + NLA_PUT_U32(msg, RTA_TABLE, table); + + if (is_v4) { + if (NMP_OBJECT_CAST_IP4_ROUTE(obj)->pref_src) + NLA_PUT(msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src); + } else { + if (!IN6_IS_ADDR_UNSPECIFIED(&NMP_OBJECT_CAST_IP6_ROUTE(obj)->pref_src)) + NLA_PUT(msg, RTA_PREFSRC, addr_len, &obj->ip6_route.pref_src); + } + + if (obj->ip_route.mss || obj->ip_route.window || obj->ip_route.cwnd || obj->ip_route.initcwnd + || obj->ip_route.initrwnd || obj->ip_route.mtu || lock) { + struct nlattr *metrics; + + metrics = nla_nest_start(msg, RTA_METRICS); + if (!metrics) + goto nla_put_failure; + + if (obj->ip_route.mss) + NLA_PUT_U32(msg, RTAX_ADVMSS, obj->ip_route.mss); + if (obj->ip_route.window) + NLA_PUT_U32(msg, RTAX_WINDOW, obj->ip_route.window); + if (obj->ip_route.cwnd) + NLA_PUT_U32(msg, RTAX_CWND, obj->ip_route.cwnd); + if (obj->ip_route.initcwnd) + NLA_PUT_U32(msg, RTAX_INITCWND, obj->ip_route.initcwnd); + if (obj->ip_route.initrwnd) + NLA_PUT_U32(msg, RTAX_INITRWND, obj->ip_route.initrwnd); + if (obj->ip_route.mtu) + NLA_PUT_U32(msg, RTAX_MTU, obj->ip_route.mtu); + if (lock) + NLA_PUT_U32(msg, RTAX_LOCK, lock); + + nla_nest_end(msg, metrics); + } + + /* We currently don't have need for multi-hop routes... */ + if (is_v4) { + NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway); + } else { + if (!IN6_IS_ADDR_UNSPECIFIED(&obj->ip6_route.gateway)) + NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip6_route.gateway); + } + NLA_PUT_U32(msg, RTA_OIF, obj->ip_route.ifindex); + + if (!is_v4 && obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM) + NLA_PUT_U8(msg, RTA_PREF, obj->ip6_route.rt_pref); + + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static struct nl_msg * -_nl_msg_new_routing_rule (int nlmsg_type, - int nlmsg_flags, - const NMPlatformRoutingRule *routing_rule) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - const guint8 addr_size = nm_utils_addr_family_to_size (routing_rule->addr_family); - guint32 table; +_nl_msg_new_routing_rule(int nlmsg_type, int nlmsg_flags, const NMPlatformRoutingRule *routing_rule) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + const guint8 addr_size = nm_utils_addr_family_to_size(routing_rule->addr_family); + guint32 table; - msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags); + msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); - table = routing_rule->table; + table = routing_rule->table; - if ( NM_IN_SET (routing_rule->addr_family, AF_INET, AF_INET6) - && routing_rule->action == FR_ACT_TO_TBL - && routing_rule->l3mdev == 0 - && table == RT_TABLE_UNSPEC) { - /* for IPv6, this setting is invalid and rejected by kernel. That's fine. - * - * for IPv4, kernel will automatically assign an unused table. That's not - * fine, because we don't know what we will get. - * - * The caller must not allow that to happen. */ - nm_assert_not_reached (); - } + if (NM_IN_SET(routing_rule->addr_family, AF_INET, AF_INET6) + && routing_rule->action == FR_ACT_TO_TBL && routing_rule->l3mdev == 0 + && table == RT_TABLE_UNSPEC) { + /* for IPv6, this setting is invalid and rejected by kernel. That's fine. + * + * for IPv4, kernel will automatically assign an unused table. That's not + * fine, because we don't know what we will get. + * + * The caller must not allow that to happen. */ + nm_assert_not_reached(); + } - { - const struct fib_rule_hdr frh = { - .family = routing_rule->addr_family, - .src_len = routing_rule->src_len, - .dst_len = routing_rule->dst_len, - .tos = routing_rule->tos, - .table = table < 0x100u ? (guint8) table : (guint8) RT_TABLE_UNSPEC, - .action = routing_rule->action, + { + const struct fib_rule_hdr frh = { + .family = routing_rule->addr_family, + .src_len = routing_rule->src_len, + .dst_len = routing_rule->dst_len, + .tos = routing_rule->tos, + .table = table < 0x100u ? (guint8) table : (guint8) RT_TABLE_UNSPEC, + .action = routing_rule->action, - /* we only allow setting the "not" flag. */ - .flags = routing_rule->flags & ((guint32) FIB_RULE_INVERT), - }; + /* we only allow setting the "not" flag. */ + .flags = routing_rule->flags & ((guint32) FIB_RULE_INVERT), + }; - if (nlmsg_append_struct (msg, &frh) < 0) - goto nla_put_failure; - } + if (nlmsg_append_struct(msg, &frh) < 0) + goto nla_put_failure; + } - if (table > G_MAXINT8) - NLA_PUT_U32 (msg, FRA_TABLE, table); + if (table > G_MAXINT8) + NLA_PUT_U32(msg, FRA_TABLE, table); - if (routing_rule->suppress_prefixlen_inverse != 0) - NLA_PUT_U32 (msg, FRA_SUPPRESS_PREFIXLEN, ~routing_rule->suppress_prefixlen_inverse); + if (routing_rule->suppress_prefixlen_inverse != 0) + NLA_PUT_U32(msg, FRA_SUPPRESS_PREFIXLEN, ~routing_rule->suppress_prefixlen_inverse); - if (routing_rule->suppress_ifgroup_inverse != 0) - NLA_PUT_U32 (msg, FRA_SUPPRESS_IFGROUP, ~routing_rule->suppress_ifgroup_inverse); + if (routing_rule->suppress_ifgroup_inverse != 0) + NLA_PUT_U32(msg, FRA_SUPPRESS_IFGROUP, ~routing_rule->suppress_ifgroup_inverse); - if (routing_rule->iifname[0] != '\0') - NLA_PUT_STRING (msg, FRA_IIFNAME, routing_rule->iifname); + if (routing_rule->iifname[0] != '\0') + NLA_PUT_STRING(msg, FRA_IIFNAME, routing_rule->iifname); - if (routing_rule->oifname[0] != '\0') - NLA_PUT_STRING (msg, FRA_OIFNAME, routing_rule->oifname); + if (routing_rule->oifname[0] != '\0') + NLA_PUT_STRING(msg, FRA_OIFNAME, routing_rule->oifname); - /* we always set the priority and don't support letting kernel pick one. */ - NLA_PUT_U32 (msg, FRA_PRIORITY, routing_rule->priority); + /* we always set the priority and don't support letting kernel pick one. */ + NLA_PUT_U32(msg, FRA_PRIORITY, routing_rule->priority); - if ( routing_rule->fwmark != 0 - || routing_rule->fwmask != 0) { - NLA_PUT_U32 (msg, FRA_FWMARK, routing_rule->fwmark); - NLA_PUT_U32 (msg, FRA_FWMASK, routing_rule->fwmask); - } + if (routing_rule->fwmark != 0 || routing_rule->fwmask != 0) { + NLA_PUT_U32(msg, FRA_FWMARK, routing_rule->fwmark); + NLA_PUT_U32(msg, FRA_FWMASK, routing_rule->fwmask); + } - if (routing_rule->src_len > 0) - NLA_PUT (msg, FRA_SRC, addr_size, &routing_rule->src); + if (routing_rule->src_len > 0) + NLA_PUT(msg, FRA_SRC, addr_size, &routing_rule->src); - if (routing_rule->dst_len > 0) - NLA_PUT (msg, FRA_DST, addr_size, &routing_rule->dst); + if (routing_rule->dst_len > 0) + NLA_PUT(msg, FRA_DST, addr_size, &routing_rule->dst); - if (routing_rule->flow != 0) { - /* only relevant for IPv4. */ - NLA_PUT_U32 (msg, FRA_FLOW, routing_rule->flow); - } + if (routing_rule->flow != 0) { + /* only relevant for IPv4. */ + NLA_PUT_U32(msg, FRA_FLOW, routing_rule->flow); + } - if (routing_rule->tun_id != 0) - NLA_PUT_U64 (msg, FRA_TUN_ID, htobe64 (routing_rule->tun_id)); + if (routing_rule->tun_id != 0) + NLA_PUT_U64(msg, FRA_TUN_ID, htobe64(routing_rule->tun_id)); - if (routing_rule->l3mdev) - NLA_PUT_U8 (msg, FRA_L3MDEV, routing_rule->l3mdev); + if (routing_rule->l3mdev) + NLA_PUT_U8(msg, FRA_L3MDEV, routing_rule->l3mdev); - if (routing_rule->protocol != RTPROT_UNSPEC) - NLA_PUT_U8 (msg, FRA_PROTOCOL, routing_rule->protocol); + if (routing_rule->protocol != RTPROT_UNSPEC) + NLA_PUT_U8(msg, FRA_PROTOCOL, routing_rule->protocol); - if (routing_rule->ip_proto != 0) - NLA_PUT_U8 (msg, FRA_IP_PROTO, routing_rule->ip_proto); + if (routing_rule->ip_proto != 0) + NLA_PUT_U8(msg, FRA_IP_PROTO, routing_rule->ip_proto); - if ( routing_rule->sport_range.start - || routing_rule->sport_range.end) - NLA_PUT (msg, FRA_SPORT_RANGE, sizeof (routing_rule->sport_range), &routing_rule->sport_range); + if (routing_rule->sport_range.start || routing_rule->sport_range.end) + NLA_PUT(msg, + FRA_SPORT_RANGE, + sizeof(routing_rule->sport_range), + &routing_rule->sport_range); - if ( routing_rule->dport_range.start - || routing_rule->dport_range.end) - NLA_PUT (msg, FRA_DPORT_RANGE, sizeof (routing_rule->dport_range), &routing_rule->dport_range); + if (routing_rule->dport_range.start || routing_rule->dport_range.end) + NLA_PUT(msg, + FRA_DPORT_RANGE, + sizeof(routing_rule->dport_range), + &routing_rule->dport_range); - if (routing_rule->uid_range_has) - NLA_PUT (msg, FRA_UID_RANGE, sizeof (routing_rule->uid_range), &routing_rule->uid_range); + if (routing_rule->uid_range_has) + NLA_PUT(msg, FRA_UID_RANGE, sizeof(routing_rule->uid_range), &routing_rule->uid_range); - switch (routing_rule->action) { - case FR_ACT_GOTO: - NLA_PUT_U32 (msg, FRA_GOTO, routing_rule->goto_target); - break; - } + switch (routing_rule->action) { + case FR_ACT_GOTO: + NLA_PUT_U32(msg, FRA_GOTO, routing_rule->goto_target); + break; + } - return g_steal_pointer (&msg); + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static struct nl_msg * -_nl_msg_new_qdisc (int nlmsg_type, - int nlmsg_flags, - const NMPlatformQdisc *qdisc) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr *tc_options; - const struct tcmsg tcm = { - .tcm_family = qdisc->addr_family, - .tcm_ifindex = qdisc->ifindex, - .tcm_handle = qdisc->handle, - .tcm_parent = qdisc->parent, - .tcm_info = qdisc->info, - }; - - msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); - - if (nlmsg_append_struct (msg, &tcm) < 0) - goto nla_put_failure; - - NLA_PUT_STRING (msg, TCA_KIND, qdisc->kind); - - if (nm_streq (qdisc->kind, "sfq")) { - struct tc_sfq_qopt_v1 opt = { }; - - opt.v0.quantum = qdisc->sfq.quantum; - opt.v0.limit = qdisc->sfq.limit; - opt.v0.perturb_period = qdisc->sfq.perturb_period; - opt.v0.flows = qdisc->sfq.flows; - opt.v0.divisor = qdisc->sfq.divisor; - opt.depth = qdisc->sfq.depth; - - NLA_PUT (msg, TCA_OPTIONS, sizeof (opt), &opt); - } else if (nm_streq (qdisc->kind, "tbf")) { - struct tc_tbf_qopt opt = { }; - - if (!(tc_options = nla_nest_start (msg, TCA_OPTIONS))) - goto nla_put_failure; - - opt.rate.rate = (qdisc->tbf.rate >= (1ULL << 32)) - ? ~0U - : (guint32) qdisc->tbf.rate; - if (qdisc->tbf.limit) - opt.limit = qdisc->tbf.limit; - else if (qdisc->tbf.latency) { - opt.limit = qdisc->tbf.rate * (double) qdisc->tbf.latency - / PSCHED_TIME_UNITS_PER_SEC - + qdisc->tbf.burst; - } - - NLA_PUT (msg, TCA_TBF_PARMS, sizeof (opt), &opt); - if (qdisc->tbf.rate >= (1ULL << 32)) - NLA_PUT_U64 (msg, TCA_TBF_RATE64, qdisc->tbf.rate); - NLA_PUT_U32 (msg, TCA_TBF_BURST, qdisc->tbf.burst); - - nla_nest_end (msg, tc_options); - } else { - if (!(tc_options = nla_nest_start (msg, TCA_OPTIONS))) - goto nla_put_failure; - - if (nm_streq (qdisc->kind, "fq_codel")) { - if (qdisc->fq_codel.limit) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_LIMIT, qdisc->fq_codel.limit); - if (qdisc->fq_codel.flows) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_FLOWS, qdisc->fq_codel.flows); - if (qdisc->fq_codel.target) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_TARGET, qdisc->fq_codel.target); - if (qdisc->fq_codel.interval) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval); - if (qdisc->fq_codel.quantum) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); - if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); - if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory_limit); - if (qdisc->fq_codel.ecn) - NLA_PUT_U32 (msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); - } - - nla_nest_end (msg, tc_options); - } - - return g_steal_pointer (&msg); +_nl_msg_new_qdisc(int nlmsg_type, int nlmsg_flags, const NMPlatformQdisc *qdisc) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nlattr * tc_options; + const struct tcmsg tcm = { + .tcm_family = qdisc->addr_family, + .tcm_ifindex = qdisc->ifindex, + .tcm_handle = qdisc->handle, + .tcm_parent = qdisc->parent, + .tcm_info = qdisc->info, + }; + + msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); + + if (nlmsg_append_struct(msg, &tcm) < 0) + goto nla_put_failure; + + NLA_PUT_STRING(msg, TCA_KIND, qdisc->kind); + + if (nm_streq(qdisc->kind, "sfq")) { + struct tc_sfq_qopt_v1 opt = {}; + + opt.v0.quantum = qdisc->sfq.quantum; + opt.v0.limit = qdisc->sfq.limit; + opt.v0.perturb_period = qdisc->sfq.perturb_period; + opt.v0.flows = qdisc->sfq.flows; + opt.v0.divisor = qdisc->sfq.divisor; + opt.depth = qdisc->sfq.depth; + + NLA_PUT(msg, TCA_OPTIONS, sizeof(opt), &opt); + } else if (nm_streq(qdisc->kind, "tbf")) { + struct tc_tbf_qopt opt = {}; + + if (!(tc_options = nla_nest_start(msg, TCA_OPTIONS))) + goto nla_put_failure; + + opt.rate.rate = (qdisc->tbf.rate >= (1ULL << 32)) ? ~0U : (guint32) qdisc->tbf.rate; + if (qdisc->tbf.limit) + opt.limit = qdisc->tbf.limit; + else if (qdisc->tbf.latency) { + opt.limit = qdisc->tbf.rate * (double) qdisc->tbf.latency / PSCHED_TIME_UNITS_PER_SEC + + qdisc->tbf.burst; + } + + NLA_PUT(msg, TCA_TBF_PARMS, sizeof(opt), &opt); + if (qdisc->tbf.rate >= (1ULL << 32)) + NLA_PUT_U64(msg, TCA_TBF_RATE64, qdisc->tbf.rate); + NLA_PUT_U32(msg, TCA_TBF_BURST, qdisc->tbf.burst); + + nla_nest_end(msg, tc_options); + } else if (nm_streq(qdisc->kind, "prio")) { + struct tc_prio_qopt opt = {3, {1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}}; + + NLA_PUT(msg, TCA_OPTIONS, sizeof(opt), &opt); + } else { + if (!(tc_options = nla_nest_start(msg, TCA_OPTIONS))) + goto nla_put_failure; + + if (nm_streq(qdisc->kind, "fq_codel")) { + if (qdisc->fq_codel.limit) + NLA_PUT_U32(msg, TCA_FQ_CODEL_LIMIT, qdisc->fq_codel.limit); + if (qdisc->fq_codel.flows) + NLA_PUT_U32(msg, TCA_FQ_CODEL_FLOWS, qdisc->fq_codel.flows); + if (qdisc->fq_codel.target) + NLA_PUT_U32(msg, TCA_FQ_CODEL_TARGET, qdisc->fq_codel.target); + if (qdisc->fq_codel.interval) + NLA_PUT_U32(msg, TCA_FQ_CODEL_INTERVAL, qdisc->fq_codel.interval); + if (qdisc->fq_codel.quantum) + NLA_PUT_U32(msg, TCA_FQ_CODEL_QUANTUM, qdisc->fq_codel.quantum); + if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) + NLA_PUT_U32(msg, TCA_FQ_CODEL_CE_THRESHOLD, qdisc->fq_codel.ce_threshold); + if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) + NLA_PUT_U32(msg, TCA_FQ_CODEL_MEMORY_LIMIT, qdisc->fq_codel.memory_limit); + if (qdisc->fq_codel.ecn) + NLA_PUT_U32(msg, TCA_FQ_CODEL_ECN, qdisc->fq_codel.ecn); + } + + nla_nest_end(msg, tc_options); + } + + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static struct nl_msg * -_nl_msg_new_tfilter (int nlmsg_type, - int nlmsg_flags, - const NMPlatformTfilter *tfilter) +_nl_msg_new_tfilter(int nlmsg_type, int nlmsg_flags, const NMPlatformTfilter *tfilter) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr *tc_options; - struct nlattr *act_tab; - const struct tcmsg tcm = { - .tcm_family = tfilter->addr_family, - .tcm_ifindex = tfilter->ifindex, - .tcm_handle = tfilter->handle, - .tcm_parent = tfilter->parent, - .tcm_info = tfilter->info, - }; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nlattr * tc_options; + struct nlattr * act_tab; + const struct tcmsg tcm = { + .tcm_family = tfilter->addr_family, + .tcm_ifindex = tfilter->ifindex, + .tcm_handle = tfilter->handle, + .tcm_parent = tfilter->parent, + .tcm_info = tfilter->info, + }; - msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); + msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); - if (nlmsg_append_struct (msg, &tcm) < 0) - goto nla_put_failure; + if (nlmsg_append_struct(msg, &tcm) < 0) + goto nla_put_failure; - NLA_PUT_STRING (msg, TCA_KIND, tfilter->kind); + NLA_PUT_STRING(msg, TCA_KIND, tfilter->kind); - if (!(tc_options = nla_nest_start (msg, TCA_OPTIONS))) - goto nla_put_failure; + if (!(tc_options = nla_nest_start(msg, TCA_OPTIONS))) + goto nla_put_failure; - if (!(act_tab = nla_nest_start (msg, TCA_OPTIONS))) // 3 TCA_ACT_KIND TCA_ACT_KIND - goto nla_put_failure; + if (!(act_tab = nla_nest_start(msg, TCA_OPTIONS))) // 3 TCA_ACT_KIND TCA_ACT_KIND + goto nla_put_failure; - if (tfilter->action.kind) { - const NMPlatformAction *action = &tfilter->action; - struct nlattr *prio; - struct nlattr *act_options; + if (tfilter->action.kind) { + const NMPlatformAction *action = &tfilter->action; + struct nlattr * prio; + struct nlattr * act_options; - if (!(prio = nla_nest_start (msg, 1 /* priority */))) - goto nla_put_failure; + if (!(prio = nla_nest_start(msg, 1 /* priority */))) + goto nla_put_failure; - NLA_PUT_STRING (msg, TCA_ACT_KIND, action->kind); + NLA_PUT_STRING(msg, TCA_ACT_KIND, action->kind); - if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - const NMPlatformActionSimple *simple = &action->simple; - struct tc_defact sel = { 0, }; + if (nm_streq(action->kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { + const NMPlatformActionSimple *simple = &action->simple; + struct tc_defact sel = { + 0, + }; - if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS))) - goto nla_put_failure; + if (!(act_options = nla_nest_start(msg, TCA_ACT_OPTIONS))) + goto nla_put_failure; - NLA_PUT (msg, TCA_DEF_PARMS, sizeof (sel), &sel); - NLA_PUT (msg, TCA_DEF_DATA, sizeof (simple->sdata), simple->sdata); + NLA_PUT(msg, TCA_DEF_PARMS, sizeof(sel), &sel); + NLA_PUT(msg, TCA_DEF_DATA, sizeof(simple->sdata), simple->sdata); - nla_nest_end (msg, act_options); + nla_nest_end(msg, act_options); - } else if (nm_streq (action->kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - const NMPlatformActionMirred *mirred = &action->mirred; - struct tc_mirred sel = { 0, }; + } else if (nm_streq(action->kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { + const NMPlatformActionMirred *mirred = &action->mirred; + struct tc_mirred sel = { + 0, + }; - if (!(act_options = nla_nest_start (msg, TCA_ACT_OPTIONS))) - goto nla_put_failure; + if (!(act_options = nla_nest_start(msg, TCA_ACT_OPTIONS))) + goto nla_put_failure; - if (mirred->egress && mirred->redirect) - sel.eaction = TCA_EGRESS_REDIR; - else if (mirred->egress && mirred->mirror) - sel.eaction = TCA_EGRESS_MIRROR; - else if (mirred->ingress && mirred->redirect) - sel.eaction = TCA_INGRESS_REDIR; - else if (mirred->ingress && mirred->mirror) - sel.eaction = TCA_INGRESS_MIRROR; - sel.ifindex = mirred->ifindex; + if (mirred->egress && mirred->redirect) + sel.eaction = TCA_EGRESS_REDIR; + else if (mirred->egress && mirred->mirror) + sel.eaction = TCA_EGRESS_MIRROR; + else if (mirred->ingress && mirred->redirect) + sel.eaction = TCA_INGRESS_REDIR; + else if (mirred->ingress && mirred->mirror) + sel.eaction = TCA_INGRESS_MIRROR; + sel.ifindex = mirred->ifindex; - NLA_PUT (msg, TCA_MIRRED_PARMS, sizeof (sel), &sel); + NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(sel), &sel); - nla_nest_end (msg, act_options); - } + nla_nest_end(msg, act_options); + } - nla_nest_end (msg, prio); - } + nla_nest_end(msg, prio); + } - nla_nest_end (msg, tc_options); + nla_nest_end(msg, tc_options); - nla_nest_end (msg, act_tab); + nla_nest_end(msg, act_tab); - return g_steal_pointer (&msg); + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } /*****************************************************************************/ static struct nl_sock * -_genl_sock (NMLinuxPlatform *platform) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - - return priv->genl; -} - -#define ASSERT_SYSCTL_ARGS(pathid, dirfd, path) \ - G_STMT_START { \ - const char *const _pathid = (pathid); \ - const int _dirfd = (dirfd); \ - const char *const _path = (path); \ - \ - nm_assert (_path && _path[0]); \ - g_assert (!strstr (_path, "/../")); \ - if (_dirfd < 0) { \ - nm_assert (!_pathid); \ - nm_assert (_path[0] == '/'); \ - nm_assert ( g_str_has_prefix (_path, "/proc/sys/") \ - || g_str_has_prefix (_path, "/sys/") \ - || g_str_has_prefix (_path, "/proc/net")); \ - } else { \ - nm_assert (_pathid && _pathid[0] && _pathid[0] != '/'); \ - nm_assert (_path[0] != '/'); \ - } \ - } G_STMT_END +_genl_sock(NMLinuxPlatform *platform) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + + return priv->genl; +} + +#define ASSERT_SYSCTL_ARGS(pathid, dirfd, path) \ + G_STMT_START \ + { \ + const char *const _pathid = (pathid); \ + const int _dirfd = (dirfd); \ + const char *const _path = (path); \ + \ + nm_assert(_path &&_path[0]); \ + g_assert(!strstr(_path, "/../")); \ + if (_dirfd < 0) { \ + nm_assert(!_pathid); \ + nm_assert(_path[0] == '/'); \ + nm_assert(g_str_has_prefix(_path, "/proc/sys/") || g_str_has_prefix(_path, "/sys/") \ + || g_str_has_prefix(_path, "/proc/net")); \ + } else { \ + nm_assert(_pathid &&_pathid[0] && _pathid[0] != '/'); \ + nm_assert(_path[0] != '/'); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ @@ -4915,154 +5092,179 @@ _genl_sock (NMLinuxPlatform *platform) #define NM_THREAD_SAFE_ON_MAIN_THREAD 0 static void -_log_dbg_sysctl_set_impl (NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value) -{ - GError *error = NULL; - gs_free char *contents = NULL; - gs_free char *value_escaped = g_strescape (value, NULL); - - if (!nm_utils_file_get_contents (dirfd, - path, - 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, - NULL, - NULL, - &error)) { - _LOGD ("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", pathid ?: path, value_escaped, error->message); - g_clear_error (&error); - return; - } - - g_strstrip (contents); - if (nm_streq (contents, value)) - _LOGD ("sysctl: setting '%s' to '%s' (current value is identical)", pathid ?: path, value_escaped); - else { - gs_free char *contents_escaped = g_strescape (contents, NULL); - - _LOGD ("sysctl: setting '%s' to '%s' (current value is '%s')", pathid ?: path, value_escaped, contents_escaped); - } -} - -#define _log_dbg_sysctl_set(platform, pathid, dirfd, path, value) \ - G_STMT_START { \ - if (_LOGD_ENABLED ()) { \ - _log_dbg_sysctl_set_impl (platform, pathid, dirfd, path, value); \ - } \ - } G_STMT_END +_log_dbg_sysctl_set_impl(NMPlatform *platform, + const char *pathid, + int dirfd, + const char *path, + const char *value) +{ + GError * error = NULL; + gs_free char *contents = NULL; + gs_free char *value_escaped = g_strescape(value, NULL); + + if (!nm_utils_file_get_contents(dirfd, + path, + 1 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &contents, + NULL, + NULL, + &error)) { + _LOGD("sysctl: setting '%s' to '%s' (current value cannot be read: %s)", + pathid ?: path, + value_escaped, + error->message); + g_clear_error(&error); + return; + } + + g_strstrip(contents); + if (nm_streq(contents, value)) + _LOGD("sysctl: setting '%s' to '%s' (current value is identical)", + pathid ?: path, + value_escaped); + else { + gs_free char *contents_escaped = g_strescape(contents, NULL); + + _LOGD("sysctl: setting '%s' to '%s' (current value is '%s')", + pathid ?: path, + value_escaped, + contents_escaped); + } +} + +#define _log_dbg_sysctl_set(platform, pathid, dirfd, path, value) \ + G_STMT_START \ + { \ + if (_LOGD_ENABLED()) { \ + _log_dbg_sysctl_set_impl(platform, pathid, dirfd, path, value); \ + } \ + } \ + G_STMT_END static gboolean -sysctl_set_internal (NMPlatform *platform, - const char *pathid, - int dirfd, - const char *path, - const char *value) -{ - int fd, tries; - gssize nwrote; - gssize len; - char *actual; - gs_free char *actual_free = NULL; - int errsv; - - if (dirfd < 0) { - pathid = path; - - fd = open (path, O_WRONLY | O_TRUNC | O_CLOEXEC); - if (fd == -1) { - errsv = errno; - if (errsv == ENOENT) { - _LOGD ("sysctl: failed to open '%s': (%d) %s", - pathid, errsv, nm_strerror_native (errsv)); - } else { - _LOGE ("sysctl: failed to open '%s': (%d) %s", - pathid, errsv, nm_strerror_native (errsv)); - } - errno = errsv; - return FALSE; - } - } else { - fd = openat (dirfd, path, O_WRONLY | O_TRUNC | O_CLOEXEC); - if (fd == -1) { - errsv = errno; - if (errsv == ENOENT) { - _LOGD ("sysctl: failed to openat '%s': (%d) %s", - pathid, errsv, nm_strerror_native (errsv)); - } else { - _LOGE ("sysctl: failed to openat '%s': (%d) %s", - pathid, errsv, nm_strerror_native (errsv)); - } - errno = errsv; - return FALSE; - } - } - - _log_dbg_sysctl_set (platform, pathid, dirfd, path, value); - - /* Most sysfs and sysctl options don't care about a trailing LF, while some - * (like infiniband) do. So always add the LF. Also, neither sysfs nor - * sysctl support partial writes so the LF must be added to the string we're - * about to write. - */ - len = strlen (value) + 1; - nm_assert (len > 0); - if (len > 512) - actual = actual_free = g_malloc (len + 1); - else - actual = g_alloca (len + 1); - memcpy (actual, value, len - 1); - actual[len - 1] = '\n'; - actual[len] = '\0'; - - /* Try to write the entire value three times if a partial write occurs */ - errsv = 0; - for (tries = 0, nwrote = 0; tries < 3 && nwrote < len - 1; tries++) { - nwrote = write (fd, actual, len); - if (nwrote == -1) { - errsv = errno; - if (errsv == EINTR) { - _LOGD ("sysctl: interrupted, will try again"); - continue; - } - break; - } - } - if (nwrote == -1) { - NMLogLevel level = LOGL_ERR; - - if (errsv == EEXIST) { - level = LOGL_DEBUG; - } else if ( errsv == EINVAL - && nm_utils_sysctl_ip_conf_is_path (AF_INET6, path, NULL, "mtu")) { - /* setting the MTU can fail under regular conditions. Suppress - * logging a warning. */ - level = LOGL_DEBUG; - } - - _NMLOG (level, "sysctl: failed to set '%s' to '%s': (%d) %s", - path, value, errsv, nm_strerror_native (errsv)); - } else if (nwrote < len - 1) { - _LOGE ("sysctl: failed to set '%s' to '%s' after three attempts", - path, value); - } - - if (nwrote < len - 1) { - if (nm_close (fd) != 0) { - if (errsv != 0) - errno = errsv; - } else if (errsv != 0) - errno = errsv; - else - errno = EIO; - return FALSE; - } - if (nm_close (fd) != 0) { - /* errno is already properly set. */ - return FALSE; - } - - /* success. errno is undefined (no need to set). */ - return TRUE; +sysctl_set_internal(NMPlatform *platform, + const char *pathid, + int dirfd, + const char *path, + const char *value) +{ + int fd, tries; + gssize nwrote; + gssize len; + char * actual; + gs_free char *actual_free = NULL; + int errsv; + + if (dirfd < 0) { + pathid = path; + + fd = open(path, O_WRONLY | O_TRUNC | O_CLOEXEC); + if (fd == -1) { + errsv = errno; + if (errsv == ENOENT) { + _LOGD("sysctl: failed to open '%s': (%d) %s", + pathid, + errsv, + nm_strerror_native(errsv)); + } else { + _LOGE("sysctl: failed to open '%s': (%d) %s", + pathid, + errsv, + nm_strerror_native(errsv)); + } + errno = errsv; + return FALSE; + } + } else { + fd = openat(dirfd, path, O_WRONLY | O_TRUNC | O_CLOEXEC); + if (fd == -1) { + errsv = errno; + if (errsv == ENOENT) { + _LOGD("sysctl: failed to openat '%s': (%d) %s", + pathid, + errsv, + nm_strerror_native(errsv)); + } else { + _LOGE("sysctl: failed to openat '%s': (%d) %s", + pathid, + errsv, + nm_strerror_native(errsv)); + } + errno = errsv; + return FALSE; + } + } + + _log_dbg_sysctl_set(platform, pathid, dirfd, path, value); + + /* Most sysfs and sysctl options don't care about a trailing LF, while some + * (like infiniband) do. So always add the LF. Also, neither sysfs nor + * sysctl support partial writes so the LF must be added to the string we're + * about to write. + */ + len = strlen(value) + 1; + nm_assert(len > 0); + if (len > 512) + actual = actual_free = g_malloc(len + 1); + else + actual = g_alloca(len + 1); + memcpy(actual, value, len - 1); + actual[len - 1] = '\n'; + actual[len] = '\0'; + + /* Try to write the entire value three times if a partial write occurs */ + errsv = 0; + for (tries = 0, nwrote = 0; tries < 3 && nwrote < len - 1; tries++) { + nwrote = write(fd, actual, len); + if (nwrote == -1) { + errsv = errno; + if (errsv == EINTR) { + _LOGD("sysctl: interrupted, will try again"); + continue; + } + break; + } + } + if (nwrote == -1) { + NMLogLevel level = LOGL_ERR; + + if (errsv == EEXIST) { + level = LOGL_DEBUG; + } else if (errsv == EINVAL + && nm_utils_sysctl_ip_conf_is_path(AF_INET6, path, NULL, "mtu")) { + /* setting the MTU can fail under regular conditions. Suppress + * logging a warning. */ + level = LOGL_DEBUG; + } + + _NMLOG(level, + "sysctl: failed to set '%s' to '%s': (%d) %s", + path, + value, + errsv, + nm_strerror_native(errsv)); + } else if (nwrote < len - 1) { + _LOGE("sysctl: failed to set '%s' to '%s' after three attempts", path, value); + } + + if (nwrote < len - 1) { + if (nm_close(fd) != 0) { + if (errsv != 0) + errno = errsv; + } else if (errsv != 0) + errno = errsv; + else + errno = EIO; + return FALSE; + } + if (nm_close(fd) != 0) { + /* errno is already properly set. */ + return FALSE; + } + + /* success. errno is undefined (no need to set). */ + return TRUE; } #undef NM_THREAD_SAFE_ON_MAIN_THREAD @@ -5071,1131 +5273,1196 @@ sysctl_set_internal (NMPlatform *platform, /*****************************************************************************/ static gboolean -sysctl_set (NMPlatform *platform, - const char *pathid, - int dirfd, - const char *path, - const char *value) +sysctl_set(NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value) { - nm_auto_pop_netns NMPNetns *netns = NULL; + nm_auto_pop_netns NMPNetns *netns = NULL; - g_return_val_if_fail (path, FALSE); - g_return_val_if_fail (value, FALSE); + g_return_val_if_fail(path, FALSE); + g_return_val_if_fail(value, FALSE); - ASSERT_SYSCTL_ARGS (pathid, dirfd, path); + ASSERT_SYSCTL_ARGS(pathid, dirfd, path); - if ( dirfd < 0 - && !nm_platform_netns_push (platform, &netns)) { - errno = ENETDOWN; - return FALSE; - } + if (dirfd < 0 && !nm_platform_netns_push(platform, &netns)) { + errno = ENETDOWN; + return FALSE; + } - return sysctl_set_internal (platform, pathid, dirfd, path, value); + return sysctl_set_internal(platform, pathid, dirfd, path, value); } typedef struct { - NMPlatform *platform; - char *pathid; - int dirfd; - char *path; - char **values; - GCancellable *cancellable; - NMPlatformAsyncCallback callback; - gpointer callback_data; + NMPlatform * platform; + char * pathid; + int dirfd; + char * path; + char ** values; + GCancellable * cancellable; + NMPlatformAsyncCallback callback; + gpointer callback_data; } SysctlAsyncInfo; static void -sysctl_async_info_free (SysctlAsyncInfo *info) +sysctl_async_info_free(SysctlAsyncInfo *info) { - g_object_unref (info->platform); - g_free (info->pathid); - if (info->dirfd >= 0) - nm_close (info->dirfd); - g_free (info->path); - g_strfreev (info->values); - g_object_unref (info->cancellable); - g_slice_free (SysctlAsyncInfo, info); + g_object_unref(info->platform); + g_free(info->pathid); + if (info->dirfd >= 0) + nm_close(info->dirfd); + g_free(info->path); + g_strfreev(info->values); + g_object_unref(info->cancellable); + g_slice_free(SysctlAsyncInfo, info); } static void -sysctl_async_cb (GObject *object, - GAsyncResult *res, - gpointer user_data) +sysctl_async_cb(GObject *object, GAsyncResult *res, gpointer user_data) { - NMPlatform *platform; - GTask *task = G_TASK (res); - SysctlAsyncInfo *info; - gs_free_error GError *error = NULL; - gs_free char *values_str = NULL; + NMPlatform * platform; + GTask * task = G_TASK(res); + SysctlAsyncInfo *info; + gs_free_error GError *error = NULL; + gs_free char * values_str = NULL; - info = g_task_get_task_data (task); + info = g_task_get_task_data(task); - if (g_task_propagate_boolean (task, &error)) { - platform = info->platform; - _LOGD ("sysctl: successfully set-async '%s' to values '%s'", - info->pathid ?: info->path, - (values_str = g_strjoinv (", ", info->values))); - } + if (g_task_propagate_boolean(task, &error)) { + platform = info->platform; + _LOGD("sysctl: successfully set-async '%s' to values '%s'", + info->pathid ?: info->path, + (values_str = g_strjoinv(", ", info->values))); + } - if (info->callback) - info->callback (error, info->callback_data); + if (info->callback) + info->callback(error, info->callback_data); } static void -sysctl_async_thread_fn (GTask *task, - gpointer source_object, - gpointer task_data, - GCancellable *cancellable) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - SysctlAsyncInfo *info = task_data; - GError *error = NULL; - char **value; - - if (g_task_return_error_if_cancelled (task)) - return; - - if ( info->dirfd < 0 - && !nm_platform_netns_push (info->platform, &netns)) { - g_set_error_literal (&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "sysctl: failed changing namespace"); - g_task_return_error (task, error); - return; - } - - for (value = info->values; *value; value++) { - if (!sysctl_set_internal (info->platform, - info->pathid, - info->dirfd, - info->path, - *value)) { - g_set_error (&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "sysctl: failed setting '%s' to value '%s': %s", - info->pathid ?: info->path, - *value, - nm_strerror_native (errno)); - g_task_return_error (task, error); - return; - } - if (g_task_return_error_if_cancelled (task)) - return; - } - g_task_return_boolean (task, TRUE); +sysctl_async_thread_fn(GTask * task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + SysctlAsyncInfo * info = task_data; + GError * error = NULL; + char ** value; + + if (g_task_return_error_if_cancelled(task)) + return; + + if (info->dirfd < 0 && !nm_platform_netns_push(info->platform, &netns)) { + g_set_error_literal(&error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "sysctl: failed changing namespace"); + g_task_return_error(task, error); + return; + } + + for (value = info->values; *value; value++) { + if (!sysctl_set_internal(info->platform, info->pathid, info->dirfd, info->path, *value)) { + g_set_error(&error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "sysctl: failed setting '%s' to value '%s': %s", + info->pathid ?: info->path, + *value, + nm_strerror_native(errno)); + g_task_return_error(task, error); + return; + } + if (g_task_return_error_if_cancelled(task)) + return; + } + g_task_return_boolean(task, TRUE); } static void -sysctl_set_async_return_idle (gpointer user_data, - GCancellable *cancellable) +sysctl_set_async_return_idle(gpointer user_data, GCancellable *cancellable) { - gs_unref_object NMPlatform *platform = NULL; - gs_free_error GError *cancelled_error = NULL; - gs_free_error GError *error = NULL; - NMPlatformAsyncCallback callback; - gpointer callback_data; + gs_unref_object NMPlatform *platform = NULL; + gs_free_error GError *cancelled_error = NULL; + gs_free_error GError * error = NULL; + NMPlatformAsyncCallback callback; + gpointer callback_data; - nm_utils_user_data_unpack (user_data, &platform, &callback, &callback_data, &error); - g_cancellable_set_error_if_cancelled (cancellable, &cancelled_error); - callback (cancelled_error ?: error, callback_data); + nm_utils_user_data_unpack(user_data, &platform, &callback, &callback_data, &error); + g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); + callback(cancelled_error ?: error, callback_data); } static void -sysctl_set_async (NMPlatform *platform, - const char *pathid, - int dirfd, - const char *path, - const char *const *values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable *cancellable) -{ - SysctlAsyncInfo *info; - GTask *task; - int dirfd_dup, errsv; - gpointer packed; - GError *error = NULL; - - g_return_if_fail (platform); - g_return_if_fail (path); - g_return_if_fail (values && values[0]); - g_return_if_fail (cancellable); - g_return_if_fail (!data || callback); - - ASSERT_SYSCTL_ARGS (pathid, dirfd, path); - - if (dirfd >= 0) { - dirfd_dup = fcntl (dirfd, F_DUPFD_CLOEXEC, 0); - if (dirfd_dup < 0) { - if (!callback) - return; - errsv = errno; - g_set_error (&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "sysctl: failure duplicating directory fd: %s", - nm_strerror_native (errsv)); - packed = nm_utils_user_data_pack (g_object_ref (platform), - callback, - data, - error); - nm_utils_invoke_on_idle (cancellable, - sysctl_set_async_return_idle, - packed); - return; - } - } else - dirfd_dup = -1; - - info = g_slice_new0 (SysctlAsyncInfo); - info->platform = g_object_ref (platform); - info->pathid = g_strdup (pathid); - info->dirfd = dirfd_dup; - info->path = g_strdup (path); - info->values = g_strdupv ((char **) values); - info->callback = callback; - info->callback_data = data; - info->cancellable = g_object_ref (cancellable); - - task = g_task_new (platform, cancellable, sysctl_async_cb, NULL); - g_task_set_task_data (task, info, (GDestroyNotify) sysctl_async_info_free); - g_task_set_return_on_cancel (task, FALSE); - g_task_run_in_thread (task, sysctl_async_thread_fn); - g_object_unref (task); +sysctl_set_async(NMPlatform * platform, + const char * pathid, + int dirfd, + const char * path, + const char *const * values, + NMPlatformAsyncCallback callback, + gpointer data, + GCancellable * cancellable) +{ + SysctlAsyncInfo *info; + GTask * task; + int dirfd_dup, errsv; + gpointer packed; + GError * error = NULL; + + g_return_if_fail(platform); + g_return_if_fail(path); + g_return_if_fail(values && values[0]); + g_return_if_fail(cancellable); + g_return_if_fail(!data || callback); + + ASSERT_SYSCTL_ARGS(pathid, dirfd, path); + + if (dirfd >= 0) { + dirfd_dup = fcntl(dirfd, F_DUPFD_CLOEXEC, 0); + if (dirfd_dup < 0) { + if (!callback) + return; + errsv = errno; + g_set_error(&error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "sysctl: failure duplicating directory fd: %s", + nm_strerror_native(errsv)); + packed = nm_utils_user_data_pack(g_object_ref(platform), callback, data, error); + nm_utils_invoke_on_idle(cancellable, sysctl_set_async_return_idle, packed); + return; + } + } else + dirfd_dup = -1; + + info = g_slice_new0(SysctlAsyncInfo); + info->platform = g_object_ref(platform); + info->pathid = g_strdup(pathid); + info->dirfd = dirfd_dup; + info->path = g_strdup(path); + info->values = g_strdupv((char **) values); + info->callback = callback; + info->callback_data = data; + info->cancellable = g_object_ref(cancellable); + + task = g_task_new(platform, cancellable, sysctl_async_cb, NULL); + g_task_set_task_data(task, info, (GDestroyNotify) sysctl_async_info_free); + g_task_set_return_on_cancel(task, FALSE); + g_task_run_in_thread(task, sysctl_async_thread_fn); + g_object_unref(task); } static GSList *sysctl_clear_cache_list; void -_nm_logging_clear_platform_logging_cache (void) +_nm_logging_clear_platform_logging_cache(void) { - while (sysctl_clear_cache_list) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (sysctl_clear_cache_list->data); + while (sysctl_clear_cache_list) { + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(sysctl_clear_cache_list->data); - sysctl_clear_cache_list = g_slist_delete_link (sysctl_clear_cache_list, sysctl_clear_cache_list); + sysctl_clear_cache_list = + g_slist_delete_link(sysctl_clear_cache_list, sysctl_clear_cache_list); - g_hash_table_destroy (priv->sysctl_get_prev_values); - priv->sysctl_get_prev_values = NULL; - } + g_hash_table_destroy(priv->sysctl_get_prev_values); + priv->sysctl_get_prev_values = NULL; + } } typedef struct { - const char *path; - CList lst; - char *value; - char path_data[]; + const char *path; + CList lst; + char * value; + char path_data[]; } SysctlCacheEntry; static void -sysctl_cache_entry_free (SysctlCacheEntry *entry) +sysctl_cache_entry_free(SysctlCacheEntry *entry) { - c_list_unlink_stale (&entry->lst); - g_free (entry->value); - g_free (entry); + c_list_unlink_stale(&entry->lst); + g_free(entry->value); + g_free(entry); } static void -_log_dbg_sysctl_get_impl (NMPlatform *platform, const char *pathid, const char *contents) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - SysctlCacheEntry *entry = NULL; - - if (!priv->sysctl_get_prev_values) { - sysctl_clear_cache_list = g_slist_prepend (sysctl_clear_cache_list, platform); - c_list_init (&priv->sysctl_list); - priv->sysctl_get_prev_values = g_hash_table_new_full (nm_pstr_hash, - nm_pstr_equal, - (GDestroyNotify) sysctl_cache_entry_free, - NULL); - } else - entry = g_hash_table_lookup (priv->sysctl_get_prev_values, &pathid); - - if (entry) { - if (!nm_streq (entry->value, contents)) { - gs_free char *contents_escaped = g_strescape (contents, NULL); - gs_free char *prev_value_escaped = g_strescape (entry->value, NULL); - - _LOGD ("sysctl: reading '%s': '%s' (changed from '%s' on last read)", pathid, contents_escaped, prev_value_escaped); - g_free (entry->value); - entry->value = g_strdup (contents); - } - nm_c_list_move_front (&priv->sysctl_list, &entry->lst); - } else { - gs_free char *contents_escaped = g_strescape (contents, NULL); - SysctlCacheEntry *old; - size_t len; - - len = strlen (pathid); - entry = g_malloc (sizeof (SysctlCacheEntry) + len + 1); - entry->value = g_strdup (contents); - entry->path = entry->path_data; - memcpy (entry->path_data, pathid, len + 1); - - /* Remove oldest entry when the cache becomes too big */ - if (g_hash_table_size (priv->sysctl_get_prev_values) > 1000) { - old = c_list_last_entry (&priv->sysctl_list, SysctlCacheEntry, lst); - g_hash_table_remove (priv->sysctl_get_prev_values, old); - } - - _LOGD ("sysctl: reading '%s': '%s'", pathid, contents_escaped); - - g_hash_table_add (priv->sysctl_get_prev_values, entry); - c_list_link_front (&priv->sysctl_list, &entry->lst); - } -} - -#define _log_dbg_sysctl_get(platform, pathid, contents) \ - G_STMT_START { \ - if (_LOGD_ENABLED ()) \ - _log_dbg_sysctl_get_impl (platform, pathid, contents); \ - } G_STMT_END +_log_dbg_sysctl_get_impl(NMPlatform *platform, const char *pathid, const char *contents) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + SysctlCacheEntry * entry = NULL; + + if (!priv->sysctl_get_prev_values) { + sysctl_clear_cache_list = g_slist_prepend(sysctl_clear_cache_list, platform); + c_list_init(&priv->sysctl_list); + priv->sysctl_get_prev_values = + g_hash_table_new_full(nm_pstr_hash, + nm_pstr_equal, + (GDestroyNotify) sysctl_cache_entry_free, + NULL); + } else + entry = g_hash_table_lookup(priv->sysctl_get_prev_values, &pathid); + + if (entry) { + if (!nm_streq(entry->value, contents)) { + gs_free char *contents_escaped = g_strescape(contents, NULL); + gs_free char *prev_value_escaped = g_strescape(entry->value, NULL); + + _LOGD("sysctl: reading '%s': '%s' (changed from '%s' on last read)", + pathid, + contents_escaped, + prev_value_escaped); + g_free(entry->value); + entry->value = g_strdup(contents); + } + nm_c_list_move_front(&priv->sysctl_list, &entry->lst); + } else { + gs_free char * contents_escaped = g_strescape(contents, NULL); + SysctlCacheEntry *old; + size_t len; + + len = strlen(pathid); + entry = g_malloc(sizeof(SysctlCacheEntry) + len + 1); + entry->value = g_strdup(contents); + entry->path = entry->path_data; + memcpy(entry->path_data, pathid, len + 1); + + /* Remove oldest entry when the cache becomes too big */ + if (g_hash_table_size(priv->sysctl_get_prev_values) > 1000) { + old = c_list_last_entry(&priv->sysctl_list, SysctlCacheEntry, lst); + g_hash_table_remove(priv->sysctl_get_prev_values, old); + } + + _LOGD("sysctl: reading '%s': '%s'", pathid, contents_escaped); + + g_hash_table_add(priv->sysctl_get_prev_values, entry); + c_list_link_front(&priv->sysctl_list, &entry->lst); + } +} + +#define _log_dbg_sysctl_get(platform, pathid, contents) \ + G_STMT_START \ + { \ + if (_LOGD_ENABLED()) \ + _log_dbg_sysctl_get_impl(platform, pathid, contents); \ + } \ + G_STMT_END static char * -sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *path) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - GError *error = NULL; - gs_free char *contents = NULL; - - ASSERT_SYSCTL_ARGS (pathid, dirfd, path); - - if (dirfd < 0) { - if (!nm_platform_netns_push (platform, &netns)) { - errno = EBUSY; - return NULL; - } - pathid = path; - } - - if (!nm_utils_file_get_contents (dirfd, - path, - 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &contents, - NULL, - NULL, - &error)) { - NMLogLevel log_level = LOGL_ERR; - int errsv = EBUSY; - - if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { - errsv = ENOENT; - log_level = LOGL_DEBUG; - } else if ( g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NODEV) - || g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_FAILED)) { - /* We assume FAILED means EOPNOTSUP and don't log a error message. */ - log_level = LOGL_DEBUG; - } - - _NMLOG (log_level, "error reading %s: %s", pathid, error->message); - g_clear_error (&error); - errno = errsv; - return NULL; - } - - g_strstrip (contents); - - _log_dbg_sysctl_get (platform, pathid, contents); - - /* errno is left undefined (as we don't return NULL). */ - return g_steal_pointer (&contents); +sysctl_get(NMPlatform *platform, const char *pathid, int dirfd, const char *path) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + GError * error = NULL; + gs_free char * contents = NULL; + + ASSERT_SYSCTL_ARGS(pathid, dirfd, path); + + if (dirfd < 0) { + if (!nm_platform_netns_push(platform, &netns)) { + errno = EBUSY; + return NULL; + } + pathid = path; + } + + if (!nm_utils_file_get_contents(dirfd, + path, + 1 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &contents, + NULL, + NULL, + &error)) { + NMLogLevel log_level = LOGL_ERR; + int errsv = EBUSY; + + if (g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { + errsv = ENOENT; + log_level = LOGL_DEBUG; + } else if (g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NODEV) + || g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_FAILED)) { + /* We assume FAILED means EOPNOTSUP and don't log a error message. */ + log_level = LOGL_DEBUG; + } + + _NMLOG(log_level, "error reading %s: %s", pathid, error->message); + g_clear_error(&error); + errno = errsv; + return NULL; + } + + g_strstrip(contents); + + _log_dbg_sysctl_get(platform, pathid, contents); + + /* errno is left undefined (as we don't return NULL). */ + return g_steal_pointer(&contents); } /*****************************************************************************/ static void -process_events (NMPlatform *platform) +process_events(NMPlatform *platform) { - delayed_action_handle_all (platform, TRUE); + delayed_action_handle_all(platform, TRUE); } /*****************************************************************************/ static const RefreshAllInfo * -refresh_all_type_get_info (RefreshAllType refresh_all_type) -{ - static const RefreshAllInfo infos[] = { -#define R(_refresh_all_type, _obj_type, _addr_family) [_refresh_all_type] = { .obj_type = _obj_type, .addr_family = _addr_family, } - R (REFRESH_ALL_TYPE_LINKS, NMP_OBJECT_TYPE_LINK, AF_UNSPEC), - R (REFRESH_ALL_TYPE_IP4_ADDRESSES, NMP_OBJECT_TYPE_IP4_ADDRESS, AF_UNSPEC), - R (REFRESH_ALL_TYPE_IP6_ADDRESSES, NMP_OBJECT_TYPE_IP6_ADDRESS, AF_UNSPEC), - R (REFRESH_ALL_TYPE_IP4_ROUTES, NMP_OBJECT_TYPE_IP4_ROUTE, AF_UNSPEC), - R (REFRESH_ALL_TYPE_IP6_ROUTES, NMP_OBJECT_TYPE_IP6_ROUTE, AF_UNSPEC), - R (REFRESH_ALL_TYPE_ROUTING_RULES_IP4, NMP_OBJECT_TYPE_ROUTING_RULE, AF_INET), - R (REFRESH_ALL_TYPE_ROUTING_RULES_IP6, NMP_OBJECT_TYPE_ROUTING_RULE, AF_INET6), - R (REFRESH_ALL_TYPE_QDISCS, NMP_OBJECT_TYPE_QDISC, AF_UNSPEC), - R (REFRESH_ALL_TYPE_TFILTERS, NMP_OBJECT_TYPE_TFILTER, AF_UNSPEC), +refresh_all_type_get_info(RefreshAllType refresh_all_type) +{ + static const RefreshAllInfo infos[] = { +#define R(_refresh_all_type, _obj_type, _addr_family) \ + [_refresh_all_type] = { \ + .obj_type = _obj_type, \ + .addr_family = _addr_family, \ + } + R(REFRESH_ALL_TYPE_LINKS, NMP_OBJECT_TYPE_LINK, AF_UNSPEC), + R(REFRESH_ALL_TYPE_IP4_ADDRESSES, NMP_OBJECT_TYPE_IP4_ADDRESS, AF_UNSPEC), + R(REFRESH_ALL_TYPE_IP6_ADDRESSES, NMP_OBJECT_TYPE_IP6_ADDRESS, AF_UNSPEC), + R(REFRESH_ALL_TYPE_IP4_ROUTES, NMP_OBJECT_TYPE_IP4_ROUTE, AF_UNSPEC), + R(REFRESH_ALL_TYPE_IP6_ROUTES, NMP_OBJECT_TYPE_IP6_ROUTE, AF_UNSPEC), + R(REFRESH_ALL_TYPE_ROUTING_RULES_IP4, NMP_OBJECT_TYPE_ROUTING_RULE, AF_INET), + R(REFRESH_ALL_TYPE_ROUTING_RULES_IP6, NMP_OBJECT_TYPE_ROUTING_RULE, AF_INET6), + R(REFRESH_ALL_TYPE_QDISCS, NMP_OBJECT_TYPE_QDISC, AF_UNSPEC), + R(REFRESH_ALL_TYPE_TFILTERS, NMP_OBJECT_TYPE_TFILTER, AF_UNSPEC), #undef R - }; - - nm_assert (_NM_INT_NOT_NEGATIVE (refresh_all_type)); - nm_assert (refresh_all_type < G_N_ELEMENTS (infos)); - nm_assert (nmp_class_from_type (infos[refresh_all_type].obj_type)); - - return &infos[refresh_all_type]; -} - -static -NM_UTILS_LOOKUP_DEFINE (delayed_action_type_to_refresh_all_type, DelayedActionType, RefreshAllType, - NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (0), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, REFRESH_ALL_TYPE_LINKS), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, REFRESH_ALL_TYPE_IP4_ADDRESSES), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, REFRESH_ALL_TYPE_IP6_ADDRESSES), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, REFRESH_ALL_TYPE_IP4_ROUTES), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, REFRESH_ALL_TYPE_IP6_ROUTES), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4, REFRESH_ALL_TYPE_ROUTING_RULES_IP4), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, REFRESH_ALL_TYPE_ROUTING_RULES_IP6), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS, REFRESH_ALL_TYPE_QDISCS), - NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, REFRESH_ALL_TYPE_TFILTERS), - NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (), -); + }; + + nm_assert(_NM_INT_NOT_NEGATIVE(refresh_all_type)); + nm_assert(refresh_all_type < G_N_ELEMENTS(infos)); + nm_assert(nmp_class_from_type(infos[refresh_all_type].obj_type)); + + return &infos[refresh_all_type]; +} + +static NM_UTILS_LOOKUP_DEFINE( + delayed_action_type_to_refresh_all_type, + DelayedActionType, + RefreshAllType, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(0), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, REFRESH_ALL_TYPE_LINKS), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, + REFRESH_ALL_TYPE_IP4_ADDRESSES), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, + REFRESH_ALL_TYPE_IP6_ADDRESSES), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, REFRESH_ALL_TYPE_IP4_ROUTES), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, REFRESH_ALL_TYPE_IP6_ROUTES), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4, + REFRESH_ALL_TYPE_ROUTING_RULES_IP4), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, + REFRESH_ALL_TYPE_ROUTING_RULES_IP6), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS, REFRESH_ALL_TYPE_QDISCS), + NM_UTILS_LOOKUP_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, REFRESH_ALL_TYPE_TFILTERS), + NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER(), ); static DelayedActionType -delayed_action_type_from_refresh_all_type (RefreshAllType refresh_all_type) +delayed_action_type_from_refresh_all_type(RefreshAllType refresh_all_type) { - DelayedActionType t; + DelayedActionType t; - nm_assert (refresh_all_type_get_info (refresh_all_type)); + nm_assert(refresh_all_type_get_info(refresh_all_type)); - t = (((DelayedActionType) 1) << refresh_all_type); + t = (((DelayedActionType) 1) << refresh_all_type); - nm_assert (refresh_all_type == delayed_action_type_to_refresh_all_type (t)); + nm_assert(refresh_all_type == delayed_action_type_to_refresh_all_type(t)); - return t; + return t; } static RefreshAllType -refresh_all_type_from_needle_object (const NMPObject *obj_needle) -{ - switch (NMP_OBJECT_GET_TYPE (obj_needle)) { - case NMP_OBJECT_TYPE_LINK: return REFRESH_ALL_TYPE_LINKS; - case NMP_OBJECT_TYPE_IP4_ADDRESS: return REFRESH_ALL_TYPE_IP4_ADDRESSES; - case NMP_OBJECT_TYPE_IP6_ADDRESS: return REFRESH_ALL_TYPE_IP6_ADDRESSES; - case NMP_OBJECT_TYPE_IP4_ROUTE: return REFRESH_ALL_TYPE_IP4_ROUTES; - case NMP_OBJECT_TYPE_IP6_ROUTE: return REFRESH_ALL_TYPE_IP6_ROUTES; - case NMP_OBJECT_TYPE_QDISC: return REFRESH_ALL_TYPE_QDISCS; - case NMP_OBJECT_TYPE_TFILTER: return REFRESH_ALL_TYPE_TFILTERS; - case NMP_OBJECT_TYPE_ROUTING_RULE: - switch (NMP_OBJECT_CAST_ROUTING_RULE (obj_needle)->addr_family) { - case AF_INET: return REFRESH_ALL_TYPE_ROUTING_RULES_IP4; - case AF_INET6: return REFRESH_ALL_TYPE_ROUTING_RULES_IP6; - } - nm_assert_not_reached (); - return 0; - default: - nm_assert_not_reached (); - return 0; - } +refresh_all_type_from_needle_object(const NMPObject *obj_needle) +{ + switch (NMP_OBJECT_GET_TYPE(obj_needle)) { + case NMP_OBJECT_TYPE_LINK: + return REFRESH_ALL_TYPE_LINKS; + case NMP_OBJECT_TYPE_IP4_ADDRESS: + return REFRESH_ALL_TYPE_IP4_ADDRESSES; + case NMP_OBJECT_TYPE_IP6_ADDRESS: + return REFRESH_ALL_TYPE_IP6_ADDRESSES; + case NMP_OBJECT_TYPE_IP4_ROUTE: + return REFRESH_ALL_TYPE_IP4_ROUTES; + case NMP_OBJECT_TYPE_IP6_ROUTE: + return REFRESH_ALL_TYPE_IP6_ROUTES; + case NMP_OBJECT_TYPE_QDISC: + return REFRESH_ALL_TYPE_QDISCS; + case NMP_OBJECT_TYPE_TFILTER: + return REFRESH_ALL_TYPE_TFILTERS; + case NMP_OBJECT_TYPE_ROUTING_RULE: + switch (NMP_OBJECT_CAST_ROUTING_RULE(obj_needle)->addr_family) { + case AF_INET: + return REFRESH_ALL_TYPE_ROUTING_RULES_IP4; + case AF_INET6: + return REFRESH_ALL_TYPE_ROUTING_RULES_IP6; + } + nm_assert_not_reached(); + return 0; + default: + nm_assert_not_reached(); + return 0; + } } static const NMPLookup * -refresh_all_type_init_lookup (RefreshAllType refresh_all_type, - NMPLookup *lookup) +refresh_all_type_init_lookup(RefreshAllType refresh_all_type, NMPLookup *lookup) { - const RefreshAllInfo *refresh_all_info; + const RefreshAllInfo *refresh_all_info; - nm_assert (lookup); + nm_assert(lookup); - refresh_all_info = refresh_all_type_get_info (refresh_all_type); + refresh_all_info = refresh_all_type_get_info(refresh_all_type); - nm_assert (refresh_all_info); + nm_assert(refresh_all_info); - if (NM_IN_SET (refresh_all_info->obj_type, NMP_OBJECT_TYPE_ROUTING_RULE)) { - return nmp_lookup_init_object_by_addr_family (lookup, - refresh_all_info->obj_type, - refresh_all_info->addr_family); - } + if (NM_IN_SET(refresh_all_info->obj_type, NMP_OBJECT_TYPE_ROUTING_RULE)) { + return nmp_lookup_init_object_by_addr_family(lookup, + refresh_all_info->obj_type, + refresh_all_info->addr_family); + } - /* not yet implemented. */ - nm_assert (refresh_all_info->addr_family == AF_UNSPEC); + /* not yet implemented. */ + nm_assert(refresh_all_info->addr_family == AF_UNSPEC); - return nmp_lookup_init_obj_type (lookup, - refresh_all_info->obj_type); + return nmp_lookup_init_obj_type(lookup, refresh_all_info->obj_type); } static DelayedActionType -delayed_action_refresh_from_needle_object (const NMPObject *obj_needle) -{ - return delayed_action_type_from_refresh_all_type (refresh_all_type_from_needle_object (obj_needle)); -} - -static -NM_UTILS_LOOKUP_STR_DEFINE (delayed_action_to_string, DelayedActionType, - NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, "refresh-all-links"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, "refresh-all-ip4-addresses"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, "refresh-all-ip6-addresses"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, "refresh-all-ip4-routes"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, "refresh-all-ip6-routes"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4, "refresh-all-routing-rules-ip4"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, "refresh-all-routing-rules-ip6"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS, "refresh-all-qdiscs"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, "refresh-all-tfilters"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_LINK, "refresh-link"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_MASTER_CONNECTED, "master-connected"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_READ_NETLINK, "read-netlink"), - NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, "wait-for-nl-response"), - NM_UTILS_LOOKUP_ITEM_IGNORE (DELAYED_ACTION_TYPE_NONE), - NM_UTILS_LOOKUP_ITEM_IGNORE (DELAYED_ACTION_TYPE_REFRESH_ALL), - NM_UTILS_LOOKUP_ITEM_IGNORE (DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL), - NM_UTILS_LOOKUP_ITEM_IGNORE (__DELAYED_ACTION_TYPE_MAX), -); +delayed_action_refresh_from_needle_object(const NMPObject *obj_needle) +{ + return delayed_action_type_from_refresh_all_type( + refresh_all_type_from_needle_object(obj_needle)); +} + +static NM_UTILS_LOOKUP_STR_DEFINE( + delayed_action_to_string, + DelayedActionType, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS, "refresh-all-links"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, + "refresh-all-ip4-addresses"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, + "refresh-all-ip6-addresses"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES, "refresh-all-ip4-routes"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, "refresh-all-ip6-routes"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP4, + "refresh-all-routing-rules-ip4"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_IP6, + "refresh-all-routing-rules-ip6"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS, "refresh-all-qdiscs"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, "refresh-all-tfilters"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_REFRESH_LINK, "refresh-link"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_MASTER_CONNECTED, "master-connected"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_READ_NETLINK, "read-netlink"), + NM_UTILS_LOOKUP_STR_ITEM(DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, "wait-for-nl-response"), + NM_UTILS_LOOKUP_ITEM_IGNORE(DELAYED_ACTION_TYPE_NONE), + NM_UTILS_LOOKUP_ITEM_IGNORE(DELAYED_ACTION_TYPE_REFRESH_ALL), + NM_UTILS_LOOKUP_ITEM_IGNORE(DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL), + NM_UTILS_LOOKUP_ITEM_IGNORE(__DELAYED_ACTION_TYPE_MAX), ); static const char * -delayed_action_to_string_full (DelayedActionType action_type, gpointer user_data, char *buf, gsize buf_size) -{ - char *buf0 = buf; - const DelayedActionWaitForNlResponseData *data; - - nm_utils_strbuf_append_str (&buf, &buf_size, delayed_action_to_string (action_type)); - switch (action_type) { - case DELAYED_ACTION_TYPE_MASTER_CONNECTED: - nm_utils_strbuf_append (&buf, &buf_size, " (master-ifindex %d)", GPOINTER_TO_INT (user_data)); - break; - case DELAYED_ACTION_TYPE_REFRESH_LINK: - nm_utils_strbuf_append (&buf, &buf_size, " (ifindex %d)", GPOINTER_TO_INT (user_data)); - break; - case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE: - data = user_data; - - if (data) { - gint64 timeout = data->timeout_abs_ns - nm_utils_get_monotonic_timestamp_nsec (); - char b[255]; - - nm_utils_strbuf_append (&buf, &buf_size, " (seq %u, timeout in %s%"G_GINT64_FORMAT".%09"G_GINT64_FORMAT", response-type %d%s%s)", - data->seq_number, - timeout < 0 ? "-" : "", - (timeout < 0 ? -timeout : timeout) / NM_UTILS_NSEC_PER_SEC, - (timeout < 0 ? -timeout : timeout) % NM_UTILS_NSEC_PER_SEC, - (int) data->response_type, - data->seq_result ? ", " : "", - data->seq_result ? wait_for_nl_response_to_string (data->seq_result, NULL, b, sizeof (b)) : ""); - } else - nm_utils_strbuf_append_str (&buf, &buf_size, " (any)"); - break; - default: - nm_assert (!user_data); - break; - } - return buf0; -} - -#define _LOGt_delayed_action(action_type, user_data, operation) \ - G_STMT_START { \ - char _buf[255]; \ - \ - _LOGt ("delayed-action: %s %s", \ - ""operation, \ - delayed_action_to_string_full (action_type, user_data, _buf, sizeof (_buf))); \ - } G_STMT_END +delayed_action_to_string_full(DelayedActionType action_type, + gpointer user_data, + char * buf, + gsize buf_size) +{ + char * buf0 = buf; + const DelayedActionWaitForNlResponseData *data; + + nm_utils_strbuf_append_str(&buf, &buf_size, delayed_action_to_string(action_type)); + switch (action_type) { + case DELAYED_ACTION_TYPE_MASTER_CONNECTED: + nm_utils_strbuf_append(&buf, &buf_size, " (master-ifindex %d)", GPOINTER_TO_INT(user_data)); + break; + case DELAYED_ACTION_TYPE_REFRESH_LINK: + nm_utils_strbuf_append(&buf, &buf_size, " (ifindex %d)", GPOINTER_TO_INT(user_data)); + break; + case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE: + data = user_data; + + if (data) { + gint64 timeout = data->timeout_abs_ns - nm_utils_get_monotonic_timestamp_nsec(); + char b[255]; + + nm_utils_strbuf_append( + &buf, + &buf_size, + " (seq %u, timeout in %s%" G_GINT64_FORMAT ".%09" G_GINT64_FORMAT + ", response-type %d%s%s)", + data->seq_number, + timeout < 0 ? "-" : "", + (timeout < 0 ? -timeout : timeout) / NM_UTILS_NSEC_PER_SEC, + (timeout < 0 ? -timeout : timeout) % NM_UTILS_NSEC_PER_SEC, + (int) data->response_type, + data->seq_result ? ", " : "", + data->seq_result + ? wait_for_nl_response_to_string(data->seq_result, NULL, b, sizeof(b)) + : ""); + } else + nm_utils_strbuf_append_str(&buf, &buf_size, " (any)"); + break; + default: + nm_assert(!user_data); + break; + } + return buf0; +} + +#define _LOGt_delayed_action(action_type, user_data, operation) \ + G_STMT_START \ + { \ + char _buf[255]; \ + \ + _LOGt("delayed-action: %s %s", \ + "" operation, \ + delayed_action_to_string_full(action_type, user_data, _buf, sizeof(_buf))); \ + } \ + G_STMT_END /*****************************************************************************/ static gboolean -delayed_action_refresh_all_in_progress (NMPlatform *platform, DelayedActionType action_type) +delayed_action_refresh_all_in_progress(NMPlatform *platform, DelayedActionType action_type) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - RefreshAllType refresh_all_type; + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + RefreshAllType refresh_all_type; - nm_assert (nm_utils_is_power_of_two (action_type)); - nm_assert (NM_FLAGS_ANY (action_type, DELAYED_ACTION_TYPE_REFRESH_ALL)); - nm_assert (!NM_FLAGS_ANY (action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL)); + nm_assert(nm_utils_is_power_of_two(action_type)); + nm_assert(NM_FLAGS_ANY(action_type, DELAYED_ACTION_TYPE_REFRESH_ALL)); + nm_assert(!NM_FLAGS_ANY(action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL)); - if (NM_FLAGS_ANY (priv->delayed_action.flags, action_type)) - return TRUE; + if (NM_FLAGS_ANY(priv->delayed_action.flags, action_type)) + return TRUE; - refresh_all_type = delayed_action_type_to_refresh_all_type (action_type); - return (priv->delayed_action.refresh_all_in_progress[refresh_all_type] > 0); + refresh_all_type = delayed_action_type_to_refresh_all_type(action_type); + return (priv->delayed_action.refresh_all_in_progress[refresh_all_type] > 0); } static void -delayed_action_wait_for_nl_response_complete (NMPlatform *platform, - guint idx, - WaitForNlResponseResult seq_result) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - DelayedActionWaitForNlResponseData *data; - - nm_assert (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); - nm_assert (idx < priv->delayed_action.list_wait_for_nl_response->len); - nm_assert (seq_result); - - data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, idx); - - _LOGt_delayed_action (DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, data, "complete"); - - if (priv->delayed_action.list_wait_for_nl_response->len <= 1) - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE; - if (data->out_seq_result) - *data->out_seq_result = seq_result; - switch (data->response_type) { - case DELAYED_ACTION_RESPONSE_TYPE_VOID: - break; - case DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS: - if (data->response.out_refresh_all_in_progress) { - nm_assert (*data->response.out_refresh_all_in_progress > 0); - *data->response.out_refresh_all_in_progress -= 1; - data->response.out_refresh_all_in_progress = NULL; - } - break; - case DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET: - if (data->response.out_route_get) { - nm_assert (!*data->response.out_route_get); - data->response.out_route_get = NULL; - } - break; - } - - g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx); +delayed_action_wait_for_nl_response_complete(NMPlatform * platform, + guint idx, + WaitForNlResponseResult seq_result) +{ + NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + DelayedActionWaitForNlResponseData *data; + + nm_assert(NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); + nm_assert(idx < priv->delayed_action.list_wait_for_nl_response->len); + nm_assert(seq_result); + + data = &g_array_index(priv->delayed_action.list_wait_for_nl_response, + DelayedActionWaitForNlResponseData, + idx); + + _LOGt_delayed_action(DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, data, "complete"); + + if (priv->delayed_action.list_wait_for_nl_response->len <= 1) + priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE; + if (data->out_seq_result) + *data->out_seq_result = seq_result; + switch (data->response_type) { + case DELAYED_ACTION_RESPONSE_TYPE_VOID: + break; + case DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS: + if (data->response.out_refresh_all_in_progress) { + nm_assert(*data->response.out_refresh_all_in_progress > 0); + *data->response.out_refresh_all_in_progress -= 1; + data->response.out_refresh_all_in_progress = NULL; + } + break; + case DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET: + if (data->response.out_route_get) { + nm_assert(!*data->response.out_route_get); + data->response.out_route_get = NULL; + } + break; + } + + g_array_remove_index_fast(priv->delayed_action.list_wait_for_nl_response, idx); } static void -delayed_action_wait_for_nl_response_complete_check (NMPlatform *platform, - WaitForNlResponseResult force_result, - guint32 *out_next_seq_number, - gint64 *out_next_timeout_abs_ns, - gint64 *p_now_ns) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - guint i; - guint32 next_seq_number = 0; - gint64 next_timeout_abs_ns = 0; - int now_ns = 0; - - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; ) { - const DelayedActionWaitForNlResponseData *data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i); - - if (data->seq_result) - delayed_action_wait_for_nl_response_complete (platform, i, data->seq_result); - else if ( p_now_ns - && ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_nsec ())) >= data->timeout_abs_ns)) { - /* the caller can optionally check for timeout by providing a p_now_ns argument. */ - delayed_action_wait_for_nl_response_complete (platform, i, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT); - } else if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) - delayed_action_wait_for_nl_response_complete (platform, i, force_result); - else { - if ( next_seq_number == 0 - || next_timeout_abs_ns > data->timeout_abs_ns) { - next_seq_number = data->seq_number; - next_timeout_abs_ns = data->timeout_abs_ns; - } - i++; - } - } - - if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) { - nm_assert (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); - nm_assert (priv->delayed_action.list_wait_for_nl_response->len == 0); - } - - NM_SET_OUT (out_next_seq_number, next_seq_number); - NM_SET_OUT (out_next_timeout_abs_ns, next_timeout_abs_ns); - NM_SET_OUT (p_now_ns, now_ns); +delayed_action_wait_for_nl_response_complete_check(NMPlatform * platform, + WaitForNlResponseResult force_result, + guint32 * out_next_seq_number, + gint64 * out_next_timeout_abs_ns, + gint64 * p_now_ns) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + guint i; + guint32 next_seq_number = 0; + gint64 next_timeout_abs_ns = 0; + int now_ns = 0; + + for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len;) { + const DelayedActionWaitForNlResponseData *data = + &g_array_index(priv->delayed_action.list_wait_for_nl_response, + DelayedActionWaitForNlResponseData, + i); + + if (data->seq_result) + delayed_action_wait_for_nl_response_complete(platform, i, data->seq_result); + else if (p_now_ns + && ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_nsec())) + >= data->timeout_abs_ns)) { + /* the caller can optionally check for timeout by providing a p_now_ns argument. */ + delayed_action_wait_for_nl_response_complete( + platform, + i, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT); + } else if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) + delayed_action_wait_for_nl_response_complete(platform, i, force_result); + else { + if (next_seq_number == 0 || next_timeout_abs_ns > data->timeout_abs_ns) { + next_seq_number = data->seq_number; + next_timeout_abs_ns = data->timeout_abs_ns; + } + i++; + } + } + + if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) { + nm_assert( + !NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); + nm_assert(priv->delayed_action.list_wait_for_nl_response->len == 0); + } + + NM_SET_OUT(out_next_seq_number, next_seq_number); + NM_SET_OUT(out_next_timeout_abs_ns, next_timeout_abs_ns); + NM_SET_OUT(p_now_ns, now_ns); } static void -delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform, - WaitForNlResponseResult fallback_result) +delayed_action_wait_for_nl_response_complete_all(NMPlatform * platform, + WaitForNlResponseResult fallback_result) { - delayed_action_wait_for_nl_response_complete_check (platform, - fallback_result, - NULL, - NULL, - NULL); + delayed_action_wait_for_nl_response_complete_check(platform, fallback_result, NULL, NULL, NULL); } /*****************************************************************************/ static void -delayed_action_handle_MASTER_CONNECTED (NMPlatform *platform, int master_ifindex) +delayed_action_handle_MASTER_CONNECTED(NMPlatform *platform, int master_ifindex) { - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - NMPCacheOpsType cache_op; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + NMPCacheOpsType cache_op; - cache_op = nmp_cache_update_link_master_connected (nm_platform_get_cache (platform), master_ifindex, &obj_old, &obj_new); - if (cache_op == NMP_CACHE_OPS_UNCHANGED) - return; - cache_on_change (platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); + cache_op = nmp_cache_update_link_master_connected(nm_platform_get_cache(platform), + master_ifindex, + &obj_old, + &obj_new); + if (cache_op == NMP_CACHE_OPS_UNCHANGED) + return; + cache_on_change(platform, cache_op, obj_old, obj_new); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); } static void -delayed_action_handle_REFRESH_LINK (NMPlatform *platform, int ifindex) +delayed_action_handle_REFRESH_LINK(NMPlatform *platform, int ifindex) { - do_request_link_no_delayed_actions (platform, ifindex, NULL); + do_request_link_no_delayed_actions(platform, ifindex, NULL); } static void -delayed_action_handle_REFRESH_ALL (NMPlatform *platform, DelayedActionType flags) +delayed_action_handle_REFRESH_ALL(NMPlatform *platform, DelayedActionType flags) { - do_request_all_no_delayed_actions (platform, flags); + do_request_all_no_delayed_actions(platform, flags); } static void -delayed_action_handle_READ_NETLINK (NMPlatform *platform) +delayed_action_handle_READ_NETLINK(NMPlatform *platform) { - event_handler_read_netlink (platform, FALSE); + event_handler_read_netlink(platform, FALSE); } static void -delayed_action_handle_WAIT_FOR_NL_RESPONSE (NMPlatform *platform) +delayed_action_handle_WAIT_FOR_NL_RESPONSE(NMPlatform *platform) { - event_handler_read_netlink (platform, TRUE); + event_handler_read_netlink(platform, TRUE); } static gboolean -delayed_action_handle_one (NMPlatform *platform) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - gpointer user_data; - - if (priv->delayed_action.flags == DELAYED_ACTION_TYPE_NONE) - return FALSE; - - /* First process DELAYED_ACTION_TYPE_MASTER_CONNECTED actions. - * This type of action is entirely cache-internal and is here to resolve a - * cache inconsistency. It should be fixed right away. */ - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_MASTER_CONNECTED)) { - nm_assert (priv->delayed_action.list_master_connected->len > 0); - - user_data = priv->delayed_action.list_master_connected->pdata[0]; - g_ptr_array_remove_index_fast (priv->delayed_action.list_master_connected, 0); - if (priv->delayed_action.list_master_connected->len == 0) - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_MASTER_CONNECTED; - nm_assert (_nm_utils_ptrarray_find_first ((gconstpointer *) priv->delayed_action.list_master_connected->pdata, priv->delayed_action.list_master_connected->len, user_data) < 0); - - _LOGt_delayed_action (DELAYED_ACTION_TYPE_MASTER_CONNECTED, user_data, "handle"); - delayed_action_handle_MASTER_CONNECTED (platform, GPOINTER_TO_INT (user_data)); - return TRUE; - } - nm_assert (priv->delayed_action.list_master_connected->len == 0); - - /* Next we prefer read-netlink, because the buffer size is limited and we want to process events - * from netlink early. */ - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_READ_NETLINK)) { - _LOGt_delayed_action (DELAYED_ACTION_TYPE_READ_NETLINK, NULL, "handle"); - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_READ_NETLINK; - delayed_action_handle_READ_NETLINK (platform); - return TRUE; - } - - if (NM_FLAGS_ANY (priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_ALL)) { - DelayedActionType flags, iflags; - - flags = priv->delayed_action.flags & DELAYED_ACTION_TYPE_REFRESH_ALL; - - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL; - - if (_LOGt_ENABLED ()) { - FOR_EACH_DELAYED_ACTION (iflags, flags) - _LOGt_delayed_action (iflags, NULL, "handle"); - } - - delayed_action_handle_REFRESH_ALL (platform, flags); - return TRUE; - } - - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)) { - nm_assert (priv->delayed_action.list_refresh_link->len > 0); - - user_data = priv->delayed_action.list_refresh_link->pdata[0]; - g_ptr_array_remove_index_fast (priv->delayed_action.list_refresh_link, 0); - if (priv->delayed_action.list_refresh_link->len == 0) - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; - nm_assert (_nm_utils_ptrarray_find_first ((gconstpointer *) priv->delayed_action.list_refresh_link->pdata, priv->delayed_action.list_refresh_link->len, user_data) < 0); - - _LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "handle"); - - delayed_action_handle_REFRESH_LINK (platform, GPOINTER_TO_INT (user_data)); - - return TRUE; - } - - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - nm_assert (priv->delayed_action.list_wait_for_nl_response->len > 0); - _LOGt_delayed_action (DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, NULL, "handle"); - delayed_action_handle_WAIT_FOR_NL_RESPONSE (platform); - return TRUE; - } - - return FALSE; +delayed_action_handle_one(NMPlatform *platform) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + gpointer user_data; + + if (priv->delayed_action.flags == DELAYED_ACTION_TYPE_NONE) + return FALSE; + + /* First process DELAYED_ACTION_TYPE_MASTER_CONNECTED actions. + * This type of action is entirely cache-internal and is here to resolve a + * cache inconsistency. It should be fixed right away. */ + if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_MASTER_CONNECTED)) { + nm_assert(priv->delayed_action.list_master_connected->len > 0); + + user_data = priv->delayed_action.list_master_connected->pdata[0]; + g_ptr_array_remove_index_fast(priv->delayed_action.list_master_connected, 0); + if (priv->delayed_action.list_master_connected->len == 0) + priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_MASTER_CONNECTED; + nm_assert(_nm_utils_ptrarray_find_first( + (gconstpointer *) priv->delayed_action.list_master_connected->pdata, + priv->delayed_action.list_master_connected->len, + user_data) + < 0); + + _LOGt_delayed_action(DELAYED_ACTION_TYPE_MASTER_CONNECTED, user_data, "handle"); + delayed_action_handle_MASTER_CONNECTED(platform, GPOINTER_TO_INT(user_data)); + return TRUE; + } + nm_assert(priv->delayed_action.list_master_connected->len == 0); + + /* Next we prefer read-netlink, because the buffer size is limited and we want to process events + * from netlink early. */ + if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_READ_NETLINK)) { + _LOGt_delayed_action(DELAYED_ACTION_TYPE_READ_NETLINK, NULL, "handle"); + priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_READ_NETLINK; + delayed_action_handle_READ_NETLINK(platform); + return TRUE; + } + + if (NM_FLAGS_ANY(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_ALL)) { + DelayedActionType flags, iflags; + + flags = priv->delayed_action.flags & DELAYED_ACTION_TYPE_REFRESH_ALL; + + priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL; + + if (_LOGt_ENABLED()) { + FOR_EACH_DELAYED_ACTION(iflags, flags) + _LOGt_delayed_action(iflags, NULL, "handle"); + } + + delayed_action_handle_REFRESH_ALL(platform, flags); + return TRUE; + } + + if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)) { + nm_assert(priv->delayed_action.list_refresh_link->len > 0); + + user_data = priv->delayed_action.list_refresh_link->pdata[0]; + g_ptr_array_remove_index_fast(priv->delayed_action.list_refresh_link, 0); + if (priv->delayed_action.list_refresh_link->len == 0) + priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; + nm_assert(_nm_utils_ptrarray_find_first( + (gconstpointer *) priv->delayed_action.list_refresh_link->pdata, + priv->delayed_action.list_refresh_link->len, + user_data) + < 0); + + _LOGt_delayed_action(DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "handle"); + + delayed_action_handle_REFRESH_LINK(platform, GPOINTER_TO_INT(user_data)); + + return TRUE; + } + + if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { + nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); + _LOGt_delayed_action(DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, NULL, "handle"); + delayed_action_handle_WAIT_FOR_NL_RESPONSE(platform); + return TRUE; + } + + return FALSE; } static gboolean -delayed_action_handle_all (NMPlatform *platform, gboolean read_netlink) +delayed_action_handle_all(NMPlatform *platform, gboolean read_netlink) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - gboolean any = FALSE; + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + gboolean any = FALSE; - g_return_val_if_fail (priv->delayed_action.is_handling == 0, FALSE); + g_return_val_if_fail(priv->delayed_action.is_handling == 0, FALSE); - priv->delayed_action.is_handling++; - if (read_netlink) - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_READ_NETLINK, NULL); - while (delayed_action_handle_one (platform)) - any = TRUE; - priv->delayed_action.is_handling--; + priv->delayed_action.is_handling++; + if (read_netlink) + delayed_action_schedule(platform, DELAYED_ACTION_TYPE_READ_NETLINK, NULL); + while (delayed_action_handle_one(platform)) + any = TRUE; + priv->delayed_action.is_handling--; - cache_prune_all (platform); + cache_prune_all(platform); - return any; + return any; } static void -delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gpointer user_data) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - DelayedActionType iflags; - - nm_assert (action_type != DELAYED_ACTION_TYPE_NONE); - - switch (action_type) { - case DELAYED_ACTION_TYPE_REFRESH_LINK: - if (_nm_utils_ptrarray_find_first ((gconstpointer *) priv->delayed_action.list_refresh_link->pdata, priv->delayed_action.list_refresh_link->len, user_data) < 0) - g_ptr_array_add (priv->delayed_action.list_refresh_link, user_data); - break; - case DELAYED_ACTION_TYPE_MASTER_CONNECTED: - if (_nm_utils_ptrarray_find_first ((gconstpointer *) priv->delayed_action.list_master_connected->pdata, priv->delayed_action.list_master_connected->len, user_data) < 0) - g_ptr_array_add (priv->delayed_action.list_master_connected, user_data); - break; - case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE: - g_array_append_vals (priv->delayed_action.list_wait_for_nl_response, user_data, 1); - break; - default: - nm_assert (!user_data); - nm_assert (!NM_FLAGS_HAS (action_type, DELAYED_ACTION_TYPE_REFRESH_LINK)); - nm_assert (!NM_FLAGS_HAS (action_type, DELAYED_ACTION_TYPE_MASTER_CONNECTED)); - nm_assert (!NM_FLAGS_HAS (action_type, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); - break; - } - - priv->delayed_action.flags |= action_type; - - if (_LOGt_ENABLED ()) { - FOR_EACH_DELAYED_ACTION (iflags, action_type) - _LOGt_delayed_action (iflags, user_data, "schedule"); - } +delayed_action_schedule(NMPlatform *platform, DelayedActionType action_type, gpointer user_data) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + DelayedActionType iflags; + + nm_assert(action_type != DELAYED_ACTION_TYPE_NONE); + + switch (action_type) { + case DELAYED_ACTION_TYPE_REFRESH_LINK: + if (_nm_utils_ptrarray_find_first( + (gconstpointer *) priv->delayed_action.list_refresh_link->pdata, + priv->delayed_action.list_refresh_link->len, + user_data) + < 0) + g_ptr_array_add(priv->delayed_action.list_refresh_link, user_data); + break; + case DELAYED_ACTION_TYPE_MASTER_CONNECTED: + if (_nm_utils_ptrarray_find_first( + (gconstpointer *) priv->delayed_action.list_master_connected->pdata, + priv->delayed_action.list_master_connected->len, + user_data) + < 0) + g_ptr_array_add(priv->delayed_action.list_master_connected, user_data); + break; + case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE: + g_array_append_vals(priv->delayed_action.list_wait_for_nl_response, user_data, 1); + break; + default: + nm_assert(!user_data); + nm_assert(!NM_FLAGS_HAS(action_type, DELAYED_ACTION_TYPE_REFRESH_LINK)); + nm_assert(!NM_FLAGS_HAS(action_type, DELAYED_ACTION_TYPE_MASTER_CONNECTED)); + nm_assert(!NM_FLAGS_HAS(action_type, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)); + break; + } + + priv->delayed_action.flags |= action_type; + + if (_LOGt_ENABLED()) { + FOR_EACH_DELAYED_ACTION(iflags, action_type) + _LOGt_delayed_action(iflags, user_data, "schedule"); + } } static void -delayed_action_schedule_WAIT_FOR_NL_RESPONSE (NMPlatform *platform, - guint32 seq_number, - WaitForNlResponseResult *out_seq_result, - char **out_errmsg, - DelayedActionWaitForNlResponseType response_type, - gpointer response_out_data) -{ - DelayedActionWaitForNlResponseData data = { - .seq_number = seq_number, - .timeout_abs_ns = nm_utils_get_monotonic_timestamp_nsec () + (200 * (NM_UTILS_NSEC_PER_SEC / 1000)), - .out_seq_result = out_seq_result, - .out_errmsg = out_errmsg, - .response_type = response_type, - .response.out_data = response_out_data, - }; - - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, - &data); +delayed_action_schedule_WAIT_FOR_NL_RESPONSE(NMPlatform * platform, + guint32 seq_number, + WaitForNlResponseResult * out_seq_result, + char ** out_errmsg, + DelayedActionWaitForNlResponseType response_type, + gpointer response_out_data) +{ + DelayedActionWaitForNlResponseData data = { + .seq_number = seq_number, + .timeout_abs_ns = + nm_utils_get_monotonic_timestamp_nsec() + (200 * (NM_UTILS_NSEC_PER_SEC / 1000)), + .out_seq_result = out_seq_result, + .out_errmsg = out_errmsg, + .response_type = response_type, + .response.out_data = response_out_data, + }; + + delayed_action_schedule(platform, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, &data); } /*****************************************************************************/ static void -cache_prune_one_type (NMPlatform *platform, - const NMPLookup *lookup) +cache_prune_one_type(NMPlatform *platform, const NMPLookup *lookup) { - NMDedupMultiIter iter; - const NMPObject *obj; - NMPCacheOpsType cache_op; - NMPCache *cache = nm_platform_get_cache (platform); + NMDedupMultiIter iter; + const NMPObject *obj; + NMPCacheOpsType cache_op; + NMPCache * cache = nm_platform_get_cache(platform); - nm_dedup_multi_iter_init (&iter, - nmp_cache_lookup (cache, - lookup)); - while (nm_dedup_multi_iter_next (&iter)) { - const NMDedupMultiEntry *main_entry; + nm_dedup_multi_iter_init(&iter, nmp_cache_lookup(cache, lookup)); + while (nm_dedup_multi_iter_next(&iter)) { + const NMDedupMultiEntry *main_entry; - /* we only track the dirty flag for the OBJECT-TYPE index. That means, - * for other lookup types we need to check the dirty flag of the main-entry. */ - main_entry = nmp_cache_reresolve_main_entry (cache, iter.current, lookup); - if (!main_entry->dirty) - continue; + /* we only track the dirty flag for the OBJECT-TYPE index. That means, + * for other lookup types we need to check the dirty flag of the main-entry. */ + main_entry = nmp_cache_reresolve_main_entry(cache, iter.current, lookup); + if (!main_entry->dirty) + continue; - obj = main_entry->obj; + obj = main_entry->obj; - _LOGt ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + _LOGt("cache-prune: prune %s", + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); - { - nm_auto_nmpobj const NMPObject *obj_old = NULL; + { + nm_auto_nmpobj const NMPObject *obj_old = NULL; - cache_op = nmp_cache_remove (cache, obj, TRUE, TRUE, &obj_old); - nm_assert (cache_op == NMP_CACHE_OPS_REMOVED); - cache_on_change (platform, cache_op, obj_old, NULL); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, NULL); - } - } + cache_op = nmp_cache_remove(cache, obj, TRUE, TRUE, &obj_old); + nm_assert(cache_op == NMP_CACHE_OPS_REMOVED); + cache_on_change(platform, cache_op, obj_old, NULL); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, NULL); + } + } } static void -cache_prune_all (NMPlatform *platform) +cache_prune_all(NMPlatform *platform) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - RefreshAllType refresh_all_type; + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + RefreshAllType refresh_all_type; - for (refresh_all_type = _REFRESH_ALL_TYPE_FIRST; refresh_all_type < _REFRESH_ALL_TYPE_NUM; refresh_all_type++) { - NMPLookup lookup; + for (refresh_all_type = _REFRESH_ALL_TYPE_FIRST; refresh_all_type < _REFRESH_ALL_TYPE_NUM; + refresh_all_type++) { + NMPLookup lookup; - if (priv->pruning[refresh_all_type] == 0) - continue; - priv->pruning[refresh_all_type] -= 1; - if (priv->pruning[refresh_all_type] > 0) - continue; - refresh_all_type_init_lookup (refresh_all_type, - &lookup); - cache_prune_one_type (platform, &lookup); - } + if (priv->pruning[refresh_all_type] == 0) + continue; + priv->pruning[refresh_all_type] -= 1; + if (priv->pruning[refresh_all_type] > 0) + continue; + refresh_all_type_init_lookup(refresh_all_type, &lookup); + cache_prune_one_type(platform, &lookup); + } } static void -cache_on_change (NMPlatform *platform, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new) -{ - const NMPClass *klass; - char str_buf[sizeof (_nm_utils_to_string_buffer)]; - char str_buf2[sizeof (_nm_utils_to_string_buffer)]; - NMPCache *cache = nm_platform_get_cache (platform); - - ASSERT_nmp_cache_ops (cache, cache_op, obj_old, obj_new); - nm_assert (cache_op != NMP_CACHE_OPS_UNCHANGED); - - klass = obj_old ? NMP_OBJECT_GET_CLASS (obj_old) : NMP_OBJECT_GET_CLASS (obj_new); - - _LOGt ("update-cache-%s: %s: %s%s%s", - klass->obj_type_name, - (cache_op == NMP_CACHE_OPS_UPDATED - ? "UPDATE" - : (cache_op == NMP_CACHE_OPS_REMOVED - ? "REMOVE" - : (cache_op == NMP_CACHE_OPS_ADDED) ? "ADD" : "???")), - (cache_op != NMP_CACHE_OPS_ADDED - ? nmp_object_to_string (obj_old, NMP_OBJECT_TO_STRING_ALL, str_buf2, sizeof (str_buf2)) - : nmp_object_to_string (obj_new, NMP_OBJECT_TO_STRING_ALL, str_buf2, sizeof (str_buf2))), - (cache_op == NMP_CACHE_OPS_UPDATED) ? " -> " : "", - (cache_op == NMP_CACHE_OPS_UPDATED - ? nmp_object_to_string (obj_new, NMP_OBJECT_TO_STRING_ALL, str_buf, sizeof (str_buf)) - : "")); - - switch (klass->obj_type) { - case NMP_OBJECT_TYPE_LINK: - { - /* check whether changing a slave link can cause a master link (bridge or bond) to go up/down */ - if ( obj_old - && nmp_cache_link_connected_needs_toggle_by_ifindex (cache, obj_old->link.master, obj_new, obj_old)) - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_MASTER_CONNECTED, GINT_TO_POINTER (obj_old->link.master)); - if ( obj_new - && (!obj_old || obj_old->link.master != obj_new->link.master) - && nmp_cache_link_connected_needs_toggle_by_ifindex (cache, obj_new->link.master, obj_new, obj_old)) - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_MASTER_CONNECTED, GINT_TO_POINTER (obj_new->link.master)); - } - { - /* check whether we are about to change a master link that needs toggling connected state. */ - if ( obj_new /* <-- nonsensical, make coverity happy */ - && nmp_cache_link_connected_needs_toggle (cache, obj_new, obj_new, obj_old)) - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_MASTER_CONNECTED, GINT_TO_POINTER (obj_new->link.ifindex)); - } - { - int ifindex = 0; - - /* if we remove a link (from netlink), we must refresh the addresses, routes, qdiscs and tfilters */ - if ( cache_op == NMP_CACHE_OPS_REMOVED - && obj_old /* <-- nonsensical, make coverity happy */) - ifindex = obj_old->link.ifindex; - else if ( cache_op == NMP_CACHE_OPS_UPDATED - && obj_old && obj_new /* <-- nonsensical, make coverity happy */ - && !obj_new->_link.netlink.is_in_netlink - && obj_new->_link.netlink.is_in_netlink != obj_old->_link.netlink.is_in_netlink) - ifindex = obj_new->link.ifindex; - - if (ifindex > 0) { - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL | - DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS | - DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - NULL); - } - } - { - int ifindex = -1; - - /* removal of a link could be caused by moving the link to another netns. - * In this case, we potentially have to update other links that have this link as parent. - * Currently, kernel misses to sent us a notification in this case - * (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */ - - if ( cache_op == NMP_CACHE_OPS_REMOVED - && obj_old /* <-- nonsensical, make coverity happy */ - && obj_old->_link.netlink.is_in_netlink) - ifindex = obj_old->link.ifindex; - else if ( cache_op == NMP_CACHE_OPS_UPDATED - && obj_old && obj_new /* <-- nonsensical, make coverity happy */ - && obj_old->_link.netlink.is_in_netlink - && !obj_new->_link.netlink.is_in_netlink) - ifindex = obj_new->link.ifindex; - - if (ifindex > 0) { - NMPLookup lookup; - NMDedupMultiIter iter; - const NMPlatformLink *l; - - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK); - nmp_cache_iter_for_each_link (&iter, - nmp_cache_lookup (cache, &lookup), - &l) { - if (l->parent == ifindex) - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (l->ifindex)); - } - } - } - { - /* if a link goes down, we must refresh routes */ - if ( cache_op == NMP_CACHE_OPS_UPDATED - && obj_old && obj_new /* <-- nonsensical, make coverity happy */ - && obj_old->_link.netlink.is_in_netlink - && obj_new->_link.netlink.is_in_netlink - && ( ( NM_FLAGS_HAS (obj_old->link.n_ifi_flags, IFF_UP) - && !NM_FLAGS_HAS (obj_new->link.n_ifi_flags, IFF_UP)) - || ( NM_FLAGS_HAS (obj_old->link.n_ifi_flags, IFF_LOWER_UP) - && !NM_FLAGS_HAS (obj_new->link.n_ifi_flags, IFF_LOWER_UP)))) { - /* FIXME: I suspect that IFF_LOWER_UP must not be considered, and I - * think kernel does send RTM_DELROUTE events for IPv6 routes, so - * we might not need to refresh IPv6 routes. */ - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, - NULL); - } - } - if ( NM_IN_SET (cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED) - && (obj_new && obj_new->_link.netlink.is_in_netlink) - && (!obj_old || !obj_old->_link.netlink.is_in_netlink)) - { - gboolean re_request_link = FALSE; - const NMPlatformLnkTun *lnk_tun; - - if ( !obj_new->_link.netlink.lnk - && NM_IN_SET (obj_new->link.type, NM_LINK_TYPE_GRE, - NM_LINK_TYPE_GRETAP, - NM_LINK_TYPE_IP6TNL, - NM_LINK_TYPE_IP6GRE, - NM_LINK_TYPE_IP6GRETAP, - NM_LINK_TYPE_INFINIBAND, - NM_LINK_TYPE_MACVLAN, - NM_LINK_TYPE_MACVLAN, - NM_LINK_TYPE_SIT, - NM_LINK_TYPE_TUN, - NM_LINK_TYPE_VLAN, - NM_LINK_TYPE_VXLAN)) { - /* certain link-types also come with a IFLA_INFO_DATA/lnk_data. It may happen that - * kernel didn't send this notification, thus when we first learn about a link - * that lacks an lnk_data we re-request it again. - * - * For example https://bugzilla.redhat.com/show_bug.cgi?id=1284001 */ - re_request_link = TRUE; - } else if ( obj_new->link.type == NM_LINK_TYPE_TUN - && obj_new->_link.netlink.lnk - && (lnk_tun = &(obj_new->_link.netlink.lnk)->lnk_tun) - && !lnk_tun->persist - && lnk_tun->pi - && !lnk_tun->vnet_hdr - && !lnk_tun->multi_queue - && !lnk_tun->owner_valid - && !lnk_tun->group_valid) { - /* kernel has/had a know issue that the first notification for TUN device would - * be sent with invalid parameters. The message looks like that kind, so refetch - * it. */ - re_request_link = TRUE; - } else if ( obj_new->link.type == NM_LINK_TYPE_VETH - && obj_new->link.parent == 0) { - /* the initial notification when adding a veth pair can lack the parent/IFLA_LINK - * (https://bugzilla.redhat.com/show_bug.cgi?id=1285827). - * Request it again. */ - re_request_link = TRUE; - } else if ( obj_new->link.type == NM_LINK_TYPE_ETHERNET - && obj_new->link.l_address.len == 0) { - /* Due to a kernel bug, we sometimes receive spurious NEWLINK - * messages after a wifi interface has disappeared. Since the - * link is not present anymore we can't determine its type and - * thus it will show up as a Ethernet one, with no address - * specified. Request the link again to check if it really - * exists. https://bugzilla.redhat.com/show_bug.cgi?id=1302037 - */ - re_request_link = TRUE; - } - if (re_request_link) { - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_REFRESH_LINK, - GINT_TO_POINTER (obj_new->link.ifindex)); - } - } - { - /* on enslave/release, we also refresh the master. */ - int ifindex1 = 0, ifindex2 = 0; - gboolean changed_master, changed_connected; - - changed_master = (obj_new && obj_new->_link.netlink.is_in_netlink && obj_new->link.master > 0 ? obj_new->link.master : 0) - != (obj_old && obj_old->_link.netlink.is_in_netlink && obj_old->link.master > 0 ? obj_old->link.master : 0); - changed_connected = (obj_new && obj_new->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (obj_new->link.n_ifi_flags, IFF_LOWER_UP) : 2) - != (obj_old && obj_old->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (obj_old->link.n_ifi_flags, IFF_LOWER_UP) : 2); - - if (changed_master || changed_connected) { - ifindex1 = (obj_old && obj_old->_link.netlink.is_in_netlink && obj_old->link.master > 0) ? obj_old->link.master : 0; - ifindex2 = (obj_new && obj_new->_link.netlink.is_in_netlink && obj_new->link.master > 0) ? obj_new->link.master : 0; - - if (ifindex1 > 0) - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (ifindex1)); - if (ifindex2 > 0 && ifindex1 != ifindex2) - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (ifindex2)); - } - } - break; - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - { - /* Address deletion is sometimes accompanied by route deletion. We need to - * check all routes belonging to the same interface. */ - if (cache_op == NMP_CACHE_OPS_REMOVED) { - delayed_action_schedule (platform, - (klass->obj_type == NMP_OBJECT_TYPE_IP4_ADDRESS) - ? DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES - : DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, - NULL); - } - } - break; - default: - break; - } +cache_on_change(NMPlatform * platform, + NMPCacheOpsType cache_op, + const NMPObject *obj_old, + const NMPObject *obj_new) +{ + const NMPClass *klass; + char str_buf[sizeof(_nm_utils_to_string_buffer)]; + char str_buf2[sizeof(_nm_utils_to_string_buffer)]; + NMPCache * cache = nm_platform_get_cache(platform); + + ASSERT_nmp_cache_ops(cache, cache_op, obj_old, obj_new); + nm_assert(cache_op != NMP_CACHE_OPS_UNCHANGED); + + klass = obj_old ? NMP_OBJECT_GET_CLASS(obj_old) : NMP_OBJECT_GET_CLASS(obj_new); + + _LOGt( + "update-cache-%s: %s: %s%s%s", + klass->obj_type_name, + (cache_op == NMP_CACHE_OPS_UPDATED ? "UPDATE" + : (cache_op == NMP_CACHE_OPS_REMOVED ? "REMOVE" + : (cache_op == NMP_CACHE_OPS_ADDED) ? "ADD" + : "???")), + (cache_op != NMP_CACHE_OPS_ADDED + ? nmp_object_to_string(obj_old, NMP_OBJECT_TO_STRING_ALL, str_buf2, sizeof(str_buf2)) + : nmp_object_to_string(obj_new, NMP_OBJECT_TO_STRING_ALL, str_buf2, sizeof(str_buf2))), + (cache_op == NMP_CACHE_OPS_UPDATED) ? " -> " : "", + (cache_op == NMP_CACHE_OPS_UPDATED + ? nmp_object_to_string(obj_new, NMP_OBJECT_TO_STRING_ALL, str_buf, sizeof(str_buf)) + : "")); + + switch (klass->obj_type) { + case NMP_OBJECT_TYPE_LINK: + { + /* check whether changing a slave link can cause a master link (bridge or bond) to go up/down */ + if (obj_old + && nmp_cache_link_connected_needs_toggle_by_ifindex(cache, + obj_old->link.master, + obj_new, + obj_old)) + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_MASTER_CONNECTED, + GINT_TO_POINTER(obj_old->link.master)); + if (obj_new && (!obj_old || obj_old->link.master != obj_new->link.master) + && nmp_cache_link_connected_needs_toggle_by_ifindex(cache, + obj_new->link.master, + obj_new, + obj_old)) + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_MASTER_CONNECTED, + GINT_TO_POINTER(obj_new->link.master)); + } + { + /* check whether we are about to change a master link that needs toggling connected state. */ + if (obj_new /* <-- nonsensical, make coverity happy */ + && nmp_cache_link_connected_needs_toggle(cache, obj_new, obj_new, obj_old)) + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_MASTER_CONNECTED, + GINT_TO_POINTER(obj_new->link.ifindex)); + } + { + int ifindex = 0; + + /* if we remove a link (from netlink), we must refresh the addresses, routes, qdiscs and tfilters */ + if (cache_op == NMP_CACHE_OPS_REMOVED + && obj_old /* <-- nonsensical, make coverity happy */) + ifindex = obj_old->link.ifindex; + else if (cache_op == NMP_CACHE_OPS_UPDATED && obj_old + && obj_new /* <-- nonsensical, make coverity happy */ + && !obj_new->_link.netlink.is_in_netlink + && obj_new->_link.netlink.is_in_netlink + != obj_old->_link.netlink.is_in_netlink) + ifindex = obj_new->link.ifindex; + + if (ifindex > 0) { + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL + | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS + | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, + NULL); + } + } + { + int ifindex = -1; + + /* removal of a link could be caused by moving the link to another netns. + * In this case, we potentially have to update other links that have this link as parent. + * Currently, kernel misses to sent us a notification in this case + * (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */ + + if (cache_op == NMP_CACHE_OPS_REMOVED + && obj_old /* <-- nonsensical, make coverity happy */ + && obj_old->_link.netlink.is_in_netlink) + ifindex = obj_old->link.ifindex; + else if (cache_op == NMP_CACHE_OPS_UPDATED && obj_old + && obj_new /* <-- nonsensical, make coverity happy */ + && obj_old->_link.netlink.is_in_netlink + && !obj_new->_link.netlink.is_in_netlink) + ifindex = obj_new->link.ifindex; + + if (ifindex > 0) { + NMPLookup lookup; + NMDedupMultiIter iter; + const NMPlatformLink *l; + + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); + nmp_cache_iter_for_each_link (&iter, nmp_cache_lookup(cache, &lookup), &l) { + if (l->parent == ifindex) + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_REFRESH_LINK, + GINT_TO_POINTER(l->ifindex)); + } + } + } + { + /* if a link goes down, we must refresh routes */ + if (cache_op == NMP_CACHE_OPS_UPDATED && obj_old + && obj_new /* <-- nonsensical, make coverity happy */ + && obj_old->_link.netlink.is_in_netlink && obj_new->_link.netlink.is_in_netlink + && ((NM_FLAGS_HAS(obj_old->link.n_ifi_flags, IFF_UP) + && !NM_FLAGS_HAS(obj_new->link.n_ifi_flags, IFF_UP)) + || (NM_FLAGS_HAS(obj_old->link.n_ifi_flags, IFF_LOWER_UP) + && !NM_FLAGS_HAS(obj_new->link.n_ifi_flags, IFF_LOWER_UP)))) { + /* FIXME: I suspect that IFF_LOWER_UP must not be considered, and I + * think kernel does send RTM_DELROUTE events for IPv6 routes, so + * we might not need to refresh IPv6 routes. */ + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, + NULL); + } + } + if (NM_IN_SET(cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED) + && (obj_new && obj_new->_link.netlink.is_in_netlink) + && (!obj_old || !obj_old->_link.netlink.is_in_netlink)) { + gboolean re_request_link = FALSE; + const NMPlatformLnkTun *lnk_tun; + + if (!obj_new->_link.netlink.lnk + && NM_IN_SET(obj_new->link.type, + NM_LINK_TYPE_GRE, + NM_LINK_TYPE_GRETAP, + NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_IP6GRE, + NM_LINK_TYPE_IP6GRETAP, + NM_LINK_TYPE_INFINIBAND, + NM_LINK_TYPE_MACVLAN, + NM_LINK_TYPE_MACVLAN, + NM_LINK_TYPE_SIT, + NM_LINK_TYPE_TUN, + NM_LINK_TYPE_VLAN, + NM_LINK_TYPE_VXLAN)) { + /* certain link-types also come with a IFLA_INFO_DATA/lnk_data. It may happen that + * kernel didn't send this notification, thus when we first learn about a link + * that lacks an lnk_data we re-request it again. + * + * For example https://bugzilla.redhat.com/show_bug.cgi?id=1284001 */ + re_request_link = TRUE; + } else if (obj_new->link.type == NM_LINK_TYPE_TUN && obj_new->_link.netlink.lnk + && (lnk_tun = &(obj_new->_link.netlink.lnk)->lnk_tun) && !lnk_tun->persist + && lnk_tun->pi && !lnk_tun->vnet_hdr && !lnk_tun->multi_queue + && !lnk_tun->owner_valid && !lnk_tun->group_valid) { + /* kernel has/had a know issue that the first notification for TUN device would + * be sent with invalid parameters. The message looks like that kind, so refetch + * it. */ + re_request_link = TRUE; + } else if (obj_new->link.type == NM_LINK_TYPE_VETH && obj_new->link.parent == 0) { + /* the initial notification when adding a veth pair can lack the parent/IFLA_LINK + * (https://bugzilla.redhat.com/show_bug.cgi?id=1285827). + * Request it again. */ + re_request_link = TRUE; + } else if (obj_new->link.type == NM_LINK_TYPE_ETHERNET + && obj_new->link.l_address.len == 0) { + /* Due to a kernel bug, we sometimes receive spurious NEWLINK + * messages after a wifi interface has disappeared. Since the + * link is not present anymore we can't determine its type and + * thus it will show up as a Ethernet one, with no address + * specified. Request the link again to check if it really + * exists. https://bugzilla.redhat.com/show_bug.cgi?id=1302037 + */ + re_request_link = TRUE; + } + if (re_request_link) { + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_REFRESH_LINK, + GINT_TO_POINTER(obj_new->link.ifindex)); + } + } + { + /* on enslave/release, we also refresh the master. */ + int ifindex1 = 0, ifindex2 = 0; + gboolean changed_master, changed_connected; + + changed_master = + (obj_new && obj_new->_link.netlink.is_in_netlink && obj_new->link.master > 0 + ? obj_new->link.master + : 0) + != (obj_old && obj_old->_link.netlink.is_in_netlink && obj_old->link.master > 0 + ? obj_old->link.master + : 0); + changed_connected = (obj_new && obj_new->_link.netlink.is_in_netlink + ? NM_FLAGS_HAS(obj_new->link.n_ifi_flags, IFF_LOWER_UP) + : 2) + != (obj_old && obj_old->_link.netlink.is_in_netlink + ? NM_FLAGS_HAS(obj_old->link.n_ifi_flags, IFF_LOWER_UP) + : 2); + + if (changed_master || changed_connected) { + ifindex1 = + (obj_old && obj_old->_link.netlink.is_in_netlink && obj_old->link.master > 0) + ? obj_old->link.master + : 0; + ifindex2 = + (obj_new && obj_new->_link.netlink.is_in_netlink && obj_new->link.master > 0) + ? obj_new->link.master + : 0; + + if (ifindex1 > 0) + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_REFRESH_LINK, + GINT_TO_POINTER(ifindex1)); + if (ifindex2 > 0 && ifindex1 != ifindex2) + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_REFRESH_LINK, + GINT_TO_POINTER(ifindex2)); + } + } + break; + case NMP_OBJECT_TYPE_IP4_ADDRESS: + case NMP_OBJECT_TYPE_IP6_ADDRESS: + { + /* Address deletion is sometimes accompanied by route deletion. We need to + * check all routes belonging to the same interface. */ + if (cache_op == NMP_CACHE_OPS_REMOVED) { + delayed_action_schedule(platform, + (klass->obj_type == NMP_OBJECT_TYPE_IP4_ADDRESS) + ? DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES + : DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES, + NULL); + } + } break; + default: + break; + } } /*****************************************************************************/ static guint32 -_nlh_seq_next_get (NMLinuxPlatformPrivate *priv) +_nlh_seq_next_get(NMLinuxPlatformPrivate *priv) { - /* generate a new sequence number, but never return zero. - * Wrapping numbers are not a problem, because we don't rely - * on strictly increasing sequence numbers. */ - return (++priv->nlh_seq_next) ?: (++priv->nlh_seq_next); + /* generate a new sequence number, but never return zero. + * Wrapping numbers are not a problem, because we don't rely + * on strictly increasing sequence numbers. */ + return (++priv->nlh_seq_next) ?: (++priv->nlh_seq_next); } /** @@ -6209,57 +6476,60 @@ _nlh_seq_next_get (NMLinuxPlatformPrivate *priv) * Returns: 0 on success or a negative errno. */ static int -_nl_send_nlmsghdr (NMPlatform *platform, - struct nlmsghdr *nlhdr, - WaitForNlResponseResult *out_seq_result, - char **out_errmsg, - DelayedActionWaitForNlResponseType response_type, - gpointer response_out_data) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - guint32 seq; - int errsv; - - nm_assert (nlhdr); - - seq = _nlh_seq_next_get (priv); - nlhdr->nlmsg_seq = seq; - - { - struct sockaddr_nl nladdr = { - .nl_family = AF_NETLINK, - }; - struct iovec iov = { - .iov_base = nlhdr, - .iov_len = nlhdr->nlmsg_len - }; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof (nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - int try_count; - - if (!nlhdr->nlmsg_pid) - nlhdr->nlmsg_pid = nl_socket_get_local_port (priv->nlh); - nlhdr->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK); - - try_count = 0; +_nl_send_nlmsghdr(NMPlatform * platform, + struct nlmsghdr * nlhdr, + WaitForNlResponseResult * out_seq_result, + char ** out_errmsg, + DelayedActionWaitForNlResponseType response_type, + gpointer response_out_data) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + guint32 seq; + int errsv; + + nm_assert(nlhdr); + + seq = _nlh_seq_next_get(priv); + nlhdr->nlmsg_seq = seq; + + { + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK, + }; + struct iovec iov = {.iov_base = nlhdr, .iov_len = nlhdr->nlmsg_len}; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + int try_count; + + if (!nlhdr->nlmsg_pid) + nlhdr->nlmsg_pid = nl_socket_get_local_port(priv->nlh); + nlhdr->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK); + + try_count = 0; again: - errsv = sendmsg (nl_socket_get_fd (priv->nlh), &msg, 0); - if (errsv < 0) { - errsv = errno; - if (errsv == EINTR && try_count++ < 100) - goto again; - _LOGD ("netlink: nl-send-nlmsghdr: failed sending message: %s (%d)", nm_strerror_native (errsv), errsv); - return -nm_errno_from_native (errsv); - } - } - - delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result, out_errmsg, - response_type, response_out_data); - return 0; + errsv = sendmsg(nl_socket_get_fd(priv->nlh), &msg, 0); + if (errsv < 0) { + errsv = errno; + if (errsv == EINTR && try_count++ < 100) + goto again; + _LOGD("netlink: nl-send-nlmsghdr: failed sending message: %s (%d)", + nm_strerror_native(errsv), + errsv); + return -nm_errno_from_native(errsv); + } + } + + delayed_action_schedule_WAIT_FOR_NL_RESPONSE(platform, + seq, + out_seq_result, + out_errmsg, + response_type, + response_out_data); + return 0; } /** @@ -6273,3107 +6543,3142 @@ again: * Returns: 0 on success, or a negative libnl3 error code (beware, it's not an errno). */ static int -_nl_send_nlmsg (NMPlatform *platform, - struct nl_msg *nlmsg, - WaitForNlResponseResult *out_seq_result, - char **out_errmsg, - DelayedActionWaitForNlResponseType response_type, - gpointer response_out_data) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - struct nlmsghdr *nlhdr; - guint32 seq; - int nle; - - nlhdr = nlmsg_hdr (nlmsg); - seq = _nlh_seq_next_get (priv); - nlhdr->nlmsg_seq = seq; - - nle = nl_send_auto (priv->nlh, nlmsg); - if (nle < 0) { - _LOGD ("netlink: nl-send-nlmsg: failed sending message: %s (%d)", nm_strerror (nle), nle); - return nle; - } - - delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result, out_errmsg, - response_type, response_out_data); - return 0; +_nl_send_nlmsg(NMPlatform * platform, + struct nl_msg * nlmsg, + WaitForNlResponseResult * out_seq_result, + char ** out_errmsg, + DelayedActionWaitForNlResponseType response_type, + gpointer response_out_data) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + struct nlmsghdr * nlhdr; + guint32 seq; + int nle; + + nlhdr = nlmsg_hdr(nlmsg); + seq = _nlh_seq_next_get(priv); + nlhdr->nlmsg_seq = seq; + + nle = nl_send_auto(priv->nlh, nlmsg); + if (nle < 0) { + _LOGD("netlink: nl-send-nlmsg: failed sending message: %s (%d)", nm_strerror(nle), nle); + return nle; + } + + delayed_action_schedule_WAIT_FOR_NL_RESPONSE(platform, + seq, + out_seq_result, + out_errmsg, + response_type, + response_out_data); + return 0; } static void -do_request_link_no_delayed_actions (NMPlatform *platform, int ifindex, const char *name) +do_request_link_no_delayed_actions(NMPlatform *platform, int ifindex, const char *name) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - int nle; + NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + int nle; - if (name && !name[0]) - name = NULL; + if (name && !name[0]) + name = NULL; - g_return_if_fail (ifindex > 0 || name); + g_return_if_fail(ifindex > 0 || name); - _LOGD ("do-request-link: %d %s", ifindex, name ?: ""); + _LOGD("do-request-link: %d %s", ifindex, name ?: ""); - if (ifindex > 0) { - const NMDedupMultiEntry *entry; + if (ifindex > 0) { + const NMDedupMultiEntry *entry; - entry = nmp_cache_lookup_entry_link (nm_platform_get_cache (platform), ifindex); - if (entry) { - priv->pruning[REFRESH_ALL_TYPE_LINKS] += 1; - nm_dedup_multi_entry_set_dirty (entry, TRUE); - } - } + entry = nmp_cache_lookup_entry_link(nm_platform_get_cache(platform), ifindex); + if (entry) { + priv->pruning[REFRESH_ALL_TYPE_LINKS] += 1; + nm_dedup_multi_entry_set_dirty(entry, TRUE); + } + } - event_handler_read_netlink (platform, FALSE); + event_handler_read_netlink(platform, FALSE); - nlmsg = _nl_msg_new_link (RTM_GETLINK, - 0, - ifindex, - name); - if (nlmsg) { - nle = _nl_send_nlmsg (platform, nlmsg, NULL, NULL, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE ("do-request-link: %d %s: failed sending netlink request \"%s\" (%d)", - ifindex, name ?: "", - nm_strerror (nle), -nle); - return; - } - } + nlmsg = _nl_msg_new_link(RTM_GETLINK, 0, ifindex, name); + if (nlmsg) { + nle = _nl_send_nlmsg(platform, nlmsg, NULL, NULL, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); + if (nle < 0) { + _LOGE("do-request-link: %d %s: failed sending netlink request \"%s\" (%d)", + ifindex, + name ?: "", + nm_strerror(nle), + -nle); + return; + } + } } static void -do_request_link (NMPlatform *platform, int ifindex, const char *name) +do_request_link(NMPlatform *platform, int ifindex, const char *name) { - do_request_link_no_delayed_actions (platform, ifindex, name); - delayed_action_handle_all (platform, FALSE); + do_request_link_no_delayed_actions(platform, ifindex, name); + delayed_action_handle_all(platform, FALSE); } static struct nl_msg * -_nl_msg_new_dump (NMPObjectType obj_type, - int preferred_addr_family) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const NMPClass *klass; - - klass = nmp_class_from_type (obj_type); - - nm_assert (klass); - nm_assert (klass->rtm_gettype > 0); - - nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP); - - if (klass->addr_family != AF_UNSPEC) { - /* if the class specifies a particular address family, then it is preferred. */ - nm_assert (NM_IN_SET (preferred_addr_family, AF_UNSPEC, klass->addr_family)); - preferred_addr_family = klass->addr_family; - } - - switch (klass->obj_type) { - case NMP_OBJECT_TYPE_QDISC: - case NMP_OBJECT_TYPE_TFILTER: - { - const struct tcmsg tcmsg = { - .tcm_family = preferred_addr_family, - }; - - if (nlmsg_append_struct (nlmsg, &tcmsg) < 0) - g_return_val_if_reached (NULL); - } - break; - case NMP_OBJECT_TYPE_LINK: - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - case NMP_OBJECT_TYPE_ROUTING_RULE: - { - const struct rtgenmsg gmsg = { - .rtgen_family = preferred_addr_family, - }; - - if (nlmsg_append_struct (nlmsg, &gmsg) < 0) - g_return_val_if_reached (NULL); - } - break; - default: - g_return_val_if_reached (NULL); - } - - return g_steal_pointer (&nlmsg); +_nl_msg_new_dump(NMPObjectType obj_type, int preferred_addr_family) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + const NMPClass * klass; + + klass = nmp_class_from_type(obj_type); + + nm_assert(klass); + nm_assert(klass->rtm_gettype > 0); + + nlmsg = nlmsg_alloc_simple(klass->rtm_gettype, NLM_F_DUMP); + + if (klass->addr_family != AF_UNSPEC) { + /* if the class specifies a particular address family, then it is preferred. */ + nm_assert(NM_IN_SET(preferred_addr_family, AF_UNSPEC, klass->addr_family)); + preferred_addr_family = klass->addr_family; + } + + switch (klass->obj_type) { + case NMP_OBJECT_TYPE_QDISC: + case NMP_OBJECT_TYPE_TFILTER: + { + const struct tcmsg tcmsg = { + .tcm_family = preferred_addr_family, + }; + + if (nlmsg_append_struct(nlmsg, &tcmsg) < 0) + g_return_val_if_reached(NULL); + } break; + case NMP_OBJECT_TYPE_LINK: + case NMP_OBJECT_TYPE_IP4_ADDRESS: + case NMP_OBJECT_TYPE_IP6_ADDRESS: + case NMP_OBJECT_TYPE_IP4_ROUTE: + case NMP_OBJECT_TYPE_IP6_ROUTE: + case NMP_OBJECT_TYPE_ROUTING_RULE: + { + const struct rtgenmsg gmsg = { + .rtgen_family = preferred_addr_family, + }; + + if (nlmsg_append_struct(nlmsg, &gmsg) < 0) + g_return_val_if_reached(NULL); + } break; + default: + g_return_val_if_reached(NULL); + } + + return g_steal_pointer(&nlmsg); } static void -do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType action_type) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - DelayedActionType action_type_prune; - DelayedActionType iflags; - - nm_assert (!NM_FLAGS_ANY (action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL)); - action_type &= DELAYED_ACTION_TYPE_REFRESH_ALL; - - action_type_prune = action_type; - - /* calling nmp_cache_dirty_set_all_main() with a non-main lookup-index requires an extra - * cache lookup for every entry. - * - * Avoid that, by special casing routing-rules here. */ - if (NM_FLAGS_ALL (action_type_prune, DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL)) { - NMPLookup lookup; - - priv->pruning[REFRESH_ALL_TYPE_ROUTING_RULES_IP4] += 1; - priv->pruning[REFRESH_ALL_TYPE_ROUTING_RULES_IP6] += 1; - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - nmp_cache_dirty_set_all_main (nm_platform_get_cache (platform), - &lookup); - action_type_prune &= ~DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL; - } - - FOR_EACH_DELAYED_ACTION (iflags, action_type_prune) { - RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type (iflags); - NMPLookup lookup; - - priv->pruning[refresh_all_type] += 1; - refresh_all_type_init_lookup (refresh_all_type, - &lookup); - nmp_cache_dirty_set_all_main (nm_platform_get_cache (platform), - &lookup); - } - - FOR_EACH_DELAYED_ACTION (iflags, action_type) { - RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type (iflags); - const RefreshAllInfo *refresh_all_info = refresh_all_type_get_info (refresh_all_type); - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - int *out_refresh_all_in_progress; - - out_refresh_all_in_progress = &priv->delayed_action.refresh_all_in_progress[refresh_all_type]; - nm_assert (*out_refresh_all_in_progress >= 0); - *out_refresh_all_in_progress += 1; - - /* clear any delayed action that request a refresh of this object type. */ - priv->delayed_action.flags &= ~iflags; - _LOGt_delayed_action (iflags, NULL, "handle (do-request-all)"); - - if (refresh_all_type == REFRESH_ALL_TYPE_LINKS) { - nm_assert ( (priv->delayed_action.list_refresh_link->len > 0) - == NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)); - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)) { - _LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, NULL, "clear (do-request-all)"); - priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; - g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0); - } - } - - event_handler_read_netlink (platform, FALSE); - - nlmsg = _nl_msg_new_dump (refresh_all_info->obj_type, - refresh_all_info->addr_family); - if (!nlmsg) - goto next_after_fail; - - if (_nl_send_nlmsg (platform, - nlmsg, - NULL, - NULL, - DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS, - out_refresh_all_in_progress) < 0) - goto next_after_fail; - - continue; +do_request_all_no_delayed_actions(NMPlatform *platform, DelayedActionType action_type) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + DelayedActionType action_type_prune; + DelayedActionType iflags; + + nm_assert(!NM_FLAGS_ANY(action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL)); + action_type &= DELAYED_ACTION_TYPE_REFRESH_ALL; + + action_type_prune = action_type; + + /* calling nmp_cache_dirty_set_all_main() with a non-main lookup-index requires an extra + * cache lookup for every entry. + * + * Avoid that, by special casing routing-rules here. */ + if (NM_FLAGS_ALL(action_type_prune, DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL)) { + NMPLookup lookup; + + priv->pruning[REFRESH_ALL_TYPE_ROUTING_RULES_IP4] += 1; + priv->pruning[REFRESH_ALL_TYPE_ROUTING_RULES_IP6] += 1; + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); + nmp_cache_dirty_set_all_main(nm_platform_get_cache(platform), &lookup); + action_type_prune &= ~DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL; + } + + FOR_EACH_DELAYED_ACTION(iflags, action_type_prune) + { + RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type(iflags); + NMPLookup lookup; + + priv->pruning[refresh_all_type] += 1; + refresh_all_type_init_lookup(refresh_all_type, &lookup); + nmp_cache_dirty_set_all_main(nm_platform_get_cache(platform), &lookup); + } + + FOR_EACH_DELAYED_ACTION(iflags, action_type) + { + RefreshAllType refresh_all_type = delayed_action_type_to_refresh_all_type(iflags); + const RefreshAllInfo *refresh_all_info = refresh_all_type_get_info(refresh_all_type); + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + int * out_refresh_all_in_progress; + + out_refresh_all_in_progress = + &priv->delayed_action.refresh_all_in_progress[refresh_all_type]; + nm_assert(*out_refresh_all_in_progress >= 0); + *out_refresh_all_in_progress += 1; + + /* clear any delayed action that request a refresh of this object type. */ + priv->delayed_action.flags &= ~iflags; + _LOGt_delayed_action(iflags, NULL, "handle (do-request-all)"); + + if (refresh_all_type == REFRESH_ALL_TYPE_LINKS) { + nm_assert( + (priv->delayed_action.list_refresh_link->len > 0) + == NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)); + if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK)) { + _LOGt_delayed_action(DELAYED_ACTION_TYPE_REFRESH_LINK, + NULL, + "clear (do-request-all)"); + priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK; + g_ptr_array_set_size(priv->delayed_action.list_refresh_link, 0); + } + } + + event_handler_read_netlink(platform, FALSE); + + nlmsg = _nl_msg_new_dump(refresh_all_info->obj_type, refresh_all_info->addr_family); + if (!nlmsg) + goto next_after_fail; + + if (_nl_send_nlmsg(platform, + nlmsg, + NULL, + NULL, + DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS, + out_refresh_all_in_progress) + < 0) + goto next_after_fail; + + continue; next_after_fail: - nm_assert (*out_refresh_all_in_progress > 0); - *out_refresh_all_in_progress -= 1; - } + nm_assert(*out_refresh_all_in_progress > 0); + *out_refresh_all_in_progress -= 1; + } } static void -do_request_one_type_by_needle_object (NMPlatform *platform, const NMPObject *obj_needle) +do_request_one_type_by_needle_object(NMPlatform *platform, const NMPObject *obj_needle) { - do_request_all_no_delayed_actions (platform, delayed_action_refresh_from_needle_object (obj_needle)); - delayed_action_handle_all (platform, FALSE); + do_request_all_no_delayed_actions(platform, + delayed_action_refresh_from_needle_object(obj_needle)); + delayed_action_handle_all(platform, FALSE); } static void -event_seq_check_refresh_all (NMPlatform *platform, guint32 seq_number) +event_seq_check_refresh_all(NMPlatform *platform, guint32 seq_number) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - DelayedActionWaitForNlResponseData *data; - guint i; + NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + DelayedActionWaitForNlResponseData *data; + guint i; - if (NM_IN_SET (seq_number, 0, priv->nlh_seq_last_seen)) - return; + if (NM_IN_SET(seq_number, 0, priv->nlh_seq_last_seen)) + return; - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - nm_assert (priv->delayed_action.list_wait_for_nl_response->len > 0); + if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { + nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { - data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i); + for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { + data = &g_array_index(priv->delayed_action.list_wait_for_nl_response, + DelayedActionWaitForNlResponseData, + i); - if ( data->response_type == DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS - && data->response.out_refresh_all_in_progress - && data->seq_number == priv->nlh_seq_last_seen) { - *data->response.out_refresh_all_in_progress -= 1; - data->response.out_refresh_all_in_progress = NULL; - break; - } - } - } + if (data->response_type == DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS + && data->response.out_refresh_all_in_progress + && data->seq_number == priv->nlh_seq_last_seen) { + *data->response.out_refresh_all_in_progress -= 1; + data->response.out_refresh_all_in_progress = NULL; + break; + } + } + } - priv->nlh_seq_last_seen = seq_number; + priv->nlh_seq_last_seen = seq_number; } static void -event_seq_check (NMPlatform *platform, guint32 seq_number, WaitForNlResponseResult seq_result, const char *msg) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - DelayedActionWaitForNlResponseData *data; - guint i; - - if (seq_number == 0) - return; - - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - nm_assert (priv->delayed_action.list_wait_for_nl_response->len > 0); - - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { - data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i); - - if (data->seq_number == seq_number) { - /* We potentially receive many parts partial responses for the same sequence number. - * Thus, we only remember the result, and collect it later. */ - if (data->seq_result < 0) { - /* we already saw an error for this sequence number. - * Preserve it. */ - } else if ( seq_result != WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN - || data->seq_result == WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) - data->seq_result = seq_result; - if (data->out_errmsg && !*data->out_errmsg) - *data->out_errmsg = g_strdup (msg); - return; - } - } - } +event_seq_check(NMPlatform * platform, + guint32 seq_number, + WaitForNlResponseResult seq_result, + const char * msg) +{ + NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + DelayedActionWaitForNlResponseData *data; + guint i; + + if (seq_number == 0) + return; + + if (NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { + nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); + + for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { + data = &g_array_index(priv->delayed_action.list_wait_for_nl_response, + DelayedActionWaitForNlResponseData, + i); + + if (data->seq_number == seq_number) { + /* We potentially receive many parts partial responses for the same sequence number. + * Thus, we only remember the result, and collect it later. */ + if (data->seq_result < 0) { + /* we already saw an error for this sequence number. + * Preserve it. */ + } else if (seq_result != WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN + || data->seq_result == WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) + data->seq_result = seq_result; + if (data->out_errmsg && !*data->out_errmsg) + *data->out_errmsg = g_strdup(msg); + return; + } + } + } #if NM_MORE_LOGGING - if (seq_number != priv->nlh_seq_last_handled) - _LOGt ("netlink: recvmsg: unwaited sequence number %u", seq_number); - priv->nlh_seq_last_handled = seq_number; + if (seq_number != priv->nlh_seq_last_handled) + _LOGt("netlink: recvmsg: unwaited sequence number %u", seq_number); + priv->nlh_seq_last_handled = seq_number; #endif } static void -event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_events) -{ - NMLinuxPlatformPrivate *priv; - nm_auto_nmpobj NMPObject *obj = NULL; - NMPCacheOpsType cache_op; - struct nlmsghdr *msghdr; - char buf_nlmsghdr[400]; - gboolean is_del = FALSE; - gboolean is_dump = FALSE; - NMPCache *cache = nm_platform_get_cache (platform); - - msghdr = nlmsg_hdr (msg); - - if ( !_nm_platform_kernel_support_detected (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) - && msghdr->nlmsg_type == RTM_NEWADDR) { - /* IFA_FLAGS is set for IPv4 and IPv6 addresses. It was added first to IPv6, - * but if we encounter an IPv4 address with IFA_FLAGS, we surely have support. */ - if ( nlmsg_valid_hdr (msghdr, sizeof (struct ifaddrmsg)) - && NM_IN_SET (((struct ifaddrmsg *) nlmsg_data (msghdr))->ifa_family, - AF_INET, - AF_INET6)) { - /* see if the nl_msg contains the IFA_FLAGS attribute. If it does, - * we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR - * and IFA_F_NOPREFIXROUTE for IPv6. They were added together in kernel 3.14, - * dated 30 March, 2014. - * - * For IPv4, IFA_F_NOPREFIXROUTE was added later, but there is no easy - * way to detect kernel support. */ - _nm_platform_kernel_support_init (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS, - !!nlmsg_find_attr (msghdr, sizeof (struct ifaddrmsg), IFA_FLAGS) - ? 1 - : -1); - } - } - - if (!handle_events) - return; - - if (NM_IN_SET (msghdr->nlmsg_type, RTM_DELLINK, - RTM_DELADDR, - RTM_DELROUTE, - RTM_DELRULE, - RTM_DELQDISC, - RTM_DELTFILTER)) { - /* The event notifies about a deleted object. We don't need to initialize all - * fields of the object. */ - is_del = TRUE; - } - - obj = nmp_object_new_from_nl (platform, cache, msg, is_del); - if (!obj) { - _LOGT ("event-notification: %s: ignore", - nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr))); - return; - } - - if ( !is_del - && NM_IN_SET (msghdr->nlmsg_type, RTM_NEWADDR, - RTM_NEWLINK, - RTM_NEWROUTE, - RTM_NEWRULE, - RTM_NEWQDISC, - RTM_NEWTFILTER)) { - is_dump = delayed_action_refresh_all_in_progress (platform, - delayed_action_refresh_from_needle_object (obj)); - } - - _LOGT ("event-notification: %s%s: %s", - nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)), - is_dump ? ", in-dump" : "", - nmp_object_to_string (obj, - is_del ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC, - NULL, 0)); - - { - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - - switch (msghdr->nlmsg_type) { - - case RTM_GETLINK: - case RTM_NEWADDR: - case RTM_NEWLINK: - case RTM_NEWQDISC: - case RTM_NEWRULE: - case RTM_NEWTFILTER: - cache_op = nmp_cache_update_netlink (cache, obj, is_dump, &obj_old, &obj_new); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - cache_on_change (platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); - } - break; - - case RTM_NEWROUTE: { - nm_auto_nmpobj const NMPObject *obj_replace = NULL; - gboolean resync_required = FALSE; - gboolean only_dirty = FALSE; - gboolean is_ipv6; - - /* IPv4 routes that are a response to RTM_GETROUTE must have - * the cloned flag while IPv6 routes don't have to. */ - is_ipv6 = NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP6_ROUTE; - if (is_ipv6 || NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED)) { - nm_assert (is_ipv6 || !nmp_object_is_alive (obj)); - priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { - guint i; - - nm_assert (priv->delayed_action.list_wait_for_nl_response->len > 0); - for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { - DelayedActionWaitForNlResponseData *data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i); - - if ( data->response_type == DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET - && data->response.out_route_get) { - nm_assert (!*data->response.out_route_get); - if (data->seq_number == nlmsg_hdr (msg)->nlmsg_seq) { - *data->response.out_route_get = nmp_object_clone (obj, FALSE); - data->response.out_route_get = NULL; - break; - } - } - } - } - } - - cache_op = nmp_cache_update_netlink_route (cache, - obj, - is_dump, - msghdr->nlmsg_flags, - &obj_old, - &obj_new, - &obj_replace, - &resync_required); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - if (obj_replace) { - const NMDedupMultiEntry *entry_replace; - - /* we found an object that is to be replaced by the RTM_NEWROUTE message. - * While we invoke the signal, the platform cache might change and invalidate - * the findings. Mitigate that (for the most part), by marking the entry as - * dirty and only delete @obj_replace if it is still dirty afterwards. - * - * Yes, there is a tiny tiny chance for still getting it wrong. But in practice, - * the signal handlers do not cause to call the platform again, so the cache - * is not really changing. -- if they would, it would anyway be dangerous to overflow - * the stack and it's not ensured that the processing of netlink messages is - * reentrant (maybe it is). - */ - entry_replace = nmp_cache_lookup_entry (cache, obj_replace); - nm_assert (entry_replace && entry_replace->obj == obj_replace); - nm_dedup_multi_entry_set_dirty (entry_replace, TRUE); - only_dirty = TRUE; - } - cache_on_change (platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); - } - - if (obj_replace) { - /* the RTM_NEWROUTE message indicates that another route was replaced. - * Remove it now. */ - cache_op = nmp_cache_remove (cache, obj_replace, TRUE, only_dirty, NULL); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - nm_assert (cache_op == NMP_CACHE_OPS_REMOVED); - cache_on_change (platform, cache_op, obj_replace, NULL); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_replace, NULL); - } - } - - if (resync_required) { - /* we'd like to avoid such resyncs as they are expensive and we should only rely on the - * netlink events. This needs investigation. */ - _LOGT ("schedule resync of routes after RTM_NEWROUTE"); - delayed_action_schedule (platform, - delayed_action_refresh_from_needle_object (obj), - NULL); - } - break; - } - - case RTM_DELADDR: - case RTM_DELLINK: - case RTM_DELQDISC: - case RTM_DELROUTE: - case RTM_DELRULE: - case RTM_DELTFILTER: - cache_op = nmp_cache_remove_netlink (cache, obj, &obj_old, &obj_new); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - cache_on_change (platform, cache_op, obj_old, obj_new); - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); - } - break; - default: - break; - } - } +event_valid_msg(NMPlatform *platform, struct nl_msg *msg, gboolean handle_events) +{ + NMLinuxPlatformPrivate *priv; + nm_auto_nmpobj NMPObject *obj = NULL; + NMPCacheOpsType cache_op; + struct nlmsghdr * msghdr; + char buf_nlmsghdr[400]; + gboolean is_del = FALSE; + gboolean is_dump = FALSE; + NMPCache * cache = nm_platform_get_cache(platform); + + msghdr = nlmsg_hdr(msg); + + if (!_nm_platform_kernel_support_detected(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) + && msghdr->nlmsg_type == RTM_NEWADDR) { + /* IFA_FLAGS is set for IPv4 and IPv6 addresses. It was added first to IPv6, + * but if we encounter an IPv4 address with IFA_FLAGS, we surely have support. */ + if (nlmsg_valid_hdr(msghdr, sizeof(struct ifaddrmsg)) + && NM_IN_SET(((struct ifaddrmsg *) nlmsg_data(msghdr))->ifa_family, + AF_INET, + AF_INET6)) { + /* see if the nl_msg contains the IFA_FLAGS attribute. If it does, + * we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR + * and IFA_F_NOPREFIXROUTE for IPv6. They were added together in kernel 3.14, + * dated 30 March, 2014. + * + * For IPv4, IFA_F_NOPREFIXROUTE was added later, but there is no easy + * way to detect kernel support. */ + _nm_platform_kernel_support_init( + NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS, + !!nlmsg_find_attr(msghdr, sizeof(struct ifaddrmsg), IFA_FLAGS) ? 1 : -1); + } + } + + if (!handle_events) + return; + + if (NM_IN_SET(msghdr->nlmsg_type, + RTM_DELLINK, + RTM_DELADDR, + RTM_DELROUTE, + RTM_DELRULE, + RTM_DELQDISC, + RTM_DELTFILTER)) { + /* The event notifies about a deleted object. We don't need to initialize all + * fields of the object. */ + is_del = TRUE; + } + + obj = nmp_object_new_from_nl(platform, cache, msg, is_del); + if (!obj) { + _LOGT("event-notification: %s: ignore", + nl_nlmsghdr_to_str(msghdr, buf_nlmsghdr, sizeof(buf_nlmsghdr))); + return; + } + + if (!is_del + && NM_IN_SET(msghdr->nlmsg_type, + RTM_NEWADDR, + RTM_NEWLINK, + RTM_NEWROUTE, + RTM_NEWRULE, + RTM_NEWQDISC, + RTM_NEWTFILTER)) { + is_dump = + delayed_action_refresh_all_in_progress(platform, + delayed_action_refresh_from_needle_object(obj)); + } + + _LOGT("event-notification: %s%s: %s", + nl_nlmsghdr_to_str(msghdr, buf_nlmsghdr, sizeof(buf_nlmsghdr)), + is_dump ? ", in-dump" : "", + nmp_object_to_string(obj, + is_del ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC, + NULL, + 0)); + + { + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + + switch (msghdr->nlmsg_type) { + case RTM_GETLINK: + case RTM_NEWADDR: + case RTM_NEWLINK: + case RTM_NEWQDISC: + case RTM_NEWRULE: + case RTM_NEWTFILTER: + cache_op = nmp_cache_update_netlink(cache, obj, is_dump, &obj_old, &obj_new); + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + cache_on_change(platform, cache_op, obj_old, obj_new); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); + } + break; + + case RTM_NEWROUTE: + { + nm_auto_nmpobj const NMPObject *obj_replace = NULL; + gboolean resync_required = FALSE; + gboolean only_dirty = FALSE; + gboolean is_ipv6; + + /* IPv4 routes that are a response to RTM_GETROUTE must have + * the cloned flag while IPv6 routes don't have to. */ + is_ipv6 = NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP6_ROUTE; + if (is_ipv6 || NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, RTM_F_CLONED)) { + nm_assert(is_ipv6 || !nmp_object_is_alive(obj)); + priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + if (NM_FLAGS_HAS(priv->delayed_action.flags, + DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) { + guint i; + + nm_assert(priv->delayed_action.list_wait_for_nl_response->len > 0); + for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) { + DelayedActionWaitForNlResponseData *data = + &g_array_index(priv->delayed_action.list_wait_for_nl_response, + DelayedActionWaitForNlResponseData, + i); + + if (data->response_type == DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET + && data->response.out_route_get) { + nm_assert(!*data->response.out_route_get); + if (data->seq_number == nlmsg_hdr(msg)->nlmsg_seq) { + *data->response.out_route_get = nmp_object_clone(obj, FALSE); + data->response.out_route_get = NULL; + break; + } + } + } + } + } + + cache_op = nmp_cache_update_netlink_route(cache, + obj, + is_dump, + msghdr->nlmsg_flags, + &obj_old, + &obj_new, + &obj_replace, + &resync_required); + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + if (obj_replace) { + const NMDedupMultiEntry *entry_replace; + + /* we found an object that is to be replaced by the RTM_NEWROUTE message. + * While we invoke the signal, the platform cache might change and invalidate + * the findings. Mitigate that (for the most part), by marking the entry as + * dirty and only delete @obj_replace if it is still dirty afterwards. + * + * Yes, there is a tiny tiny chance for still getting it wrong. But in practice, + * the signal handlers do not cause to call the platform again, so the cache + * is not really changing. -- if they would, it would anyway be dangerous to overflow + * the stack and it's not ensured that the processing of netlink messages is + * reentrant (maybe it is). + */ + entry_replace = nmp_cache_lookup_entry(cache, obj_replace); + nm_assert(entry_replace && entry_replace->obj == obj_replace); + nm_dedup_multi_entry_set_dirty(entry_replace, TRUE); + only_dirty = TRUE; + } + cache_on_change(platform, cache_op, obj_old, obj_new); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); + } + + if (obj_replace) { + /* the RTM_NEWROUTE message indicates that another route was replaced. + * Remove it now. */ + cache_op = nmp_cache_remove(cache, obj_replace, TRUE, only_dirty, NULL); + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + nm_assert(cache_op == NMP_CACHE_OPS_REMOVED); + cache_on_change(platform, cache_op, obj_replace, NULL); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_replace, NULL); + } + } + + if (resync_required) { + /* we'd like to avoid such resyncs as they are expensive and we should only rely on the + * netlink events. This needs investigation. */ + _LOGT("schedule resync of routes after RTM_NEWROUTE"); + delayed_action_schedule(platform, + delayed_action_refresh_from_needle_object(obj), + NULL); + } + break; + } + + case RTM_DELADDR: + case RTM_DELLINK: + case RTM_DELQDISC: + case RTM_DELROUTE: + case RTM_DELRULE: + case RTM_DELTFILTER: + cache_op = nmp_cache_remove_netlink(cache, obj, &obj_old, &obj_new); + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + cache_on_change(platform, cache_op, obj_old, obj_new); + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); + } + break; + default: + break; + } + } } /*****************************************************************************/ static int -do_add_link_with_lookup (NMPlatform *platform, - NMLinkType link_type, - const char *name, - struct nl_msg *nlmsg, - const NMPlatformLink **out_link) -{ - const NMPObject *obj = NULL; - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char *errmsg = NULL; - int nle; - char s_buf[256]; - NMPCache *cache = nm_platform_get_cache (platform); - - event_handler_read_netlink (platform, FALSE); - - nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, &errmsg, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE ("do-add-link[%s/%s]: failed sending netlink request \"%s\" (%d)", - name, - nm_link_type_to_string (link_type), - nm_strerror (nle), -nle); - NM_SET_OUT (out_link, NULL); - return nle; - } - - delayed_action_handle_all (platform, FALSE); - - nm_assert (seq_result); - - _NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK - ? LOGL_DEBUG - : LOGL_WARN, - "do-add-link[%s/%s]: %s", - name, - nm_link_type_to_string (link_type), - wait_for_nl_response_to_string (seq_result, errmsg, s_buf, sizeof (s_buf))); - - if (out_link) { - obj = nmp_cache_lookup_link_full (cache, 0, name, FALSE, link_type, NULL, NULL); - *out_link = NMP_OBJECT_CAST_LINK (obj); - } - - return wait_for_nl_response_to_nmerr (seq_result); +do_add_link_with_lookup(NMPlatform * platform, + NMLinkType link_type, + const char * name, + struct nl_msg * nlmsg, + const NMPlatformLink **out_link) +{ + const NMPObject * obj = NULL; + WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + gs_free char * errmsg = NULL; + int nle; + char s_buf[256]; + NMPCache * cache = nm_platform_get_cache(platform); + + event_handler_read_netlink(platform, FALSE); + + nle = _nl_send_nlmsg(platform, + nlmsg, + &seq_result, + &errmsg, + DELAYED_ACTION_RESPONSE_TYPE_VOID, + NULL); + if (nle < 0) { + _LOGE("do-add-link[%s/%s]: failed sending netlink request \"%s\" (%d)", + name, + nm_link_type_to_string(link_type), + nm_strerror(nle), + -nle); + NM_SET_OUT(out_link, NULL); + return nle; + } + + delayed_action_handle_all(platform, FALSE); + + nm_assert(seq_result); + + _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, + "do-add-link[%s/%s]: %s", + name, + nm_link_type_to_string(link_type), + wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); + + if (out_link) { + obj = nmp_cache_lookup_link_full(cache, 0, name, FALSE, link_type, NULL, NULL); + *out_link = NMP_OBJECT_CAST_LINK(obj); + } + + return wait_for_nl_response_to_nmerr(seq_result); } static int -do_add_addrroute (NMPlatform *platform, - const NMPObject *obj_id, - struct nl_msg *nlmsg, - gboolean suppress_netlink_failure) -{ - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char *errmsg = NULL; - int nle; - char s_buf[256]; - - nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id), - NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - - event_handler_read_netlink (platform, FALSE); - - nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, &errmsg, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE ("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)", - NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, - nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - nm_strerror (nle), -nle); - return -NME_PL_NETLINK; - } - - delayed_action_handle_all (platform, FALSE); - - nm_assert (seq_result); - - _NMLOG (( seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK - || ( suppress_netlink_failure - && seq_result < 0)) - ? LOGL_DEBUG - : LOGL_WARN, - "do-add-%s[%s]: %s", - NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, - nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - wait_for_nl_response_to_string (seq_result, errmsg, s_buf, sizeof (s_buf))); - - if (NMP_OBJECT_GET_TYPE (obj_id) == NMP_OBJECT_TYPE_IP6_ADDRESS) { - /* In rare cases, the object is not yet ready as we received the ACK from - * kernel. Need to refetch. - * - * We want to safe the expensive refetch, thus we look first into the cache - * whether the object exists. - * - * rh#1484434 */ - if (!nmp_cache_lookup_obj (nm_platform_get_cache (platform), obj_id)) - do_request_one_type_by_needle_object (platform, obj_id); - } - - return wait_for_nl_response_to_nmerr (seq_result); +do_add_addrroute(NMPlatform * platform, + const NMPObject *obj_id, + struct nl_msg * nlmsg, + gboolean suppress_netlink_failure) +{ + WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + gs_free char * errmsg = NULL; + int nle; + char s_buf[256]; + + nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE)); + + event_handler_read_netlink(platform, FALSE); + + nle = _nl_send_nlmsg(platform, + nlmsg, + &seq_result, + &errmsg, + DELAYED_ACTION_RESPONSE_TYPE_VOID, + NULL); + if (nle < 0) { + _LOGE("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)", + NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, + nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), + nm_strerror(nle), + -nle); + return -NME_PL_NETLINK; + } + + delayed_action_handle_all(platform, FALSE); + + nm_assert(seq_result); + + _NMLOG((seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK + || (suppress_netlink_failure && seq_result < 0)) + ? LOGL_DEBUG + : LOGL_WARN, + "do-add-%s[%s]: %s", + NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, + nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), + wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); + + if (NMP_OBJECT_GET_TYPE(obj_id) == NMP_OBJECT_TYPE_IP6_ADDRESS) { + /* In rare cases, the object is not yet ready as we received the ACK from + * kernel. Need to refetch. + * + * We want to safe the expensive refetch, thus we look first into the cache + * whether the object exists. + * + * rh#1484434 */ + if (!nmp_cache_lookup_obj(nm_platform_get_cache(platform), obj_id)) + do_request_one_type_by_needle_object(platform, obj_id); + } + + return wait_for_nl_response_to_nmerr(seq_result); } static gboolean -do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *nlmsg) -{ - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char *errmsg = NULL; - int nle; - char s_buf[256]; - gboolean success; - const char *log_detail = ""; - - event_handler_read_netlink (platform, FALSE); - - nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, &errmsg, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE ("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)", - NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, - nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - nm_strerror (nle), -nle); - return FALSE; - } - - delayed_action_handle_all (platform, FALSE); - - nm_assert (seq_result); - - success = TRUE; - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { - /* ok */ - } else if (NM_IN_SET (-((int) seq_result), ESRCH, ENOENT)) - log_detail = ", meaning the object was already removed"; - else if ( NM_IN_SET (-((int) seq_result), ENXIO) - && NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id), NMP_OBJECT_TYPE_IP6_ADDRESS)) { - /* On RHEL7 kernel, deleting a non existing address fails with ENXIO */ - log_detail = ", meaning the address was already removed"; - } else if ( NM_IN_SET (-((int) seq_result), EADDRNOTAVAIL) - && NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id), NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)) - log_detail = ", meaning the address was already removed"; - else - success = FALSE; - - _NMLOG (success ? LOGL_DEBUG : LOGL_WARN, - "do-delete-%s[%s]: %s%s", - NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, - nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), - wait_for_nl_response_to_string (seq_result, errmsg, s_buf, sizeof (s_buf)), - log_detail); - - if (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id), - NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER)) { - /* In rare cases, the object is still there after we receive the ACK from - * kernel. Need to refetch. - * - * We want to safe the expensive refetch, thus we look first into the cache - * whether the object exists. - * - * rh#1484434 */ - if (nmp_cache_lookup_obj (nm_platform_get_cache (platform), obj_id)) - do_request_one_type_by_needle_object (platform, obj_id); - } - - return success; +do_delete_object(NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *nlmsg) +{ + WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + gs_free char * errmsg = NULL; + int nle; + char s_buf[256]; + gboolean success; + const char * log_detail = ""; + + event_handler_read_netlink(platform, FALSE); + + nle = _nl_send_nlmsg(platform, + nlmsg, + &seq_result, + &errmsg, + DELAYED_ACTION_RESPONSE_TYPE_VOID, + NULL); + if (nle < 0) { + _LOGE("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)", + NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, + nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), + nm_strerror(nle), + -nle); + return FALSE; + } + + delayed_action_handle_all(platform, FALSE); + + nm_assert(seq_result); + + success = TRUE; + if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { + /* ok */ + } else if (NM_IN_SET(-((int) seq_result), ESRCH, ENOENT)) + log_detail = ", meaning the object was already removed"; + else if (NM_IN_SET(-((int) seq_result), ENXIO) + && NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), NMP_OBJECT_TYPE_IP6_ADDRESS)) { + /* On RHEL7 kernel, deleting a non existing address fails with ENXIO */ + log_detail = ", meaning the address was already removed"; + } else if (NM_IN_SET(-((int) seq_result), EADDRNOTAVAIL) + && NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS)) + log_detail = ", meaning the address was already removed"; + else + success = FALSE; + + _NMLOG(success ? LOGL_DEBUG : LOGL_WARN, + "do-delete-%s[%s]: %s%s", + NMP_OBJECT_GET_CLASS(obj_id)->obj_type_name, + nmp_object_to_string(obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0), + wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)), + log_detail); + + if (NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_id), + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_QDISC, + NMP_OBJECT_TYPE_TFILTER)) { + /* In rare cases, the object is still there after we receive the ACK from + * kernel. Need to refetch. + * + * We want to safe the expensive refetch, thus we look first into the cache + * whether the object exists. + * + * rh#1484434 */ + if (nmp_cache_lookup_obj(nm_platform_get_cache(platform), obj_id)) + do_request_one_type_by_needle_object(platform, obj_id); + } + + return success; } static int -do_change_link (NMPlatform *platform, - ChangeLinkType change_link_type, - int ifindex, - struct nl_msg *nlmsg, - const ChangeLinkData *data) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - int nle; - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char *errmsg = NULL; - char s_buf[256]; - int result = 0; - NMLogLevel log_level = LOGL_DEBUG; - const char *log_result = "failure"; - const char *log_detail = ""; - gs_free char *log_detail_free = NULL; - const NMPObject *obj_cache; - - if (!nm_platform_netns_push (platform, &netns)) { - log_level = LOGL_ERR; - log_detail = ", failure to change network namespace"; - goto out; - } +do_change_link(NMPlatform * platform, + ChangeLinkType change_link_type, + int ifindex, + struct nl_msg * nlmsg, + const ChangeLinkData *data) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + int nle; + WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + gs_free char * errmsg = NULL; + char s_buf[256]; + int result = 0; + NMLogLevel log_level = LOGL_DEBUG; + const char * log_result = "failure"; + const char * log_detail = ""; + gs_free char * log_detail_free = NULL; + const NMPObject * obj_cache; + + if (!nm_platform_netns_push(platform, &netns)) { + log_level = LOGL_ERR; + log_detail = ", failure to change network namespace"; + goto out; + } retry: - nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, &errmsg, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - log_level = LOGL_ERR; - log_detail_free = g_strdup_printf (", failure sending netlink request: %s (%d)", - nm_strerror (nle), -nle); - log_detail = log_detail_free; - goto out; - } - - /* always refetch the link after changing it. There seems to be issues - * and we sometimes lack events. Nuke it from the orbit... */ - delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (ifindex)); - - delayed_action_handle_all (platform, FALSE); - - nm_assert (seq_result); - - if ( NM_IN_SET (-((int) seq_result), EOPNOTSUPP) - && nlmsg_hdr (nlmsg)->nlmsg_type == RTM_NEWLINK) { - nlmsg_hdr (nlmsg)->nlmsg_type = RTM_SETLINK; - goto retry; - } - - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { - log_result = "success"; - } else if (NM_IN_SET (-((int) seq_result), EEXIST, EADDRINUSE)) { - /* */ - } else if (NM_IN_SET (-((int) seq_result), ESRCH, ENOENT)) { - log_detail = ", firmware not found"; - result = -NME_PL_NO_FIRMWARE; - } else if ( NM_IN_SET (-((int) seq_result), ERANGE) - && change_link_type == CHANGE_LINK_TYPE_SET_MTU) { - log_detail = ", setting MTU to requested size is not possible"; - result = -NME_PL_CANT_SET_MTU; - } else if ( NM_IN_SET (-((int) seq_result), ENFILE) - && change_link_type == CHANGE_LINK_TYPE_SET_ADDRESS - && (obj_cache = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex)) - && obj_cache->link.l_address.len == data->set_address.length - && memcmp (obj_cache->link.l_address.data, data->set_address.address, data->set_address.length) == 0) { - /* workaround ENFILE which may be wrongly returned (bgo #770456). - * If the MAC address is as expected, assume success? */ - log_result = "success"; - log_detail = " (assume success changing address)"; - result = 0; - } else if (NM_IN_SET (-((int) seq_result), ENODEV)) { - log_level = LOGL_DEBUG; - result = -NME_PL_NOT_FOUND; - } else if (-((int) seq_result) == EAFNOSUPPORT) { - log_level = LOGL_DEBUG; - result = -NME_PL_OPNOTSUPP; - } else { - log_level = LOGL_WARN; - result = -NME_UNSPEC; - } + nle = _nl_send_nlmsg(platform, + nlmsg, + &seq_result, + &errmsg, + DELAYED_ACTION_RESPONSE_TYPE_VOID, + NULL); + if (nle < 0) { + log_level = LOGL_ERR; + log_detail_free = + g_strdup_printf(", failure sending netlink request: %s (%d)", nm_strerror(nle), -nle); + log_detail = log_detail_free; + goto out; + } + + /* always refetch the link after changing it. There seems to be issues + * and we sometimes lack events. Nuke it from the orbit... */ + delayed_action_schedule(platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER(ifindex)); + + delayed_action_handle_all(platform, FALSE); + + nm_assert(seq_result); + + if (NM_IN_SET(-((int) seq_result), EOPNOTSUPP) && nlmsg_hdr(nlmsg)->nlmsg_type == RTM_NEWLINK) { + nlmsg_hdr(nlmsg)->nlmsg_type = RTM_SETLINK; + goto retry; + } + + if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { + log_result = "success"; + } else if (NM_IN_SET(-((int) seq_result), EEXIST, EADDRINUSE)) { + /* */ + } else if (NM_IN_SET(-((int) seq_result), ESRCH, ENOENT)) { + log_detail = ", firmware not found"; + result = -NME_PL_NO_FIRMWARE; + } else if (NM_IN_SET(-((int) seq_result), ERANGE) + && change_link_type == CHANGE_LINK_TYPE_SET_MTU) { + log_detail = ", setting MTU to requested size is not possible"; + result = -NME_PL_CANT_SET_MTU; + } else if (NM_IN_SET(-((int) seq_result), ENFILE) + && change_link_type == CHANGE_LINK_TYPE_SET_ADDRESS + && (obj_cache = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex)) + && obj_cache->link.l_address.len == data->set_address.length + && memcmp(obj_cache->link.l_address.data, + data->set_address.address, + data->set_address.length) + == 0) { + /* workaround ENFILE which may be wrongly returned (bgo #770456). + * If the MAC address is as expected, assume success? */ + log_result = "success"; + log_detail = " (assume success changing address)"; + result = 0; + } else if (NM_IN_SET(-((int) seq_result), ENODEV)) { + log_level = LOGL_DEBUG; + result = -NME_PL_NOT_FOUND; + } else if (-((int) seq_result) == EAFNOSUPPORT) { + log_level = LOGL_DEBUG; + result = -NME_PL_OPNOTSUPP; + } else { + log_level = LOGL_WARN; + result = -NME_UNSPEC; + } out: - _NMLOG (log_level, - "do-change-link[%d]: %s changing link: %s%s", - ifindex, - log_result, - wait_for_nl_response_to_string (seq_result, errmsg, s_buf, sizeof (s_buf)), - log_detail); - return result; + _NMLOG(log_level, + "do-change-link[%d]: %s changing link: %s%s", + ifindex, + log_result, + wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)), + log_detail); + return result; } static int -link_add (NMPlatform *platform, - NMLinkType type, - const char *name, - int parent, - const void *address, - size_t address_len, - gconstpointer extra_data, - const NMPlatformLink **out_link) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - if (type == NM_LINK_TYPE_BOND) { - /* When the kernel loads the bond module, either via explicit modprobe - * or automatically in response to creating a bond master, it will also - * create a 'bond0' interface. Since the bond we're about to create may - * or may not be named 'bond0' prevent potential confusion about a bond - * that the user didn't want by telling the bonding module not to create - * bond0 automatically. - */ - if (!g_file_test ("/sys/class/net/bonding_masters", G_FILE_TEST_EXISTS)) - (void) nm_utils_modprobe (NULL, TRUE, "bonding", "max_bonds=0", NULL); - } - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - NLM_F_CREATE | NLM_F_EXCL, - 0, - name); - if (!nlmsg) - return -NME_UNSPEC; - - if (parent > 0) - NLA_PUT_U32 (nlmsg, IFLA_LINK, parent); - - if (address && address_len) - NLA_PUT (nlmsg, IFLA_ADDRESS, address_len, address); - - if (!_nl_msg_new_link_set_linkinfo (nlmsg, type, extra_data)) - return -NME_UNSPEC; - - return do_add_link_with_lookup (platform, type, name, nlmsg, out_link); +link_add(NMPlatform * platform, + NMLinkType type, + const char * name, + int parent, + const void * address, + size_t address_len, + gconstpointer extra_data, + const NMPlatformLink **out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + + if (type == NM_LINK_TYPE_BOND) { + /* When the kernel loads the bond module, either via explicit modprobe + * or automatically in response to creating a bond master, it will also + * create a 'bond0' interface. Since the bond we're about to create may + * or may not be named 'bond0' prevent potential confusion about a bond + * that the user didn't want by telling the bonding module not to create + * bond0 automatically. + */ + if (!g_file_test("/sys/class/net/bonding_masters", G_FILE_TEST_EXISTS)) + (void) nm_utils_modprobe(NULL, TRUE, "bonding", "max_bonds=0", NULL); + } + + nlmsg = _nl_msg_new_link(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, name); + if (!nlmsg) + return -NME_UNSPEC; + + if (parent > 0) + NLA_PUT_U32(nlmsg, IFLA_LINK, parent); + + if (address && address_len) + NLA_PUT(nlmsg, IFLA_ADDRESS, address_len, address); + + if (!_nl_msg_new_link_set_linkinfo(nlmsg, type, extra_data)) + return -NME_UNSPEC; + + return do_add_link_with_lookup(platform, type, name, nlmsg, out_link); nla_put_failure: - g_return_val_if_reached (-NME_BUG); + g_return_val_if_reached(-NME_BUG); } static gboolean -link_delete (NMPlatform *platform, int ifindex) +link_delete(NMPlatform *platform, int ifindex) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj_id; - const NMPObject *obj; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + NMPObject obj_id; + const NMPObject * obj; - obj = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex); - if (!obj || !obj->_link.netlink.is_in_netlink) - return FALSE; + obj = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); + if (!obj || !obj->_link.netlink.is_in_netlink) + return FALSE; - nlmsg = _nl_msg_new_link (RTM_DELLINK, - 0, - ifindex, - NULL); + nlmsg = _nl_msg_new_link(RTM_DELLINK, 0, ifindex, NULL); - nmp_object_stackinit_id_link (&obj_id, ifindex); - return do_delete_object (platform, &obj_id, nlmsg); + nmp_object_stackinit_id_link(&obj_id, ifindex); + return do_delete_object(platform, &obj_id, nlmsg); } static gboolean -link_refresh (NMPlatform *platform, int ifindex) +link_refresh(NMPlatform *platform, int ifindex) { - do_request_link (platform, ifindex, NULL); - return !!nm_platform_link_get_obj (platform, ifindex, TRUE); + do_request_link(platform, ifindex, NULL); + return !!nm_platform_link_get_obj(platform, ifindex, TRUE); } static gboolean -link_set_netns (NMPlatform *platform, - int ifindex, - int netns_fd) +link_set_netns(NMPlatform *platform, int ifindex, int netns_fd) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if (!nlmsg) - return FALSE; + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg) + return FALSE; - NLA_PUT (nlmsg, IFLA_NET_NS_FD, 4, &netns_fd); - return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); + NLA_PUT(nlmsg, IFLA_NET_NS_FD, 4, &netns_fd); + return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static int -link_change_flags (NMPlatform *platform, - int ifindex, - unsigned flags_mask, - unsigned flags_set) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - char s_flags[100]; - - _LOGD ("link: change %d: flags: set 0x%x/0x%x ([%s] / [%s])", - ifindex, - flags_set, - flags_mask, - nm_platform_link_flags2str (flags_set, s_flags, sizeof (s_flags)), - nm_platform_link_flags2str (flags_mask, NULL, 0)); - - nlmsg = _nl_msg_new_link_full (RTM_NEWLINK, - 0, - ifindex, - NULL, - AF_UNSPEC, - flags_mask, - flags_set); - if (!nlmsg) - return -NME_UNSPEC; - return do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL); +link_change_flags(NMPlatform *platform, int ifindex, unsigned flags_mask, unsigned flags_set) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + char s_flags[100]; + + _LOGD("link: change %d: flags: set 0x%x/0x%x ([%s] / [%s])", + ifindex, + flags_set, + flags_mask, + nm_platform_link_flags2str(flags_set, s_flags, sizeof(s_flags)), + nm_platform_link_flags2str(flags_mask, NULL, 0)); + + nlmsg = _nl_msg_new_link_full(RTM_NEWLINK, 0, ifindex, NULL, AF_UNSPEC, flags_mask, flags_set); + if (!nlmsg) + return -NME_UNSPEC; + return do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL); } static gboolean -link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware) +link_set_up(NMPlatform *platform, int ifindex, gboolean *out_no_firmware) { - int r; + int r; - r = link_change_flags (platform, ifindex, IFF_UP, IFF_UP); - NM_SET_OUT (out_no_firmware, (r == -NME_PL_NO_FIRMWARE)); - return r >= 0; + r = link_change_flags(platform, ifindex, IFF_UP, IFF_UP); + NM_SET_OUT(out_no_firmware, (r == -NME_PL_NO_FIRMWARE)); + return r >= 0; } static gboolean -link_set_down (NMPlatform *platform, int ifindex) +link_set_down(NMPlatform *platform, int ifindex) { - return (link_change_flags (platform, ifindex, IFF_UP, 0) >= 0); + return (link_change_flags(platform, ifindex, IFF_UP, 0) >= 0); } static gboolean -link_set_arp (NMPlatform *platform, int ifindex) +link_set_arp(NMPlatform *platform, int ifindex) { - return (link_change_flags (platform, ifindex, IFF_NOARP, 0) >= 0); + return (link_change_flags(platform, ifindex, IFF_NOARP, 0) >= 0); } static gboolean -link_set_noarp (NMPlatform *platform, int ifindex) +link_set_noarp(NMPlatform *platform, int ifindex) { - return (link_change_flags (platform, ifindex, IFF_NOARP, IFF_NOARP) >= 0); + return (link_change_flags(platform, ifindex, IFF_NOARP, IFF_NOARP) >= 0); } static int -link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enabled) +link_set_user_ipv6ll_enabled(NMPlatform *platform, int ifindex, gboolean enabled) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - guint8 mode = enabled ? NM_IN6_ADDR_GEN_MODE_NONE : NM_IN6_ADDR_GEN_MODE_EUI64; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + guint8 mode = enabled ? NM_IN6_ADDR_GEN_MODE_NONE : NM_IN6_ADDR_GEN_MODE_EUI64; - _LOGD ("link: change %d: user-ipv6ll: set IPv6 address generation mode to %s", - ifindex, - nm_platform_link_inet6_addrgenmode2str (mode, NULL, 0)); + _LOGD("link: change %d: user-ipv6ll: set IPv6 address generation mode to %s", + ifindex, + nm_platform_link_inet6_addrgenmode2str(mode, NULL, 0)); - if (!nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { - _LOGD ("link: change %d: user-ipv6ll: not supported", ifindex); - return -NME_PL_OPNOTSUPP; - } + if (!nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { + _LOGD("link: change %d: user-ipv6ll: not supported", ifindex); + return -NME_PL_OPNOTSUPP; + } - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if ( !nlmsg - || !_nl_msg_new_link_set_afspec (nlmsg, mode, NULL)) - g_return_val_if_reached (-NME_BUG); + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg || !_nl_msg_new_link_set_afspec(nlmsg, mode, NULL)) + g_return_val_if_reached(-NME_BUG); - return do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL); + return do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL); } static gboolean -link_set_token (NMPlatform *platform, int ifindex, NMUtilsIPv6IfaceId iid) +link_set_token(NMPlatform *platform, int ifindex, NMUtilsIPv6IfaceId iid) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - _LOGD ("link: change %d: token: set IPv6 address generation token to %s", - ifindex, nm_utils_inet6_interface_identifier_to_token (iid, sbuf)); + _LOGD("link: change %d: token: set IPv6 address generation token to %s", + ifindex, + nm_utils_inet6_interface_identifier_to_token(iid, sbuf)); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, NULL); - if (!nlmsg || !_nl_msg_new_link_set_afspec (nlmsg, -1, &iid)) - g_return_val_if_reached (FALSE); + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg || !_nl_msg_new_link_set_afspec(nlmsg, -1, &iid)) + g_return_val_if_reached(FALSE); - return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); + return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); } static gboolean -link_supports_carrier_detect (NMPlatform *platform, int ifindex) +link_supports_carrier_detect(NMPlatform *platform, int ifindex) { - nm_auto_pop_netns NMPNetns *netns = NULL; + nm_auto_pop_netns NMPNetns *netns = NULL; - if (!nm_platform_netns_push (platform, &netns)) - return FALSE; + if (!nm_platform_netns_push(platform, &netns)) + return FALSE; - /* We use netlink for the actual carrier detection, but netlink can't tell - * us whether the device actually supports carrier detection in the first - * place. We assume any device that does implements one of these two APIs. - */ - return nmp_utils_ethtool_supports_carrier_detect (ifindex) - || nmp_utils_mii_supports_carrier_detect (ifindex); + /* We use netlink for the actual carrier detection, but netlink can't tell + * us whether the device actually supports carrier detection in the first + * place. We assume any device that does implements one of these two APIs. + */ + return nmp_utils_ethtool_supports_carrier_detect(ifindex) + || nmp_utils_mii_supports_carrier_detect(ifindex); } static gboolean -link_supports_vlans (NMPlatform *platform, int ifindex) +link_supports_vlans(NMPlatform *platform, int ifindex) { - nm_auto_pop_netns NMPNetns *netns = NULL; - const NMPObject *obj; + nm_auto_pop_netns NMPNetns *netns = NULL; + const NMPObject * obj; - obj = nm_platform_link_get_obj (platform, ifindex, TRUE); + obj = nm_platform_link_get_obj(platform, ifindex, TRUE); - /* Only ARPHRD_ETHER links can possibly support VLANs. */ - if (!obj || obj->link.arptype != ARPHRD_ETHER) - return FALSE; + /* Only ARPHRD_ETHER links can possibly support VLANs. */ + if (!obj || obj->link.arptype != ARPHRD_ETHER) + return FALSE; - if (!nm_platform_netns_push (platform, &netns)) - return FALSE; + if (!nm_platform_netns_push(platform, &netns)) + return FALSE; - return nmp_utils_ethtool_supports_vlans (ifindex); + return nmp_utils_ethtool_supports_vlans(ifindex); } static gboolean -link_supports_sriov (NMPlatform *platform, int ifindex) +link_supports_sriov(NMPlatform *platform, int ifindex) { - nm_auto_pop_netns NMPNetns *netns = NULL; - nm_auto_close int dirfd = -1; - char ifname[IFNAMSIZ]; - int num = -1; + nm_auto_pop_netns NMPNetns *netns = NULL; + nm_auto_close int dirfd = -1; + char ifname[IFNAMSIZ]; + int num = -1; - if (!nm_platform_netns_push (platform, &netns)) - return FALSE; + if (!nm_platform_netns_push(platform, &netns)) + return FALSE; - dirfd = nm_platform_sysctl_open_netdir (platform, ifindex, ifname); - if (dirfd < 0) - return FALSE; + dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname); + if (dirfd < 0) + return FALSE; - num = nm_platform_sysctl_get_int32 (platform, - NMP_SYSCTL_PATHID_NETDIR (dirfd, - ifname, - "device/sriov_numvfs"), - -1); + num = + nm_platform_sysctl_get_int32(platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_numvfs"), + -1); - return num != -1; + return num != -1; } static int -link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size_t length) +link_set_address(NMPlatform *platform, int ifindex, gconstpointer address, size_t length) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const ChangeLinkData d = { - .set_address = { - .address = address, - .length = length, - }, - }; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + const ChangeLinkData d = { + .set_address = + { + .address = address, + .length = length, + }, + }; - if (!address || !length) - g_return_val_if_reached (-NME_BUG); + if (!address || !length) + g_return_val_if_reached(-NME_BUG); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if (!nlmsg) - g_return_val_if_reached (-NME_BUG); + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg) + g_return_val_if_reached(-NME_BUG); - NLA_PUT (nlmsg, IFLA_ADDRESS, length, address); + NLA_PUT(nlmsg, IFLA_ADDRESS, length, address); - return do_change_link (platform, CHANGE_LINK_TYPE_SET_ADDRESS, ifindex, nlmsg, &d); + return do_change_link(platform, CHANGE_LINK_TYPE_SET_ADDRESS, ifindex, nlmsg, &d); nla_put_failure: - g_return_val_if_reached (-NME_BUG); + g_return_val_if_reached(-NME_BUG); } static int -link_set_name (NMPlatform *platform, int ifindex, const char *name) +link_set_name(NMPlatform *platform, int ifindex, const char *name) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if (!nlmsg) - g_return_val_if_reached (-NME_BUG); + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg) + g_return_val_if_reached(-NME_BUG); - NLA_PUT (nlmsg, IFLA_IFNAME, strlen (name) + 1, name); + NLA_PUT(nlmsg, IFLA_IFNAME, strlen(name) + 1, name); - return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); + return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static gboolean -link_get_permanent_address (NMPlatform *platform, - int ifindex, - guint8 *buf, - size_t *length) +link_get_permanent_address(NMPlatform *platform, int ifindex, guint8 *buf, size_t *length) { - nm_auto_pop_netns NMPNetns *netns = NULL; + nm_auto_pop_netns NMPNetns *netns = NULL; - if (!nm_platform_netns_push (platform, &netns)) - return FALSE; + if (!nm_platform_netns_push(platform, &netns)) + return FALSE; - return nmp_utils_ethtool_get_permanent_address (ifindex, buf, length); + return nmp_utils_ethtool_get_permanent_address(ifindex, buf, length); } static int -link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu) +link_set_mtu(NMPlatform *platform, int ifindex, guint32 mtu) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if (!nlmsg) - return FALSE; + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg) + return FALSE; - NLA_PUT_U32 (nlmsg, IFLA_MTU, mtu); + NLA_PUT_U32(nlmsg, IFLA_MTU, mtu); - return do_change_link (platform, CHANGE_LINK_TYPE_SET_MTU, ifindex, nlmsg, NULL); + return do_change_link(platform, CHANGE_LINK_TYPE_SET_MTU, ifindex, nlmsg, NULL); nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static void -sriov_idle_cb (gpointer user_data, - GCancellable *cancellable) +sriov_idle_cb(gpointer user_data, GCancellable *cancellable) { - gs_unref_object NMPlatform *platform = NULL; - gs_free_error GError *cancelled_error = NULL; - gs_free_error GError *error = NULL; - NMPlatformAsyncCallback callback; - gpointer callback_data; + gs_unref_object NMPlatform *platform = NULL; + gs_free_error GError *cancelled_error = NULL; + gs_free_error GError * error = NULL; + NMPlatformAsyncCallback callback; + gpointer callback_data; - g_cancellable_set_error_if_cancelled (cancellable, &cancelled_error); - nm_utils_user_data_unpack (user_data, &platform, &error, &callback, &callback_data); - callback (cancelled_error ?: error, callback_data); + g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); + nm_utils_user_data_unpack(user_data, &platform, &error, &callback, &callback_data); + callback(cancelled_error ?: error, callback_data); } static void -link_set_sriov_params_async (NMPlatform *platform, - int ifindex, - guint num_vfs, - NMTernary autoprobe, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable *cancellable) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - gs_free_error GError *error = NULL; - nm_auto_close int dirfd = -1; - int current_autoprobe; - guint i, total; - gint64 current_num; - char ifname[IFNAMSIZ]; - gpointer packed; - const char *values[3]; - char buf[64]; - - g_return_if_fail (callback || !data); - g_return_if_fail (cancellable); - - if (!nm_platform_netns_push (platform, &netns)) { - g_set_error_literal (&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "couldn't change namespace"); - goto out_idle; - } - - dirfd = nm_platform_sysctl_open_netdir (platform, ifindex, ifname); - if (!dirfd) { - g_set_error_literal (&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "couldn't open netdir"); - goto out_idle; - } - - total = nm_platform_sysctl_get_int_checked (platform, - NMP_SYSCTL_PATHID_NETDIR (dirfd, - ifname, - "device/sriov_totalvfs"), - 10, 0, G_MAXUINT, 0); - if (!errno && num_vfs > total) { - _LOGW ("link: %d only supports %u VFs (requested %u)", ifindex, total, num_vfs); - num_vfs = total; - } - - /* - * Take special care when setting new values: - * - don't touch anything if the right values are already set - * - to change the number of VFs or autoprobe we need to destroy existing VFs - * - the autoprobe setting is irrelevant when numvfs is zero - */ - current_num = nm_platform_sysctl_get_int_checked (platform, - NMP_SYSCTL_PATHID_NETDIR (dirfd, - ifname, - "device/sriov_numvfs"), - 10, 0, G_MAXUINT, -1); - current_autoprobe = nm_platform_sysctl_get_int_checked (platform, - NMP_SYSCTL_PATHID_NETDIR (dirfd, - ifname, - "device/sriov_drivers_autoprobe"), - 10, 0, 1, -1); - - if ( current_autoprobe == -1 - && errno == ENOENT) { - /* older kernel versions don't have this sysctl. Assume the value is - * "1". */ - current_autoprobe = 1; - } - - if ( current_num == num_vfs - && (autoprobe == NM_TERNARY_DEFAULT || current_autoprobe == autoprobe)) - goto out_idle; - - if ( NM_IN_SET (autoprobe, NM_TERNARY_TRUE, NM_TERNARY_FALSE) - && current_autoprobe != autoprobe - && !nm_platform_sysctl_set (NM_PLATFORM_GET, - NMP_SYSCTL_PATHID_NETDIR (dirfd, - ifname, - "device/sriov_drivers_autoprobe"), - nm_sprintf_buf (buf, "%d", (int) autoprobe))) { - g_set_error (&error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "couldn't set SR-IOV drivers-autoprobe to %d: %s", - (int) autoprobe, nm_strerror_native (errno)); - goto out_idle; - } - - if (current_num == 0 && num_vfs == 0) - goto out_idle; - - i = 0; - if (current_num != 0) - values[i++] = "0"; - if (num_vfs != 0) - values[i++] = nm_sprintf_bufa (32, "%u", num_vfs); - values[i++] = NULL; - - sysctl_set_async (platform, - NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "device/sriov_numvfs"), - values, - callback, - data, - cancellable); - return; +link_set_sriov_params_async(NMPlatform * platform, + int ifindex, + guint num_vfs, + NMTernary autoprobe, + NMPlatformAsyncCallback callback, + gpointer data, + GCancellable * cancellable) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + gs_free_error GError *error = NULL; + nm_auto_close int dirfd = -1; + int current_autoprobe; + guint i, total; + gint64 current_num; + char ifname[IFNAMSIZ]; + gpointer packed; + const char * values[3]; + char buf[64]; + + g_return_if_fail(callback || !data); + g_return_if_fail(cancellable); + + if (!nm_platform_netns_push(platform, &netns)) { + g_set_error_literal(&error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "couldn't change namespace"); + goto out_idle; + } + + dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname); + if (!dirfd) { + g_set_error_literal(&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "couldn't open netdir"); + goto out_idle; + } + + total = nm_platform_sysctl_get_int_checked( + platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_totalvfs"), + 10, + 0, + G_MAXUINT, + 0); + if (!errno && num_vfs > total) { + _LOGW("link: %d only supports %u VFs (requested %u)", ifindex, total, num_vfs); + num_vfs = total; + } + + /* + * Take special care when setting new values: + * - don't touch anything if the right values are already set + * - to change the number of VFs or autoprobe we need to destroy existing VFs + * - the autoprobe setting is irrelevant when numvfs is zero + */ + current_num = nm_platform_sysctl_get_int_checked( + platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_numvfs"), + 10, + 0, + G_MAXUINT, + -1); + current_autoprobe = nm_platform_sysctl_get_int_checked( + platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_drivers_autoprobe"), + 10, + 0, + 1, + -1); + + if (current_autoprobe == -1 && errno == ENOENT) { + /* older kernel versions don't have this sysctl. Assume the value is + * "1". */ + current_autoprobe = 1; + } + + if (current_num == num_vfs + && (autoprobe == NM_TERNARY_DEFAULT || current_autoprobe == autoprobe)) + goto out_idle; + + if (NM_IN_SET(autoprobe, NM_TERNARY_TRUE, NM_TERNARY_FALSE) && current_autoprobe != autoprobe + && !nm_platform_sysctl_set( + NM_PLATFORM_GET, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_drivers_autoprobe"), + nm_sprintf_buf(buf, "%d", (int) autoprobe))) { + g_set_error(&error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "couldn't set SR-IOV drivers-autoprobe to %d: %s", + (int) autoprobe, + nm_strerror_native(errno)); + goto out_idle; + } + + if (current_num == 0 && num_vfs == 0) + goto out_idle; + + i = 0; + if (current_num != 0) + values[i++] = "0"; + if (num_vfs != 0) + values[i++] = nm_sprintf_bufa(32, "%u", num_vfs); + values[i++] = NULL; + + sysctl_set_async(platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_numvfs"), + values, + callback, + data, + cancellable); + return; out_idle: - if (callback) { - packed = nm_utils_user_data_pack (g_object_ref (platform), - g_steal_pointer (&error), - callback, - data); - nm_utils_invoke_on_idle (cancellable, sriov_idle_cb, packed); - } + if (callback) { + packed = nm_utils_user_data_pack(g_object_ref(platform), + g_steal_pointer(&error), + callback, + data); + nm_utils_invoke_on_idle(cancellable, sriov_idle_cb, packed); + } } static gboolean -link_set_sriov_vfs (NMPlatform *platform, int ifindex, const NMPlatformVF *const *vfs) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *list, *info, *vlan_list; - guint i; - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if (!nlmsg) - g_return_val_if_reached (-NME_BUG); - - if (!(list = nla_nest_start (nlmsg, IFLA_VFINFO_LIST))) - goto nla_put_failure; - - for (i = 0; vfs[i]; i++) { - const NMPlatformVF *vf = vfs[i]; - - if (!(info = nla_nest_start (nlmsg, IFLA_VF_INFO))) - goto nla_put_failure; - - if (vf->spoofchk >= 0) { - struct _ifla_vf_setting ivs = { 0 }; - - ivs.vf = vf->index; - ivs.setting = vf->spoofchk; - NLA_PUT (nlmsg, IFLA_VF_SPOOFCHK, sizeof (ivs), &ivs); - } - - if (vf->trust >= 0) { - struct _ifla_vf_setting ivs = { 0 }; - - ivs.vf = vf->index; - ivs.setting = vf->trust; - NLA_PUT (nlmsg, IFLA_VF_TRUST, sizeof (ivs), &ivs); - } - - if (vf->mac.len) { - struct ifla_vf_mac ivm = { 0 }; - - ivm.vf = vf->index; - memcpy (ivm.mac, vf->mac.data, vf->mac.len); - NLA_PUT (nlmsg, IFLA_VF_MAC, sizeof (ivm), &ivm); - } - - if (vf->min_tx_rate || vf->max_tx_rate) { - struct _ifla_vf_rate ivr = { 0 }; - - ivr.vf = vf->index; - ivr.min_tx_rate = vf->min_tx_rate; - ivr.max_tx_rate = vf->max_tx_rate; - NLA_PUT (nlmsg, IFLA_VF_RATE, sizeof (ivr), &ivr); - } - - /* Kernel only supports one VLAN per VF now. If this - * changes in the future, we need to figure out how to - * clear existing VLANs and set new ones in one message - * with the new API.*/ - if (vf->num_vlans > 1) { - _LOGW ("multiple VLANs per VF are not supported at the moment"); - return FALSE; - } else { - struct _ifla_vf_vlan_info ivvi = { 0 }; - - if (!(vlan_list = nla_nest_start (nlmsg, IFLA_VF_VLAN_LIST))) - goto nla_put_failure; - - ivvi.vf = vf->index; - if (vf->num_vlans == 1) { - ivvi.vlan = vf->vlans[0].id; - ivvi.qos = vf->vlans[0].qos; - ivvi.vlan_proto = htons (vf->vlans[0].proto_ad ? ETH_P_8021AD : ETH_P_8021Q); - } else { - /* Clear existing VLAN */ - ivvi.vlan = 0; - ivvi.qos = 0; - ivvi.vlan_proto = htons (ETH_P_8021Q); - } - - NLA_PUT (nlmsg, IFLA_VF_VLAN_INFO, sizeof (ivvi), &ivvi); - nla_nest_end (nlmsg, vlan_list); - } - nla_nest_end (nlmsg, info); - } - nla_nest_end (nlmsg, list); - - return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); +link_set_sriov_vfs(NMPlatform *platform, int ifindex, const NMPlatformVF *const *vfs) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr * list, *info, *vlan_list; + guint i; + + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg) + g_return_val_if_reached(-NME_BUG); + + if (!(list = nla_nest_start(nlmsg, IFLA_VFINFO_LIST))) + goto nla_put_failure; + + for (i = 0; vfs[i]; i++) { + const NMPlatformVF *vf = vfs[i]; + + if (!(info = nla_nest_start(nlmsg, IFLA_VF_INFO))) + goto nla_put_failure; + + if (vf->spoofchk >= 0) { + struct _ifla_vf_setting ivs = {0}; + + ivs.vf = vf->index; + ivs.setting = vf->spoofchk; + NLA_PUT(nlmsg, IFLA_VF_SPOOFCHK, sizeof(ivs), &ivs); + } + + if (vf->trust >= 0) { + struct _ifla_vf_setting ivs = {0}; + + ivs.vf = vf->index; + ivs.setting = vf->trust; + NLA_PUT(nlmsg, IFLA_VF_TRUST, sizeof(ivs), &ivs); + } + + if (vf->mac.len) { + struct ifla_vf_mac ivm = {0}; + + ivm.vf = vf->index; + memcpy(ivm.mac, vf->mac.data, vf->mac.len); + NLA_PUT(nlmsg, IFLA_VF_MAC, sizeof(ivm), &ivm); + } + + if (vf->min_tx_rate || vf->max_tx_rate) { + struct _ifla_vf_rate ivr = {0}; + + ivr.vf = vf->index; + ivr.min_tx_rate = vf->min_tx_rate; + ivr.max_tx_rate = vf->max_tx_rate; + NLA_PUT(nlmsg, IFLA_VF_RATE, sizeof(ivr), &ivr); + } + + /* Kernel only supports one VLAN per VF now. If this + * changes in the future, we need to figure out how to + * clear existing VLANs and set new ones in one message + * with the new API.*/ + if (vf->num_vlans > 1) { + _LOGW("multiple VLANs per VF are not supported at the moment"); + return FALSE; + } else { + struct _ifla_vf_vlan_info ivvi = {0}; + + if (!(vlan_list = nla_nest_start(nlmsg, IFLA_VF_VLAN_LIST))) + goto nla_put_failure; + + ivvi.vf = vf->index; + if (vf->num_vlans == 1) { + ivvi.vlan = vf->vlans[0].id; + ivvi.qos = vf->vlans[0].qos; + ivvi.vlan_proto = htons(vf->vlans[0].proto_ad ? ETH_P_8021AD : ETH_P_8021Q); + } else { + /* Clear existing VLAN */ + ivvi.vlan = 0; + ivvi.qos = 0; + ivvi.vlan_proto = htons(ETH_P_8021Q); + } + + NLA_PUT(nlmsg, IFLA_VF_VLAN_INFO, sizeof(ivvi), &ivvi); + nla_nest_end(nlmsg, vlan_list); + } + nla_nest_end(nlmsg, info); + } + nla_nest_end(nlmsg, list); + + return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static gboolean -link_set_bridge_vlans (NMPlatform *platform, - int ifindex, - gboolean on_master, - const NMPlatformBridgeVlan *const *vlans) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - struct nlattr *list; - struct bridge_vlan_info vinfo = { }; - guint i; - - nlmsg = _nl_msg_new_link_full (vlans ? RTM_SETLINK : RTM_DELLINK, - 0, - ifindex, - NULL, - AF_BRIDGE, - 0, - 0); - if (!nlmsg) - g_return_val_if_reached (-NME_BUG); - - if (!(list = nla_nest_start (nlmsg, IFLA_AF_SPEC))) - goto nla_put_failure; - - NLA_PUT_U16 (nlmsg, - IFLA_BRIDGE_FLAGS, - on_master ? BRIDGE_FLAGS_MASTER : BRIDGE_FLAGS_SELF); - - if (vlans) { - /* Add VLANs */ - for (i = 0; vlans[i]; i++) { - const NMPlatformBridgeVlan *vlan = vlans[i]; - gboolean is_range = vlan->vid_start != vlan->vid_end; - - vinfo.vid = vlan->vid_start; - vinfo.flags = is_range ? BRIDGE_VLAN_INFO_RANGE_BEGIN : 0; - - if (vlan->untagged) - vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; - if (vlan->pvid) - vinfo.flags |= BRIDGE_VLAN_INFO_PVID; - - NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo); - - if (is_range) { - vinfo.vid = vlan->vid_end; - vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END; - NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo); - } - } - } else { - /* Flush existing VLANs */ - vinfo.vid = 1; - vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN; - NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo); - - vinfo.vid = 4094; - vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END; - NLA_PUT (nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof (vinfo), &vinfo); - } - - nla_nest_end (nlmsg, list); - - return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); +link_set_bridge_vlans(NMPlatform * platform, + int ifindex, + gboolean on_master, + const NMPlatformBridgeVlan *const *vlans) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr * list; + struct bridge_vlan_info vinfo = {}; + guint i; + + nlmsg = + _nl_msg_new_link_full(vlans ? RTM_SETLINK : RTM_DELLINK, 0, ifindex, NULL, AF_BRIDGE, 0, 0); + if (!nlmsg) + g_return_val_if_reached(-NME_BUG); + + if (!(list = nla_nest_start(nlmsg, IFLA_AF_SPEC))) + goto nla_put_failure; + + NLA_PUT_U16(nlmsg, IFLA_BRIDGE_FLAGS, on_master ? BRIDGE_FLAGS_MASTER : BRIDGE_FLAGS_SELF); + + if (vlans) { + /* Add VLANs */ + for (i = 0; vlans[i]; i++) { + const NMPlatformBridgeVlan *vlan = vlans[i]; + gboolean is_range = vlan->vid_start != vlan->vid_end; + + vinfo.vid = vlan->vid_start; + vinfo.flags = is_range ? BRIDGE_VLAN_INFO_RANGE_BEGIN : 0; + + if (vlan->untagged) + vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED; + if (vlan->pvid) + vinfo.flags |= BRIDGE_VLAN_INFO_PVID; + + NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); + + if (is_range) { + vinfo.vid = vlan->vid_end; + vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END; + NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); + } + } + } else { + /* Flush existing VLANs */ + vinfo.vid = 1; + vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN; + NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); + + vinfo.vid = 4094; + vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END; + NLA_PUT(nlmsg, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo); + } + + nla_nest_end(nlmsg, list); + + return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static char * -link_get_physical_port_id (NMPlatform *platform, int ifindex) +link_get_physical_port_id(NMPlatform *platform, int ifindex) { - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; + nm_auto_close int dirfd = -1; + char ifname_verified[IFNAMSIZ]; - dirfd = nm_platform_sysctl_open_netdir (platform, ifindex, ifname_verified); - if (dirfd < 0) - return NULL; - return sysctl_get (platform, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_verified, "phys_port_id")); + dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname_verified); + if (dirfd < 0) + return NULL; + return sysctl_get(platform, NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "phys_port_id")); } static guint -link_get_dev_id (NMPlatform *platform, int ifindex) +link_get_dev_id(NMPlatform *platform, int ifindex) { - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; + nm_auto_close int dirfd = -1; + char ifname_verified[IFNAMSIZ]; - dirfd = nm_platform_sysctl_open_netdir (platform, ifindex, ifname_verified); - if (dirfd < 0) - return 0; - return nm_platform_sysctl_get_int_checked (platform, - NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_verified, "dev_id"), - 16, 0, G_MAXUINT16, 0); + dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname_verified); + if (dirfd < 0) + return 0; + return nm_platform_sysctl_get_int_checked( + platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "dev_id"), + 16, + 0, + G_MAXUINT16, + 0); } static gboolean -link_tun_add (NMPlatform *platform, - const char *name, - const NMPlatformLnkTun *props, - const NMPlatformLink **out_link, - int *out_fd) -{ - const NMPObject *obj; - struct ifreq ifr = { }; - nm_auto_close int fd = -1; - - nm_assert (NM_IN_SET (props->type, IFF_TAP, IFF_TUN)); - nm_assert (props->persist || out_fd); - - fd = open ("/dev/net/tun", O_RDWR | O_CLOEXEC); - if (fd < 0) - return FALSE; - - nm_utils_ifname_cpy (ifr.ifr_name, name); - ifr.ifr_flags = ((short) props->type) - | ((short) IFF_TUN_EXCL) - | (!props->pi ? (short) IFF_NO_PI : (short) 0) - | ( props->vnet_hdr ? (short) IFF_VNET_HDR : (short) 0) - | ( props->multi_queue ? (short) NM_IFF_MULTI_QUEUE : (short) 0); - if (ioctl (fd, TUNSETIFF, &ifr)) - return FALSE; - - if (props->owner_valid) { - if (ioctl (fd, TUNSETOWNER, (uid_t) props->owner)) - return FALSE; - } - - if (props->group_valid) { - if (ioctl (fd, TUNSETGROUP, (gid_t) props->group)) - return FALSE; - } - - if (props->persist) { - if (ioctl (fd, TUNSETPERSIST, 1)) - return FALSE; - } - - do_request_link (platform, 0, name); - obj = nmp_cache_lookup_link_full (nm_platform_get_cache (platform), - 0, name, FALSE, - NM_LINK_TYPE_TUN, - NULL, NULL); - - if (!obj) - return FALSE; - - NM_SET_OUT (out_link, &obj->link); - NM_SET_OUT (out_fd, nm_steal_fd (&fd)); - return TRUE; +link_tun_add(NMPlatform * platform, + const char * name, + const NMPlatformLnkTun *props, + const NMPlatformLink ** out_link, + int * out_fd) +{ + const NMPObject * obj; + struct ifreq ifr = {}; + nm_auto_close int fd = -1; + + nm_assert(NM_IN_SET(props->type, IFF_TAP, IFF_TUN)); + nm_assert(props->persist || out_fd); + + fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC); + if (fd < 0) + return FALSE; + + nm_utils_ifname_cpy(ifr.ifr_name, name); + ifr.ifr_flags = ((short) props->type) | ((short) IFF_TUN_EXCL) + | (!props->pi ? (short) IFF_NO_PI : (short) 0) + | (props->vnet_hdr ? (short) IFF_VNET_HDR : (short) 0) + | (props->multi_queue ? (short) NM_IFF_MULTI_QUEUE : (short) 0); + if (ioctl(fd, TUNSETIFF, &ifr)) + return FALSE; + + if (props->owner_valid) { + if (ioctl(fd, TUNSETOWNER, (uid_t) props->owner)) + return FALSE; + } + + if (props->group_valid) { + if (ioctl(fd, TUNSETGROUP, (gid_t) props->group)) + return FALSE; + } + + if (props->persist) { + if (ioctl(fd, TUNSETPERSIST, 1)) + return FALSE; + } + + do_request_link(platform, 0, name); + obj = nmp_cache_lookup_link_full(nm_platform_get_cache(platform), + 0, + name, + FALSE, + NM_LINK_TYPE_TUN, + NULL, + NULL); + + if (!obj) + return FALSE; + + NM_SET_OUT(out_link, &obj->link); + NM_SET_OUT(out_fd, nm_steal_fd(&fd)); + return TRUE; } static void -_vlan_change_vlan_qos_mapping_create (gboolean is_ingress_map, - gboolean reset_all, - const NMVlanQosMapping *current_map, - guint current_n_map, - const NMVlanQosMapping *set_map, - guint set_n_map, - NMVlanQosMapping **out_map, - guint *out_n_map) -{ - NMVlanQosMapping *map; - guint i, j, len; - const guint INGRESS_RANGE_LEN = 8; - - nm_assert (out_map && !*out_map); - nm_assert (out_n_map && !*out_n_map); - - if (!reset_all) - current_n_map = 0; - else if (is_ingress_map) - current_n_map = INGRESS_RANGE_LEN; - - len = current_n_map + set_n_map; - - if (len == 0) - return; - - map = g_new (NMVlanQosMapping, len); - - if (current_n_map) { - if (is_ingress_map) { - /* For the ingress-map, there are only 8 entries (0 to 7). - * When the user requests to reset all entries, we don't actually - * need the cached entries, we can just explicitly clear all possible - * ones. - * - * That makes only a real difference in case our cache is out-of-date. - * - * For the egress map we cannot do that, because there are far too - * many. There we can only clear the entries that we know about. */ - for (i = 0; i < INGRESS_RANGE_LEN; i++) { - map[i].from = i; - map[i].to = 0; - } - } else { - for (i = 0; i < current_n_map; i++) { - map[i].from = current_map[i].from; - map[i].to = 0; - } - } - } - if (set_n_map) - memcpy (&map[current_n_map], set_map, sizeof (*set_map) * set_n_map); - - g_qsort_with_data (map, - len, - sizeof (*map), - _vlan_qos_mapping_cmp_from, - NULL); - - for (i = 0, j = 0; i < len; i++) { - if ( ( is_ingress_map && !VLAN_XGRESS_PRIO_VALID (map[i].from)) - || (!is_ingress_map && !VLAN_XGRESS_PRIO_VALID (map[i].to))) - continue; - if ( j > 0 - && map[j - 1].from == map[i].from) - map[j - 1] = map[i]; - else - map[j++] = map[i]; - } - - *out_map = map; - *out_n_map = j; +_vlan_change_vlan_qos_mapping_create(gboolean is_ingress_map, + gboolean reset_all, + const NMVlanQosMapping *current_map, + guint current_n_map, + const NMVlanQosMapping *set_map, + guint set_n_map, + NMVlanQosMapping ** out_map, + guint * out_n_map) +{ + NMVlanQosMapping *map; + guint i, j, len; + const guint INGRESS_RANGE_LEN = 8; + + nm_assert(out_map && !*out_map); + nm_assert(out_n_map && !*out_n_map); + + if (!reset_all) + current_n_map = 0; + else if (is_ingress_map) + current_n_map = INGRESS_RANGE_LEN; + + len = current_n_map + set_n_map; + + if (len == 0) + return; + + map = g_new(NMVlanQosMapping, len); + + if (current_n_map) { + if (is_ingress_map) { + /* For the ingress-map, there are only 8 entries (0 to 7). + * When the user requests to reset all entries, we don't actually + * need the cached entries, we can just explicitly clear all possible + * ones. + * + * That makes only a real difference in case our cache is out-of-date. + * + * For the egress map we cannot do that, because there are far too + * many. There we can only clear the entries that we know about. */ + for (i = 0; i < INGRESS_RANGE_LEN; i++) { + map[i].from = i; + map[i].to = 0; + } + } else { + for (i = 0; i < current_n_map; i++) { + map[i].from = current_map[i].from; + map[i].to = 0; + } + } + } + if (set_n_map) + memcpy(&map[current_n_map], set_map, sizeof(*set_map) * set_n_map); + + g_qsort_with_data(map, len, sizeof(*map), _vlan_qos_mapping_cmp_from, NULL); + + for (i = 0, j = 0; i < len; i++) { + if ((is_ingress_map && !VLAN_XGRESS_PRIO_VALID(map[i].from)) + || (!is_ingress_map && !VLAN_XGRESS_PRIO_VALID(map[i].to))) + continue; + if (j > 0 && map[j - 1].from == map[i].from) + map[j - 1] = map[i]; + else + map[j++] = map[i]; + } + + *out_map = map; + *out_n_map = j; } static gboolean -link_vlan_change (NMPlatform *platform, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map) -{ - const NMPObject *obj_cache; - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - const NMPObjectLnkVlan *lnk; - guint new_n_ingress_map = 0; - guint new_n_egress_map = 0; - gs_free NMVlanQosMapping *new_ingress_map = NULL; - gs_free NMVlanQosMapping *new_egress_map = NULL; - - obj_cache = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex); - if ( !obj_cache - || !obj_cache->_link.netlink.is_in_netlink) { - _LOGD ("link: change %d: %s: link does not exist", ifindex, "vlan"); - return FALSE; - } - - lnk = obj_cache->_link.netlink.lnk ? &obj_cache->_link.netlink.lnk->_lnk_vlan : NULL; - - flags_set &= flags_mask; - - _vlan_change_vlan_qos_mapping_create (TRUE, - ingress_reset_all, - lnk ? lnk->ingress_qos_map : NULL, - lnk ? lnk->n_ingress_qos_map : 0, - ingress_map, - n_ingress_map, - &new_ingress_map, - &new_n_ingress_map); - - _vlan_change_vlan_qos_mapping_create (FALSE, - egress_reset_all, - lnk ? lnk->egress_qos_map : NULL, - lnk ? lnk->n_egress_qos_map : 0, - egress_map, - n_egress_map, - &new_egress_map, - &new_n_egress_map); - - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if ( !nlmsg - || !_nl_msg_new_link_set_linkinfo_vlan (nlmsg, - -1, - flags_mask, - flags_set, - new_ingress_map, - new_n_ingress_map, - new_egress_map, - new_n_egress_map)) - g_return_val_if_reached (FALSE); - - return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); +link_vlan_change(NMPlatform * platform, + int ifindex, + NMVlanFlags flags_mask, + NMVlanFlags flags_set, + gboolean ingress_reset_all, + const NMVlanQosMapping *ingress_map, + gsize n_ingress_map, + gboolean egress_reset_all, + const NMVlanQosMapping *egress_map, + gsize n_egress_map) +{ + const NMPObject * obj_cache; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + const NMPObjectLnkVlan * lnk; + guint new_n_ingress_map = 0; + guint new_n_egress_map = 0; + gs_free NMVlanQosMapping *new_ingress_map = NULL; + gs_free NMVlanQosMapping *new_egress_map = NULL; + + obj_cache = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); + if (!obj_cache || !obj_cache->_link.netlink.is_in_netlink) { + _LOGD("link: change %d: %s: link does not exist", ifindex, "vlan"); + return FALSE; + } + + lnk = obj_cache->_link.netlink.lnk ? &obj_cache->_link.netlink.lnk->_lnk_vlan : NULL; + + flags_set &= flags_mask; + + _vlan_change_vlan_qos_mapping_create(TRUE, + ingress_reset_all, + lnk ? lnk->ingress_qos_map : NULL, + lnk ? lnk->n_ingress_qos_map : 0, + ingress_map, + n_ingress_map, + &new_ingress_map, + &new_n_ingress_map); + + _vlan_change_vlan_qos_mapping_create(FALSE, + egress_reset_all, + lnk ? lnk->egress_qos_map : NULL, + lnk ? lnk->n_egress_qos_map : 0, + egress_map, + n_egress_map, + &new_egress_map, + &new_n_egress_map); + + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg + || !_nl_msg_new_link_set_linkinfo_vlan(nlmsg, + -1, + flags_mask, + flags_set, + new_ingress_map, + new_n_ingress_map, + new_egress_map, + new_n_egress_map)) + g_return_val_if_reached(FALSE); + + return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); } static gboolean -link_enslave (NMPlatform *platform, int master, int slave) +link_enslave(NMPlatform *platform, int master, int slave) { - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - int ifindex = slave; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + int ifindex = slave; - nlmsg = _nl_msg_new_link (RTM_NEWLINK, - 0, - ifindex, - NULL); - if (!nlmsg) - return FALSE; + nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + if (!nlmsg) + return FALSE; - NLA_PUT_U32 (nlmsg, IFLA_MASTER, master); + NLA_PUT_U32(nlmsg, IFLA_MASTER, master); - return (do_change_link (platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); + return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static gboolean -link_release (NMPlatform *platform, int master, int slave) +link_release(NMPlatform *platform, int master, int slave) { - return link_enslave (platform, 0, slave); + return link_enslave(platform, 0, slave); } /*****************************************************************************/ static gboolean -_infiniband_partition_action (NMPlatform *platform, - InfinibandAction action, - int parent, - int p_key, - const NMPlatformLink **out_link) -{ - nm_auto_close int dirfd = -1; - char ifname_parent[IFNAMSIZ]; - const NMPObject *obj; - char id[20]; - char name[IFNAMSIZ]; - gboolean success; - - nm_assert (NM_IN_SET (action, INFINIBAND_ACTION_CREATE_CHILD, INFINIBAND_ACTION_DELETE_CHILD)); - nm_assert (p_key > 0 && p_key <= 0xffff && p_key != 0x8000); - - dirfd = nm_platform_sysctl_open_netdir (platform, parent, ifname_parent); - if (dirfd < 0) { - errno = ENOENT; - return FALSE; - } - - nm_sprintf_buf (id, "0x%04x", p_key); - if (action == INFINIBAND_ACTION_CREATE_CHILD) - success = nm_platform_sysctl_set (platform, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_parent, "create_child"), id); - else - success = nm_platform_sysctl_set (platform, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_parent, "delete_child"), id); - - if (!success) { - if ( action == INFINIBAND_ACTION_DELETE_CHILD - && errno == ENODEV) - return TRUE; - return FALSE; - } - - nm_utils_new_infiniband_name (name, ifname_parent, p_key); - do_request_link (platform, 0, name); - - if (action == INFINIBAND_ACTION_DELETE_CHILD) - return TRUE; - - obj = nmp_cache_lookup_link_full (nm_platform_get_cache (platform), 0, name, FALSE, - NM_LINK_TYPE_INFINIBAND, NULL, NULL); - if (out_link) - *out_link = obj ? &obj->link : NULL; - return !!obj; +_infiniband_partition_action(NMPlatform * platform, + InfinibandAction action, + int parent, + int p_key, + const NMPlatformLink **out_link) +{ + nm_auto_close int dirfd = -1; + char ifname_parent[IFNAMSIZ]; + const NMPObject * obj; + char id[20]; + char name[IFNAMSIZ]; + gboolean success; + + nm_assert(NM_IN_SET(action, INFINIBAND_ACTION_CREATE_CHILD, INFINIBAND_ACTION_DELETE_CHILD)); + nm_assert(p_key > 0 && p_key <= 0xffff && p_key != 0x8000); + + dirfd = nm_platform_sysctl_open_netdir(platform, parent, ifname_parent); + if (dirfd < 0) { + errno = ENOENT; + return FALSE; + } + + nm_sprintf_buf(id, "0x%04x", p_key); + if (action == INFINIBAND_ACTION_CREATE_CHILD) + success = + nm_platform_sysctl_set(platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_parent, "create_child"), + id); + else + success = + nm_platform_sysctl_set(platform, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_parent, "delete_child"), + id); + + if (!success) { + if (action == INFINIBAND_ACTION_DELETE_CHILD && errno == ENODEV) + return TRUE; + return FALSE; + } + + nm_utils_new_infiniband_name(name, ifname_parent, p_key); + do_request_link(platform, 0, name); + + if (action == INFINIBAND_ACTION_DELETE_CHILD) + return TRUE; + + obj = nmp_cache_lookup_link_full(nm_platform_get_cache(platform), + 0, + name, + FALSE, + NM_LINK_TYPE_INFINIBAND, + NULL, + NULL); + if (out_link) + *out_link = obj ? &obj->link : NULL; + return !!obj; } static gboolean -infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link) +infiniband_partition_add(NMPlatform * platform, + int parent, + int p_key, + const NMPlatformLink **out_link) { - return _infiniband_partition_action (platform, INFINIBAND_ACTION_CREATE_CHILD, parent, p_key, out_link); + return _infiniband_partition_action(platform, + INFINIBAND_ACTION_CREATE_CHILD, + parent, + p_key, + out_link); } static gboolean -infiniband_partition_delete (NMPlatform *platform, int parent, int p_key) +infiniband_partition_delete(NMPlatform *platform, int parent, int p_key) { - return _infiniband_partition_action (platform, INFINIBAND_ACTION_DELETE_CHILD, parent, p_key, NULL); + return _infiniband_partition_action(platform, + INFINIBAND_ACTION_DELETE_CHILD, + parent, + p_key, + NULL); } /*****************************************************************************/ static GObject * -get_ext_data (NMPlatform *platform, int ifindex) +get_ext_data(NMPlatform *platform, int ifindex) { - const NMPObject *obj; + const NMPObject *obj; - obj = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex); - if (!obj) - return NULL; + obj = nmp_cache_lookup_link(nm_platform_get_cache(platform), ifindex); + if (!obj) + return NULL; - return obj->_link.ext_data; + return obj->_link.ext_data; } /*****************************************************************************/ #define WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, retval) \ - nm_auto_pop_netns NMPNetns *netns = NULL; \ - NMWifiUtils *wifi_data; \ - if (!nm_platform_netns_push (platform, &netns)) \ - return retval; \ - wifi_data = NM_WIFI_UTILS (get_ext_data (platform, ifindex)); \ - if (!wifi_data) \ - return retval; + nm_auto_pop_netns NMPNetns *netns = NULL; \ + NMWifiUtils * wifi_data; \ + if (!nm_platform_netns_push(platform, &netns)) \ + return retval; \ + wifi_data = NM_WIFI_UTILS(get_ext_data(platform, ifindex)); \ + if (!wifi_data) \ + return retval; static gboolean -wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) +wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - if (caps) - *caps = nm_wifi_utils_get_caps (wifi_data); - return TRUE; + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + if (caps) + *caps = nm_wifi_utils_get_caps(wifi_data); + return TRUE; } static gboolean -wifi_get_bssid (NMPlatform *platform, int ifindex, guint8 *bssid) +wifi_get_bssid(NMPlatform *platform, int ifindex, guint8 *bssid) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_bssid (wifi_data, bssid); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + return nm_wifi_utils_get_bssid(wifi_data, bssid); } static guint32 -wifi_get_frequency (NMPlatform *platform, int ifindex) +wifi_get_frequency(NMPlatform *platform, int ifindex) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, 0); - return nm_wifi_utils_get_freq (wifi_data); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, 0); + return nm_wifi_utils_get_freq(wifi_data); } static gboolean -wifi_get_quality (NMPlatform *platform, int ifindex) +wifi_get_quality(NMPlatform *platform, int ifindex) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_qual (wifi_data); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + return nm_wifi_utils_get_qual(wifi_data); } static guint32 -wifi_get_rate (NMPlatform *platform, int ifindex) +wifi_get_rate(NMPlatform *platform, int ifindex) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_rate (wifi_data); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + return nm_wifi_utils_get_rate(wifi_data); } static NM80211Mode -wifi_get_mode (NMPlatform *platform, int ifindex) +wifi_get_mode(NMPlatform *platform, int ifindex) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, NM_802_11_MODE_UNKNOWN); - return nm_wifi_utils_get_mode (wifi_data); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, NM_802_11_MODE_UNKNOWN); + return nm_wifi_utils_get_mode(wifi_data); } static void -wifi_set_mode (NMPlatform *platform, int ifindex, NM80211Mode mode) +wifi_set_mode(NMPlatform *platform, int ifindex, NM80211Mode mode) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, ); - nm_wifi_utils_set_mode (wifi_data, mode); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, ); + nm_wifi_utils_set_mode(wifi_data, mode); } static void -wifi_set_powersave (NMPlatform *platform, int ifindex, guint32 powersave) +wifi_set_powersave(NMPlatform *platform, int ifindex, guint32 powersave) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, ); - nm_wifi_utils_set_powersave (wifi_data, powersave); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, ); + nm_wifi_utils_set_powersave(wifi_data, powersave); } static guint32 -wifi_find_frequency (NMPlatform *platform, int ifindex, const guint32 *freqs) +wifi_find_frequency(NMPlatform *platform, int ifindex, const guint32 *freqs) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, 0); - return nm_wifi_utils_find_freq (wifi_data, freqs); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, 0); + return nm_wifi_utils_find_freq(wifi_data, freqs); } static void -wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean running) +wifi_indicate_addressing_running(NMPlatform *platform, int ifindex, gboolean running) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, ); - nm_wifi_utils_indicate_addressing_running (wifi_data, running); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, ); + nm_wifi_utils_indicate_addressing_running(wifi_data, running); } static NMSettingWirelessWakeOnWLan -wifi_get_wake_on_wlan (NMPlatform *platform, int ifindex) +wifi_get_wake_on_wlan(NMPlatform *platform, int ifindex) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_wake_on_wlan (wifi_data); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + return nm_wifi_utils_get_wake_on_wlan(wifi_data); } static gboolean -wifi_set_wake_on_wlan (NMPlatform *platform, int ifindex, - NMSettingWirelessWakeOnWLan wowl) +wifi_set_wake_on_wlan(NMPlatform *platform, int ifindex, NMSettingWirelessWakeOnWLan wowl) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_set_wake_on_wlan (wifi_data, wowl); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + return nm_wifi_utils_set_wake_on_wlan(wifi_data, wowl); } /*****************************************************************************/ static gboolean -link_can_assume (NMPlatform *platform, int ifindex) +link_can_assume(NMPlatform *platform, int ifindex) { - NMPLookup lookup; - const NMPObject *link, *o; - NMDedupMultiIter iter; - NMPCache *cache = nm_platform_get_cache (platform); + NMPLookup lookup; + const NMPObject *link, *o; + NMDedupMultiIter iter; + NMPCache * cache = nm_platform_get_cache(platform); - if (ifindex <= 0) - return FALSE; + if (ifindex <= 0) + return FALSE; - link = nm_platform_link_get_obj (platform, ifindex, TRUE); - if (!link) - return FALSE; + link = nm_platform_link_get_obj(platform, ifindex, TRUE); + if (!link) + return FALSE; - if (!NM_FLAGS_HAS (link->link.n_ifi_flags, IFF_UP)) - return FALSE; + if (!NM_FLAGS_HAS(link->link.n_ifi_flags, IFF_UP)) + return FALSE; - if (link->link.master > 0) - return TRUE; + if (link->link.master > 0) + return TRUE; - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_IP4_ADDRESS, - ifindex); - if (nmp_cache_lookup (cache, &lookup)) - return TRUE; + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex); + if (nmp_cache_lookup(cache, &lookup)) + return TRUE; - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_IP6_ADDRESS, - ifindex); - nmp_cache_iter_for_each (&iter, - nmp_cache_lookup (cache, &lookup), - &o) { - nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_TYPE_IP6_ADDRESS); - if (!IN6_IS_ADDR_LINKLOCAL (&o->ip6_address.address)) - return TRUE; - } - return FALSE; + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex); + nmp_cache_iter_for_each (&iter, nmp_cache_lookup(cache, &lookup), &o) { + nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_TYPE_IP6_ADDRESS); + if (!IN6_IS_ADDR_LINKLOCAL(&o->ip6_address.address)) + return TRUE; + } + return FALSE; } /*****************************************************************************/ static guint32 -mesh_get_channel (NMPlatform *platform, int ifindex) +mesh_get_channel(NMPlatform *platform, int ifindex) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, 0); - return nm_wifi_utils_get_mesh_channel (wifi_data); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, 0); + return nm_wifi_utils_get_mesh_channel(wifi_data); } static gboolean -mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel) +mesh_set_channel(NMPlatform *platform, int ifindex, guint32 channel) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_set_mesh_channel (wifi_data, channel); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + return nm_wifi_utils_set_mesh_channel(wifi_data, channel); } static gboolean -mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) +mesh_set_ssid(NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) { - WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_set_mesh_ssid (wifi_data, ssid, len); + WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); + return nm_wifi_utils_set_mesh_ssid(wifi_data, ssid, len); } /*****************************************************************************/ -#define WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, retval) \ - NMWpanUtils *wpan_data = NM_WPAN_UTILS (get_ext_data (platform, ifindex)); \ - if (!wpan_data) \ - return retval; +#define WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, retval) \ + NMWpanUtils *wpan_data = NM_WPAN_UTILS(get_ext_data(platform, ifindex)); \ + if (!wpan_data) \ + return retval; static guint16 -wpan_get_pan_id (NMPlatform *platform, int ifindex) +wpan_get_pan_id(NMPlatform *platform, int ifindex) { - WPAN_GET_WPAN_DATA (wpan_data, platform, ifindex, G_MAXINT16); - return nm_wpan_utils_get_pan_id (wpan_data); + WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, G_MAXINT16); + return nm_wpan_utils_get_pan_id(wpan_data); } static gboolean -wpan_set_pan_id (NMPlatform *platform, int ifindex, guint16 pan_id) +wpan_set_pan_id(NMPlatform *platform, int ifindex, guint16 pan_id) { - WPAN_GET_WPAN_DATA (wpan_data, platform, ifindex, FALSE); - return nm_wpan_utils_set_pan_id (wpan_data, pan_id); + WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, FALSE); + return nm_wpan_utils_set_pan_id(wpan_data, pan_id); } static guint16 -wpan_get_short_addr (NMPlatform *platform, int ifindex) +wpan_get_short_addr(NMPlatform *platform, int ifindex) { - WPAN_GET_WPAN_DATA (wpan_data, platform, ifindex, G_MAXINT16); - return nm_wpan_utils_get_short_addr (wpan_data); + WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, G_MAXINT16); + return nm_wpan_utils_get_short_addr(wpan_data); } static gboolean -wpan_set_short_addr (NMPlatform *platform, int ifindex, guint16 short_addr) +wpan_set_short_addr(NMPlatform *platform, int ifindex, guint16 short_addr) { - WPAN_GET_WPAN_DATA (wpan_data, platform, ifindex, FALSE); - return nm_wpan_utils_set_short_addr (wpan_data, short_addr); + WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, FALSE); + return nm_wpan_utils_set_short_addr(wpan_data, short_addr); } static gboolean -wpan_set_channel (NMPlatform *platform, int ifindex, guint8 page, guint8 channel) +wpan_set_channel(NMPlatform *platform, int ifindex, guint8 page, guint8 channel) { - WPAN_GET_WPAN_DATA (wpan_data, platform, ifindex, FALSE); - return nm_wpan_utils_set_channel (wpan_data, page, channel); + WPAN_GET_WPAN_DATA(wpan_data, platform, ifindex, FALSE); + return nm_wpan_utils_set_channel(wpan_data, page, channel); } /*****************************************************************************/ static gboolean -link_get_wake_on_lan (NMPlatform *platform, int ifindex) +link_get_wake_on_lan(NMPlatform *platform, int ifindex) { - nm_auto_pop_netns NMPNetns *netns = NULL; - NMLinkType type = nm_platform_link_get_type (platform, ifindex); + nm_auto_pop_netns NMPNetns *netns = NULL; + NMLinkType type = nm_platform_link_get_type(platform, ifindex); - if (!nm_platform_netns_push (platform, &netns)) - return FALSE; + if (!nm_platform_netns_push(platform, &netns)) + return FALSE; - if (type == NM_LINK_TYPE_ETHERNET) - return nmp_utils_ethtool_get_wake_on_lan (ifindex); - else if (type == NM_LINK_TYPE_WIFI) { - NMWifiUtils *wifi_data = NM_WIFI_UTILS (get_ext_data (platform, ifindex)); + if (type == NM_LINK_TYPE_ETHERNET) + return nmp_utils_ethtool_get_wake_on_lan(ifindex); + else if (type == NM_LINK_TYPE_WIFI) { + NMWifiUtils *wifi_data = NM_WIFI_UTILS(get_ext_data(platform, ifindex)); - if (!wifi_data) - return FALSE; + if (!wifi_data) + return FALSE; - return !NM_IN_SET (nm_wifi_utils_get_wake_on_wlan (wifi_data), - NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE, - NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE); + return !NM_IN_SET(nm_wifi_utils_get_wake_on_wlan(wifi_data), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE, + NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE); - } else - return FALSE; + } else + return FALSE; } static gboolean -link_get_driver_info (NMPlatform *platform, - int ifindex, - char **out_driver_name, - char **out_driver_version, - char **out_fw_version) +link_get_driver_info(NMPlatform *platform, + int ifindex, + char ** out_driver_name, + char ** out_driver_version, + char ** out_fw_version) { - nm_auto_pop_netns NMPNetns *netns = NULL; - NMPUtilsEthtoolDriverInfo driver_info; + nm_auto_pop_netns NMPNetns *netns = NULL; + NMPUtilsEthtoolDriverInfo driver_info; - if (!nm_platform_netns_push (platform, &netns)) - return FALSE; + if (!nm_platform_netns_push(platform, &netns)) + return FALSE; - if (!nmp_utils_ethtool_get_driver_info (ifindex, &driver_info)) - return FALSE; - NM_SET_OUT (out_driver_name, g_strdup (driver_info.driver)); - NM_SET_OUT (out_driver_version, g_strdup (driver_info.version)); - NM_SET_OUT (out_fw_version, g_strdup (driver_info.fw_version)); - return TRUE; + if (!nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) + return FALSE; + NM_SET_OUT(out_driver_name, g_strdup(driver_info.driver)); + NM_SET_OUT(out_driver_version, g_strdup(driver_info.version)); + NM_SET_OUT(out_fw_version, g_strdup(driver_info.fw_version)); + return TRUE; } /*****************************************************************************/ static gboolean -ip4_address_add (NMPlatform *platform, - int ifindex, - in_addr_t addr, - guint8 plen, - in_addr_t peer_addr, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) -{ - NMPObject obj_id; - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - nlmsg = _nl_msg_new_address (RTM_NEWADDR, - NLM_F_CREATE | NLM_F_REPLACE, - AF_INET, - ifindex, - &addr, - plen, - &peer_addr, - flags, - nm_utils_ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE, - lifetime, - preferred, - broadcast_address, - label); - - nmp_object_stackinit_id_ip4_address (&obj_id, ifindex, addr, plen, peer_addr); - return (do_add_addrroute (platform, &obj_id, nlmsg, FALSE) >= 0); +ip4_address_add(NMPlatform *platform, + int ifindex, + in_addr_t addr, + guint8 plen, + in_addr_t peer_addr, + in_addr_t broadcast_address, + guint32 lifetime, + guint32 preferred, + guint32 flags, + const char *label) +{ + NMPObject obj_id; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + + nlmsg = _nl_msg_new_address(RTM_NEWADDR, + NLM_F_CREATE | NLM_F_REPLACE, + AF_INET, + ifindex, + &addr, + plen, + &peer_addr, + flags, + nm_utils_ip4_address_is_link_local(addr) ? RT_SCOPE_LINK + : RT_SCOPE_UNIVERSE, + lifetime, + preferred, + broadcast_address, + label); + + nmp_object_stackinit_id_ip4_address(&obj_id, ifindex, addr, plen, peer_addr); + return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE) >= 0); } static gboolean -ip6_address_add (NMPlatform *platform, - int ifindex, - struct in6_addr addr, - guint8 plen, - struct in6_addr peer_addr, - guint32 lifetime, - guint32 preferred, - guint32 flags) -{ - NMPObject obj_id; - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - nlmsg = _nl_msg_new_address (RTM_NEWADDR, - NLM_F_CREATE | NLM_F_REPLACE, - AF_INET6, - ifindex, - &addr, - plen, - IN6_IS_ADDR_UNSPECIFIED (&peer_addr) ? NULL : &peer_addr, - flags, - RT_SCOPE_UNIVERSE, - lifetime, - preferred, - 0, - NULL); - - nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &addr); - return (do_add_addrroute (platform, &obj_id, nlmsg, FALSE) >= 0); +ip6_address_add(NMPlatform * platform, + int ifindex, + struct in6_addr addr, + guint8 plen, + struct in6_addr peer_addr, + guint32 lifetime, + guint32 preferred, + guint32 flags) +{ + NMPObject obj_id; + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + + nlmsg = _nl_msg_new_address(RTM_NEWADDR, + NLM_F_CREATE | NLM_F_REPLACE, + AF_INET6, + ifindex, + &addr, + plen, + IN6_IS_ADDR_UNSPECIFIED(&peer_addr) ? NULL : &peer_addr, + flags, + RT_SCOPE_UNIVERSE, + lifetime, + preferred, + 0, + NULL); + + nmp_object_stackinit_id_ip6_address(&obj_id, ifindex, &addr); + return (do_add_addrroute(platform, &obj_id, nlmsg, FALSE) >= 0); } static gboolean -ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj_id; - - nlmsg = _nl_msg_new_address (RTM_DELADDR, - 0, - AF_INET, - ifindex, - &addr, - plen, - &peer_address, - 0, - RT_SCOPE_NOWHERE, - NM_PLATFORM_LIFETIME_PERMANENT, - NM_PLATFORM_LIFETIME_PERMANENT, - 0, - NULL); - if (!nlmsg) - g_return_val_if_reached (FALSE); - - nmp_object_stackinit_id_ip4_address (&obj_id, ifindex, addr, plen, peer_address); - return do_delete_object (platform, &obj_id, nlmsg); +ip4_address_delete(NMPlatform *platform, + int ifindex, + in_addr_t addr, + guint8 plen, + in_addr_t peer_address) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + NMPObject obj_id; + + nlmsg = _nl_msg_new_address(RTM_DELADDR, + 0, + AF_INET, + ifindex, + &addr, + plen, + &peer_address, + 0, + RT_SCOPE_NOWHERE, + NM_PLATFORM_LIFETIME_PERMANENT, + NM_PLATFORM_LIFETIME_PERMANENT, + 0, + NULL); + if (!nlmsg) + g_return_val_if_reached(FALSE); + + nmp_object_stackinit_id_ip4_address(&obj_id, ifindex, addr, plen, peer_address); + return do_delete_object(platform, &obj_id, nlmsg); } static gboolean -ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj_id; - - nlmsg = _nl_msg_new_address (RTM_DELADDR, - 0, - AF_INET6, - ifindex, - &addr, - plen, - NULL, - 0, - RT_SCOPE_NOWHERE, - NM_PLATFORM_LIFETIME_PERMANENT, - NM_PLATFORM_LIFETIME_PERMANENT, - 0, - NULL); - if (!nlmsg) - g_return_val_if_reached (FALSE); - - nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &addr); - return do_delete_object (platform, &obj_id, nlmsg); +ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + NMPObject obj_id; + + nlmsg = _nl_msg_new_address(RTM_DELADDR, + 0, + AF_INET6, + ifindex, + &addr, + plen, + NULL, + 0, + RT_SCOPE_NOWHERE, + NM_PLATFORM_LIFETIME_PERMANENT, + NM_PLATFORM_LIFETIME_PERMANENT, + 0, + NULL); + if (!nlmsg) + g_return_val_if_reached(FALSE); + + nmp_object_stackinit_id_ip6_address(&obj_id, ifindex, &addr); + return do_delete_object(platform, &obj_id, nlmsg); } /*****************************************************************************/ static int -ip_route_add (NMPlatform *platform, - NMPNlmFlags flags, - int addr_family, - const NMPlatformIPRoute *route) -{ - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - NMPObject obj; - - switch (addr_family) { - case AF_INET: - nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP4_ROUTE, (const NMPlatformObject *) route); - break; - case AF_INET6: - nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route); - break; - default: - nm_assert_not_reached (); - } - - nm_platform_ip_route_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (&obj)); - - nlmsg = _nl_msg_new_route (RTM_NEWROUTE, flags & NMP_NLM_FLAG_FMASK, &obj); - if (!nlmsg) - g_return_val_if_reached (-NME_BUG); - return do_add_addrroute (platform, - &obj, - nlmsg, - NM_FLAGS_HAS (flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE)); +ip_route_add(NMPlatform * platform, + NMPNlmFlags flags, + int addr_family, + const NMPlatformIPRoute *route) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + NMPObject obj; + + switch (addr_family) { + case AF_INET: + nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP4_ROUTE, (const NMPlatformObject *) route); + break; + case AF_INET6: + nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route); + break; + default: + nm_assert_not_reached(); + } + + nm_platform_ip_route_normalize(addr_family, NMP_OBJECT_CAST_IP_ROUTE(&obj)); + + nlmsg = _nl_msg_new_route(RTM_NEWROUTE, flags & NMP_NLM_FLAG_FMASK, &obj); + if (!nlmsg) + g_return_val_if_reached(-NME_BUG); + return do_add_addrroute(platform, + &obj, + nlmsg, + NM_FLAGS_HAS(flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE)); } static gboolean -object_delete (NMPlatform *platform, - const NMPObject *obj) -{ - nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL; - nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - - if (!NMP_OBJECT_IS_STACKINIT (obj)) - obj_keep_alive = nmp_object_ref (obj); - - switch (NMP_OBJECT_GET_TYPE (obj)) { - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - nlmsg = _nl_msg_new_route (RTM_DELROUTE, 0, obj); - break; - case NMP_OBJECT_TYPE_ROUTING_RULE: - nlmsg = _nl_msg_new_routing_rule (RTM_DELRULE, 0, NMP_OBJECT_CAST_ROUTING_RULE (obj)); - break; - case NMP_OBJECT_TYPE_QDISC: - nlmsg = _nl_msg_new_qdisc (RTM_DELQDISC, 0, NMP_OBJECT_CAST_QDISC (obj)); - break; - case NMP_OBJECT_TYPE_TFILTER: - nlmsg = _nl_msg_new_tfilter (RTM_DELTFILTER, 0, NMP_OBJECT_CAST_TFILTER (obj)); - break; - default: - break; - } - - if (!nlmsg) - g_return_val_if_reached (FALSE); - return do_delete_object (platform, obj, nlmsg); +object_delete(NMPlatform *platform, const NMPObject *obj) +{ + nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL; + nm_auto_nlmsg struct nl_msg * nlmsg = NULL; + + if (!NMP_OBJECT_IS_STACKINIT(obj)) + obj_keep_alive = nmp_object_ref(obj); + + switch (NMP_OBJECT_GET_TYPE(obj)) { + case NMP_OBJECT_TYPE_IP4_ROUTE: + case NMP_OBJECT_TYPE_IP6_ROUTE: + nlmsg = _nl_msg_new_route(RTM_DELROUTE, 0, obj); + break; + case NMP_OBJECT_TYPE_ROUTING_RULE: + nlmsg = _nl_msg_new_routing_rule(RTM_DELRULE, 0, NMP_OBJECT_CAST_ROUTING_RULE(obj)); + break; + case NMP_OBJECT_TYPE_QDISC: + nlmsg = _nl_msg_new_qdisc(RTM_DELQDISC, 0, NMP_OBJECT_CAST_QDISC(obj)); + break; + case NMP_OBJECT_TYPE_TFILTER: + nlmsg = _nl_msg_new_tfilter(RTM_DELTFILTER, 0, NMP_OBJECT_CAST_TFILTER(obj)); + break; + default: + break; + } + + if (!nlmsg) + g_return_val_if_reached(FALSE); + return do_delete_object(platform, obj, nlmsg); } /*****************************************************************************/ static int -ip_route_get (NMPlatform *platform, - int addr_family, - gconstpointer address, - int oif_ifindex, - NMPObject **out_route) -{ - const gboolean is_v4 = (addr_family == AF_INET); - const int addr_len = is_v4 ? 4 : 16; - int try_count = 0; - WaitForNlResponseResult seq_result; - int nle; - nm_auto_nmpobj NMPObject *route = NULL; - - nm_assert (NM_IS_LINUX_PLATFORM (platform)); - nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - nm_assert (address); - - do { - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[64]; - } req = { - .n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)), - .n.nlmsg_flags = NLM_F_REQUEST, - .n.nlmsg_type = RTM_GETROUTE, - .r.rtm_family = addr_family, - .r.rtm_tos = 0, - .r.rtm_dst_len = is_v4 ? 32 : 128, - .r.rtm_flags = 0x1000 /* RTM_F_LOOKUP_TABLE */, - }; - - nm_clear_pointer (&route, nmp_object_unref); - - if (!_nl_addattr_l (&req.n, sizeof (req), RTA_DST, address, addr_len)) - nm_assert_not_reached (); - - if (oif_ifindex > 0) { - gint32 ii = oif_ifindex; - - if (!_nl_addattr_l (&req.n, sizeof (req), RTA_OIF, &ii, sizeof (ii))) - nm_assert_not_reached (); - } - - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - nle = _nl_send_nlmsghdr (platform, &req.n, &seq_result, NULL, DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET, &route); - if (nle < 0) { - _LOGE ("get-route: failure sending netlink request \"%s\" (%d)", - nm_strerror_native (-nle), -nle); - return -NME_UNSPEC; - } - - delayed_action_handle_all (platform, FALSE); - - /* Retry, if we failed due to a cache resync. That can happen when the netlink - * socket fills up and we lost the response. */ - } while ( seq_result == WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC - && ++try_count < 10); - - if (seq_result < 0) { - /* negative seq_result is an errno from kernel. Map it to negative - * int (which are also errno). */ - return (int) seq_result; - } - - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { - if (route) { - NM_SET_OUT (out_route, g_steal_pointer (&route)); - return 0; - } - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN; - } - - return -NME_UNSPEC; +ip_route_get(NMPlatform * platform, + int addr_family, + gconstpointer address, + int oif_ifindex, + NMPObject ** out_route) +{ + const gboolean is_v4 = (addr_family == AF_INET); + const int addr_len = is_v4 ? 4 : 16; + int try_count = 0; + WaitForNlResponseResult seq_result; + int nle; + nm_auto_nmpobj NMPObject *route = NULL; + + nm_assert(NM_IS_LINUX_PLATFORM(platform)); + nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + nm_assert(address); + + do { + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[64]; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = RTM_GETROUTE, + .r.rtm_family = addr_family, + .r.rtm_tos = 0, + .r.rtm_dst_len = is_v4 ? 32 : 128, + .r.rtm_flags = 0x1000 /* RTM_F_LOOKUP_TABLE */, + }; + + nm_clear_pointer(&route, nmp_object_unref); + + if (!_nl_addattr_l(&req.n, sizeof(req), RTA_DST, address, addr_len)) + nm_assert_not_reached(); + + if (oif_ifindex > 0) { + gint32 ii = oif_ifindex; + + if (!_nl_addattr_l(&req.n, sizeof(req), RTA_OIF, &ii, sizeof(ii))) + nm_assert_not_reached(); + } + + seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + nle = _nl_send_nlmsghdr(platform, + &req.n, + &seq_result, + NULL, + DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET, + &route); + if (nle < 0) { + _LOGE("get-route: failure sending netlink request \"%s\" (%d)", + nm_strerror_native(-nle), + -nle); + return -NME_UNSPEC; + } + + delayed_action_handle_all(platform, FALSE); + + /* Retry, if we failed due to a cache resync. That can happen when the netlink + * socket fills up and we lost the response. */ + } while (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC && ++try_count < 10); + + if (seq_result < 0) { + /* negative seq_result is an errno from kernel. Map it to negative + * int (which are also errno). */ + return (int) seq_result; + } + + if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) { + if (route) { + NM_SET_OUT(out_route, g_steal_pointer(&route)); + return 0; + } + seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN; + } + + return -NME_UNSPEC; } /*****************************************************************************/ static int -routing_rule_add (NMPlatform *platform, - NMPNlmFlags flags, - const NMPlatformRoutingRule *routing_rule) +routing_rule_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformRoutingRule *routing_rule) { - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - nm_auto_nlmsg struct nl_msg *msg = NULL; - gs_free char *errmsg = NULL; - char s_buf[256]; - int nle; + WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + nm_auto_nlmsg struct nl_msg *msg = NULL; + gs_free char * errmsg = NULL; + char s_buf[256]; + int nle; - msg = _nl_msg_new_routing_rule (RTM_NEWRULE, flags, routing_rule); + msg = _nl_msg_new_routing_rule(RTM_NEWRULE, flags, routing_rule); - event_handler_read_netlink (platform, FALSE); + event_handler_read_netlink(platform, FALSE); - nle = _nl_send_nlmsg (platform, msg, &seq_result, &errmsg, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE ("do-add-rule: failed sending netlink request \"%s\" (%d)", - nm_strerror (nle), -nle); - return -NME_PL_NETLINK; - } + nle = _nl_send_nlmsg(platform, + msg, + &seq_result, + &errmsg, + DELAYED_ACTION_RESPONSE_TYPE_VOID, + NULL); + if (nle < 0) { + _LOGE("do-add-rule: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle); + return -NME_PL_NETLINK; + } - delayed_action_handle_all (platform, FALSE); + delayed_action_handle_all(platform, FALSE); - nm_assert (seq_result); + nm_assert(seq_result); - _NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK - ? LOGL_DEBUG - : LOGL_WARN, - "do-add-rule: %s", - wait_for_nl_response_to_string (seq_result, errmsg, s_buf, sizeof (s_buf))); + _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, + "do-add-rule: %s", + wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; - if (seq_result < 0) - return seq_result; - return -NME_UNSPEC; + if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) + return 0; + if (seq_result < 0) + return seq_result; + return -NME_UNSPEC; } /*****************************************************************************/ static int -qdisc_add (NMPlatform *platform, - NMPNlmFlags flags, - const NMPlatformQdisc *qdisc) +qdisc_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformQdisc *qdisc) { - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char *errmsg = NULL; - int nle; - char s_buf[256]; - nm_auto_nlmsg struct nl_msg *msg = NULL; + WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + gs_free char * errmsg = NULL; + int nle; + char s_buf[256]; + nm_auto_nlmsg struct nl_msg *msg = NULL; - /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind - * is undefined. */ + /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind + * is undefined. */ - msg = _nl_msg_new_qdisc (RTM_NEWQDISC, flags, qdisc); + msg = _nl_msg_new_qdisc(RTM_NEWQDISC, flags, qdisc); - event_handler_read_netlink (platform, FALSE); + event_handler_read_netlink(platform, FALSE); - nle = _nl_send_nlmsg (platform, msg, &seq_result, &errmsg, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE ("do-add-qdisc: failed sending netlink request \"%s\" (%d)", - nm_strerror (nle), -nle); - return -NME_PL_NETLINK; - } + nle = _nl_send_nlmsg(platform, + msg, + &seq_result, + &errmsg, + DELAYED_ACTION_RESPONSE_TYPE_VOID, + NULL); + if (nle < 0) { + _LOGE("do-add-qdisc: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle); + return -NME_PL_NETLINK; + } - delayed_action_handle_all (platform, FALSE); + delayed_action_handle_all(platform, FALSE); - nm_assert (seq_result); + nm_assert(seq_result); - _NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK - ? LOGL_DEBUG - : LOGL_WARN, - "do-add-qdisc: %s", - wait_for_nl_response_to_string (seq_result, errmsg, s_buf, sizeof (s_buf))); + _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, + "do-add-qdisc: %s", + wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; - if (seq_result < 0) - return seq_result; - return -NME_UNSPEC; + if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) + return 0; + if (seq_result < 0) + return seq_result; + return -NME_UNSPEC; } /*****************************************************************************/ static int -tfilter_add (NMPlatform *platform, - NMPNlmFlags flags, - const NMPlatformTfilter *tfilter) +tfilter_add(NMPlatform *platform, NMPNlmFlags flags, const NMPlatformTfilter *tfilter) { - WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; - gs_free char *errmsg = NULL; - int nle; - char s_buf[256]; - nm_auto_nlmsg struct nl_msg *msg = NULL; + WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN; + gs_free char * errmsg = NULL; + int nle; + char s_buf[256]; + nm_auto_nlmsg struct nl_msg *msg = NULL; - /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind - * and tfilter.action.kind is undefined. */ + /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind + * and tfilter.action.kind is undefined. */ - msg = _nl_msg_new_tfilter (RTM_NEWTFILTER, flags, tfilter); + msg = _nl_msg_new_tfilter(RTM_NEWTFILTER, flags, tfilter); - event_handler_read_netlink (platform, FALSE); + event_handler_read_netlink(platform, FALSE); - nle = _nl_send_nlmsg (platform, msg, &seq_result, &errmsg, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL); - if (nle < 0) { - _LOGE ("do-add-tfilter: failed sending netlink request \"%s\" (%d)", - nm_strerror (nle), -nle); - return -NME_PL_NETLINK; - } + nle = _nl_send_nlmsg(platform, + msg, + &seq_result, + &errmsg, + DELAYED_ACTION_RESPONSE_TYPE_VOID, + NULL); + if (nle < 0) { + _LOGE("do-add-tfilter: failed sending netlink request \"%s\" (%d)", nm_strerror(nle), -nle); + return -NME_PL_NETLINK; + } - delayed_action_handle_all (platform, FALSE); + delayed_action_handle_all(platform, FALSE); - nm_assert (seq_result); + nm_assert(seq_result); - _NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK - ? LOGL_DEBUG - : LOGL_WARN, - "do-add-tfilter: %s", - wait_for_nl_response_to_string (seq_result, errmsg, s_buf, sizeof (s_buf))); + _NMLOG(seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK ? LOGL_DEBUG : LOGL_WARN, + "do-add-tfilter: %s", + wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf))); - if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) - return 0; + if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) + return 0; - return -NME_UNSPEC; + return -NME_UNSPEC; } /*****************************************************************************/ static gboolean -event_handler (int fd, - GIOCondition io_condition, - gpointer user_data) +event_handler(int fd, GIOCondition io_condition, gpointer user_data) { - delayed_action_handle_all (NM_PLATFORM (user_data), TRUE); - return TRUE; + delayed_action_handle_all(NM_PLATFORM(user_data), TRUE); + return TRUE; } /*****************************************************************************/ /* copied from libnl3's recvmsgs() */ static int -event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events) -{ - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - struct nl_sock *sk = priv->nlh; - int n; - int err = 0; - gboolean multipart = 0; - gboolean interrupted = FALSE; - struct nlmsghdr *hdr; - WaitForNlResponseResult seq_result; - struct sockaddr_nl nla = {0}; - struct ucred creds; - gboolean creds_has; - nm_auto_free unsigned char *buf = NULL; +event_handler_recvmsgs(NMPlatform *platform, gboolean handle_events) +{ + NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + struct nl_sock * sk = priv->nlh; + int n; + int err = 0; + gboolean multipart = 0; + gboolean interrupted = FALSE; + struct nlmsghdr * hdr; + WaitForNlResponseResult seq_result; + struct sockaddr_nl nla = {0}; + struct ucred creds; + gboolean creds_has; + nm_auto_free unsigned char *buf = NULL; continue_reading: - nm_clear_pointer (&buf, free); - n = nl_recv (sk, &nla, &buf, &creds, &creds_has); - - if (n <= 0) { - - if (n == -NME_NL_MSG_TRUNC) { - int buf_size; - - /* the message receive buffer was too small. We lost one message, which - * is unfortunate. Try to double the buffer size for the next time. */ - buf_size = nl_socket_get_msg_buf_size (sk); - if (buf_size < 512*1024) { - buf_size *= 2; - _LOGT ("netlink: recvmsg: increase message buffer size for recvmsg() to %d bytes", buf_size); - if (nl_socket_set_msg_buf_size (sk, buf_size) < 0) - nm_assert_not_reached (); - if (!handle_events) - goto continue_reading; - } - } - - return n; - } - - hdr = (struct nlmsghdr *) buf; - while (nlmsg_ok (hdr, n)) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - gboolean abort_parsing = FALSE; - gboolean process_valid_msg = FALSE; - guint32 seq_number; - char buf_nlmsghdr[400]; - const char *extack_msg = NULL; - - msg = nlmsg_alloc_convert (hdr); - - nlmsg_set_proto (msg, NETLINK_ROUTE); - nlmsg_set_src (msg, &nla); - - if (!creds_has || creds.pid) { - if (!creds_has) - _LOGT ("netlink: recvmsg: received message without credentials"); - else - _LOGT ("netlink: recvmsg: received non-kernel message (pid %d)", creds.pid); - err = 0; - goto stop; - } - - _LOGt ("netlink: recvmsg: new message %s", - nl_nlmsghdr_to_str (hdr, buf_nlmsghdr, sizeof (buf_nlmsghdr))); - - nlmsg_set_creds (msg, &creds); - - if (hdr->nlmsg_flags & NLM_F_MULTI) - multipart = TRUE; - - if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { - /* - * We have to continue reading to clear - * all messages until a NLMSG_DONE is - * received and report the inconsistency. - */ - interrupted = TRUE; - } - - /* Other side wishes to see an ack for this message */ - if (hdr->nlmsg_flags & NLM_F_ACK) { - /* FIXME: implement */ - } - - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN; - - if (hdr->nlmsg_type == NLMSG_DONE) { - /* messages terminates a multipart message, this is - * usually the end of a message and therefore we slip - * out of the loop by default. the user may overrule - * this action by skipping this packet. */ - multipart = FALSE; - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; - } else if (hdr->nlmsg_type == NLMSG_NOOP) { - /* Message to be ignored, the default action is to - * skip this message if no callback is specified. The - * user may overrule this action by returning - * NL_PROCEED. */ - } else if (hdr->nlmsg_type == NLMSG_OVERRUN) { - /* Data got lost, report back to user. The default action is to - * quit parsing. The user may overrule this action by retuning - * NL_SKIP or NL_PROCEED (dangerous) */ - err = -NME_NL_MSG_OVERFLOW; - abort_parsing = TRUE; - } else if (hdr->nlmsg_type == NLMSG_ERROR) { - /* Message carries a nlmsgerr */ - struct nlmsgerr *e = nlmsg_data (hdr); - - if (hdr->nlmsg_len < nlmsg_size (sizeof (*e))) { - /* Truncated error message, the default action - * is to stop parsing. The user may overrule - * this action by returning NL_SKIP or - * NL_PROCEED (dangerous) */ - err = -NME_NL_MSG_TRUNC; - abort_parsing = TRUE; - } else if (e->error) { - int errsv = nm_errno_native (e->error); - - if ( NM_FLAGS_HAS (hdr->nlmsg_flags, NLM_F_ACK_TLVS) - && hdr->nlmsg_len >= sizeof (*e) + e->msg.nlmsg_len) { - static const struct nla_policy policy[] = { - [NLMSGERR_ATTR_MSG] = { .type = NLA_STRING }, - [NLMSGERR_ATTR_OFFS] = { .type = NLA_U32 }, - }; - struct nlattr *tb[G_N_ELEMENTS (policy)]; - struct nlattr *tlvs; - - tlvs = (struct nlattr *) ((char *) e + sizeof (*e) + e->msg.nlmsg_len - NLMSG_HDRLEN); - if (nla_parse_arr (tb, - tlvs, - hdr->nlmsg_len - sizeof (*e) - e->msg.nlmsg_len, - policy) >= 0) { - if (tb[NLMSGERR_ATTR_MSG]) - extack_msg = nla_get_string (tb[NLMSGERR_ATTR_MSG]); - } - } - - /* Error message reported back from kernel. */ - _LOGD ("netlink: recvmsg: error message from kernel: %s (%d)%s%s%s for request %d", - nm_strerror_native (errsv), - errsv, - NM_PRINT_FMT_QUOTED (extack_msg, " \"", extack_msg, "\"", ""), - nlmsg_hdr (msg)->nlmsg_seq); - seq_result = -NM_ERRNO_NATIVE (errsv); - } else - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; - } else - process_valid_msg = TRUE; - - seq_number = nlmsg_hdr (msg)->nlmsg_seq; - - /* check whether the seq number is different from before, and - * whether the previous number (@nlh_seq_last_seen) is a pending - * refresh-all request. In that case, the pending request is thereby - * completed. - * - * We must do that before processing the message with event_valid_msg(), - * because we must track the completion of the pending request before that. */ - event_seq_check_refresh_all (platform, seq_number); - - if (process_valid_msg) { - /* Valid message (not checking for MULTIPART bit to - * get along with broken kernels. NL_SKIP has no - * effect on this. */ - - event_valid_msg (platform, msg, handle_events); - - seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; - } - - event_seq_check (platform, seq_number, seq_result, extack_msg); - - if (abort_parsing) - goto stop; - - err = 0; - hdr = nlmsg_next (hdr, &n); - } - - if (multipart) { - /* Multipart message not yet complete, continue reading */ - goto continue_reading; - } + nm_clear_pointer(&buf, free); + n = nl_recv(sk, &nla, &buf, &creds, &creds_has); + + if (n <= 0) { + if (n == -NME_NL_MSG_TRUNC) { + int buf_size; + + /* the message receive buffer was too small. We lost one message, which + * is unfortunate. Try to double the buffer size for the next time. */ + buf_size = nl_socket_get_msg_buf_size(sk); + if (buf_size < 512 * 1024) { + buf_size *= 2; + _LOGT("netlink: recvmsg: increase message buffer size for recvmsg() to %d bytes", + buf_size); + if (nl_socket_set_msg_buf_size(sk, buf_size) < 0) + nm_assert_not_reached(); + if (!handle_events) + goto continue_reading; + } + } + + return n; + } + + hdr = (struct nlmsghdr *) buf; + while (nlmsg_ok(hdr, n)) { + nm_auto_nlmsg struct nl_msg *msg = NULL; + gboolean abort_parsing = FALSE; + gboolean process_valid_msg = FALSE; + guint32 seq_number; + char buf_nlmsghdr[400]; + const char * extack_msg = NULL; + + msg = nlmsg_alloc_convert(hdr); + + nlmsg_set_proto(msg, NETLINK_ROUTE); + nlmsg_set_src(msg, &nla); + + if (!creds_has || creds.pid) { + if (!creds_has) + _LOGT("netlink: recvmsg: received message without credentials"); + else + _LOGT("netlink: recvmsg: received non-kernel message (pid %d)", creds.pid); + err = 0; + goto stop; + } + + _LOGt("netlink: recvmsg: new message %s", + nl_nlmsghdr_to_str(hdr, buf_nlmsghdr, sizeof(buf_nlmsghdr))); + + nlmsg_set_creds(msg, &creds); + + if (hdr->nlmsg_flags & NLM_F_MULTI) + multipart = TRUE; + + if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { + /* + * We have to continue reading to clear + * all messages until a NLMSG_DONE is + * received and report the inconsistency. + */ + interrupted = TRUE; + } + + /* Other side wishes to see an ack for this message */ + if (hdr->nlmsg_flags & NLM_F_ACK) { + /* FIXME: implement */ + } + + seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN; + + if (hdr->nlmsg_type == NLMSG_DONE) { + /* messages terminates a multipart message, this is + * usually the end of a message and therefore we slip + * out of the loop by default. the user may overrule + * this action by skipping this packet. */ + multipart = FALSE; + seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; + } else if (hdr->nlmsg_type == NLMSG_NOOP) { + /* Message to be ignored, the default action is to + * skip this message if no callback is specified. The + * user may overrule this action by returning + * NL_PROCEED. */ + } else if (hdr->nlmsg_type == NLMSG_OVERRUN) { + /* Data got lost, report back to user. The default action is to + * quit parsing. The user may overrule this action by returning + * NL_SKIP or NL_PROCEED (dangerous) */ + err = -NME_NL_MSG_OVERFLOW; + abort_parsing = TRUE; + } else if (hdr->nlmsg_type == NLMSG_ERROR) { + /* Message carries a nlmsgerr */ + struct nlmsgerr *e = nlmsg_data(hdr); + + if (hdr->nlmsg_len < nlmsg_size(sizeof(*e))) { + /* Truncated error message, the default action + * is to stop parsing. The user may overrule + * this action by returning NL_SKIP or + * NL_PROCEED (dangerous) */ + err = -NME_NL_MSG_TRUNC; + abort_parsing = TRUE; + } else if (e->error) { + int errsv = nm_errno_native(e->error); + + if (NM_FLAGS_HAS(hdr->nlmsg_flags, NLM_F_ACK_TLVS) + && hdr->nlmsg_len >= sizeof(*e) + e->msg.nlmsg_len) { + static const struct nla_policy policy[] = { + [NLMSGERR_ATTR_MSG] = {.type = NLA_STRING}, + [NLMSGERR_ATTR_OFFS] = {.type = NLA_U32}, + }; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + struct nlattr *tlvs; + + tlvs = (struct nlattr *) ((char *) e + sizeof(*e) + e->msg.nlmsg_len + - NLMSG_HDRLEN); + if (nla_parse_arr(tb, + tlvs, + hdr->nlmsg_len - sizeof(*e) - e->msg.nlmsg_len, + policy) + >= 0) { + if (tb[NLMSGERR_ATTR_MSG]) + extack_msg = nla_get_string(tb[NLMSGERR_ATTR_MSG]); + } + } + + /* Error message reported back from kernel. */ + _LOGD("netlink: recvmsg: error message from kernel: %s (%d)%s%s%s for request %d", + nm_strerror_native(errsv), + errsv, + NM_PRINT_FMT_QUOTED(extack_msg, " \"", extack_msg, "\"", ""), + nlmsg_hdr(msg)->nlmsg_seq); + seq_result = -NM_ERRNO_NATIVE(errsv); + } else + seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; + } else + process_valid_msg = TRUE; + + seq_number = nlmsg_hdr(msg)->nlmsg_seq; + + /* check whether the seq number is different from before, and + * whether the previous number (@nlh_seq_last_seen) is a pending + * refresh-all request. In that case, the pending request is thereby + * completed. + * + * We must do that before processing the message with event_valid_msg(), + * because we must track the completion of the pending request before that. */ + event_seq_check_refresh_all(platform, seq_number); + + if (process_valid_msg) { + /* Valid message (not checking for MULTIPART bit to + * get along with broken kernels. NL_SKIP has no + * effect on this. */ + + event_valid_msg(platform, msg, handle_events); + + seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK; + } + + event_seq_check(platform, seq_number, seq_result, extack_msg); + + if (abort_parsing) + goto stop; + + err = 0; + hdr = nlmsg_next(hdr, &n); + } + + if (multipart) { + /* Multipart message not yet complete, continue reading */ + goto continue_reading; + } stop: - if (!handle_events) { - /* when we don't handle events, we want to drain all messages from the socket - * without handling the messages (but still check for sequence numbers). - * Repeat reading. */ - goto continue_reading; - } + if (!handle_events) { + /* when we don't handle events, we want to drain all messages from the socket + * without handling the messages (but still check for sequence numbers). + * Repeat reading. */ + goto continue_reading; + } - if (interrupted) - return -NME_NL_DUMP_INTR; - return err; + if (interrupted) + return -NME_NL_DUMP_INTR; + return err; } /*****************************************************************************/ static gboolean -event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks) -{ - nm_auto_pop_netns NMPNetns *netns = NULL; - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - int r; - struct pollfd pfd; - gboolean any = FALSE; - int timeout_msec; - struct { - guint32 seq_number; - gint64 timeout_abs_ns; - gint64 now_ns; - } next; - - if (!nm_platform_netns_push (platform, &netns)) { - delayed_action_wait_for_nl_response_complete_all (platform, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS); - return FALSE; - } - - for (;;) { - for (;;) { - int nle; - - nle = event_handler_recvmsgs (platform, TRUE); - - if (nle < 0) { - switch (nle) { - case -EAGAIN: - goto after_read; - case -NME_NL_DUMP_INTR: - _LOGD ("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", nm_strerror (nle), nle); - break; - case -NME_NL_MSG_TRUNC: - case -ENOBUFS: - _LOGI ("netlink: read: %s. Need to resynchronize platform cache", - ({ - const char *_reason = "unknown"; - switch (nle) { - case -NME_NL_MSG_TRUNC: _reason = "message truncated"; break; - case -ENOBUFS: _reason = "too many netlink events"; break; - } - _reason; - })); - event_handler_recvmsgs (platform, FALSE); - delayed_action_wait_for_nl_response_complete_all (platform, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC); - - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL | - DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS | - DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - NULL); - break; - default: - _LOGE ("netlink: read: failed to retrieve incoming events: %s (%d)", nm_strerror (nle), nle); - break; - } - } - any = TRUE; - } +event_handler_read_netlink(NMPlatform *platform, gboolean wait_for_acks) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + NMLinuxPlatformPrivate * priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + int r; + struct pollfd pfd; + gboolean any = FALSE; + int timeout_msec; + struct { + guint32 seq_number; + gint64 timeout_abs_ns; + gint64 now_ns; + } next; + + if (!nm_platform_netns_push(platform, &netns)) { + delayed_action_wait_for_nl_response_complete_all(platform, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS); + return FALSE; + } + + for (;;) { + for (;;) { + int nle; + + nle = event_handler_recvmsgs(platform, TRUE); + + if (nle < 0) { + switch (nle) { + case -EAGAIN: + goto after_read; + case -NME_NL_DUMP_INTR: + _LOGD("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", + nm_strerror(nle), + nle); + break; + case -NME_NL_MSG_TRUNC: + case -ENOBUFS: + _LOGI("netlink: read: %s. Need to resynchronize platform cache", ({ + const char *_reason = "unknown"; + switch (nle) { + case -NME_NL_MSG_TRUNC: + _reason = "message truncated"; + break; + case -ENOBUFS: + _reason = "too many netlink events"; + break; + } + _reason; + })); + event_handler_recvmsgs(platform, FALSE); + delayed_action_wait_for_nl_response_complete_all( + platform, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC); + + delayed_action_schedule(platform, + DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL + | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS + | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, + NULL); + break; + default: + _LOGE("netlink: read: failed to retrieve incoming events: %s (%d)", + nm_strerror(nle), + nle); + break; + } + } + any = TRUE; + } after_read: - if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) - return any; + if (!NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) + return any; - delayed_action_wait_for_nl_response_complete_check (platform, - WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN, - &next.seq_number, - &next.timeout_abs_ns, - &next.now_ns); + delayed_action_wait_for_nl_response_complete_check(platform, + WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN, + &next.seq_number, + &next.timeout_abs_ns, + &next.now_ns); - if ( !wait_for_acks - || !NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) - return any; + if (!wait_for_acks + || !NM_FLAGS_HAS(priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) + return any; - nm_assert (next.seq_number); - nm_assert (next.now_ns > 0); - nm_assert (next.timeout_abs_ns > next.now_ns); + nm_assert(next.seq_number); + nm_assert(next.now_ns > 0); + nm_assert(next.timeout_abs_ns > next.now_ns); - _LOGT ("netlink: read: wait for ACK for sequence number %u...", next.seq_number); + _LOGT("netlink: read: wait for ACK for sequence number %u...", next.seq_number); - timeout_msec = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NSEC_PER_SEC / 1000); + timeout_msec = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NSEC_PER_SEC / 1000); - memset (&pfd, 0, sizeof (pfd)); - pfd.fd = nl_socket_get_fd (priv->nlh); - pfd.events = POLLIN; - r = poll (&pfd, 1, MAX (1, timeout_msec)); + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = nl_socket_get_fd(priv->nlh); + pfd.events = POLLIN; + r = poll(&pfd, 1, MAX(1, timeout_msec)); - if (r == 0) { - /* timeout and there is nothing to read. */ - goto after_read; - } + if (r == 0) { + /* timeout and there is nothing to read. */ + goto after_read; + } - if (r < 0) { - int errsv = errno; + if (r < 0) { + int errsv = errno; - if (errsv != EINTR) { - _LOGE ("netlink: read: poll failed with %s", nm_strerror_native (errsv)); - delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL); - return any; - } - /* Continue to read again, even if there might be nothing to read after EINTR. */ - } - } + if (errsv != EINTR) { + _LOGE("netlink: read: poll failed with %s", nm_strerror_native(errsv)); + delayed_action_wait_for_nl_response_complete_all( + platform, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL); + return any; + } + /* Continue to read again, even if there might be nothing to read after EINTR. */ + } + } } /*****************************************************************************/ static void -cache_update_link_udev (NMPlatform *platform, - int ifindex, - struct udev_device *udevice) +cache_update_link_udev(NMPlatform *platform, int ifindex, struct udev_device *udevice) { - nm_auto_nmpobj const NMPObject *obj_old = NULL; - nm_auto_nmpobj const NMPObject *obj_new = NULL; - NMPCacheOpsType cache_op; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + nm_auto_nmpobj const NMPObject *obj_new = NULL; + NMPCacheOpsType cache_op; - cache_op = nmp_cache_update_link_udev (nm_platform_get_cache (platform), ifindex, udevice, &obj_old, &obj_new); + cache_op = nmp_cache_update_link_udev(nm_platform_get_cache(platform), + ifindex, + udevice, + &obj_old, + &obj_new); - if (cache_op != NMP_CACHE_OPS_UNCHANGED) { - nm_auto_pop_netns NMPNetns *netns = NULL; + if (cache_op != NMP_CACHE_OPS_UNCHANGED) { + nm_auto_pop_netns NMPNetns *netns = NULL; - cache_on_change (platform, cache_op, obj_old, obj_new); - if (!nm_platform_netns_push (platform, &netns)) - return; - nm_platform_cache_update_emit_signal (platform, cache_op, obj_old, obj_new); - } + cache_on_change(platform, cache_op, obj_old, obj_new); + if (!nm_platform_netns_push(platform, &netns)) + return; + nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new); + } } static void -udev_device_added (NMPlatform *platform, - struct udev_device *udevice) -{ - const char *ifname; - const char *ifindex_s; - int ifindex; - - ifname = udev_device_get_sysname (udevice); - if (!ifname) { - _LOGD ("udev-add: failed to get device's interface"); - return; - } - - ifindex_s = udev_device_get_property_value (udevice, "IFINDEX"); - if (!ifindex_s) { - _LOGW ("udev-add[%s]failed to get device's ifindex", ifname); - return; - } - ifindex = _nm_utils_ascii_str_to_int64 (ifindex_s, 10, 1, G_MAXINT, 0); - if (ifindex <= 0) { - _LOGW ("udev-add[%s]: retrieved invalid IFINDEX=%d", ifname, ifindex); - return; - } - - if (!udev_device_get_syspath (udevice)) { - _LOGD ("udev-add[%s,%d]: couldn't determine device path; ignoring...", ifname, ifindex); - return; - } - - _LOGT ("udev-add[%s,%d]: device added", ifname, ifindex); - cache_update_link_udev (platform, ifindex, udevice); +udev_device_added(NMPlatform *platform, struct udev_device *udevice) +{ + const char *ifname; + const char *ifindex_s; + int ifindex; + + ifname = udev_device_get_sysname(udevice); + if (!ifname) { + _LOGD("udev-add: failed to get device's interface"); + return; + } + + ifindex_s = udev_device_get_property_value(udevice, "IFINDEX"); + if (!ifindex_s) { + _LOGW("udev-add[%s]failed to get device's ifindex", ifname); + return; + } + ifindex = _nm_utils_ascii_str_to_int64(ifindex_s, 10, 1, G_MAXINT, 0); + if (ifindex <= 0) { + _LOGW("udev-add[%s]: retrieved invalid IFINDEX=%d", ifname, ifindex); + return; + } + + if (!udev_device_get_syspath(udevice)) { + _LOGD("udev-add[%s,%d]: couldn't determine device path; ignoring...", ifname, ifindex); + return; + } + + _LOGT("udev-add[%s,%d]: device added", ifname, ifindex); + cache_update_link_udev(platform, ifindex, udevice); } static gboolean -_udev_device_removed_match_link (const NMPObject *obj, gpointer udevice) +_udev_device_removed_match_link(const NMPObject *obj, gpointer udevice) { - return obj->_link.udev.device == udevice; + return obj->_link.udev.device == udevice; } static void -udev_device_removed (NMPlatform *platform, - struct udev_device *udevice) +udev_device_removed(NMPlatform *platform, struct udev_device *udevice) { - const char *ifindex_s; - int ifindex = 0; + const char *ifindex_s; + int ifindex = 0; - ifindex_s = udev_device_get_property_value (udevice, "IFINDEX"); - ifindex = _nm_utils_ascii_str_to_int64 (ifindex_s, 10, 1, G_MAXINT, 0); - if (ifindex <= 0) { - const NMPObject *obj; + ifindex_s = udev_device_get_property_value(udevice, "IFINDEX"); + ifindex = _nm_utils_ascii_str_to_int64(ifindex_s, 10, 1, G_MAXINT, 0); + if (ifindex <= 0) { + const NMPObject *obj; - obj = nmp_cache_lookup_link_full (nm_platform_get_cache (platform), - 0, NULL, FALSE, NM_LINK_TYPE_NONE, _udev_device_removed_match_link, udevice); - if (obj) - ifindex = obj->link.ifindex; - } + obj = nmp_cache_lookup_link_full(nm_platform_get_cache(platform), + 0, + NULL, + FALSE, + NM_LINK_TYPE_NONE, + _udev_device_removed_match_link, + udevice); + if (obj) + ifindex = obj->link.ifindex; + } - _LOGD ("udev-remove: IFINDEX=%d", ifindex); - if (ifindex <= 0) - return; + _LOGD("udev-remove: IFINDEX=%d", ifindex); + if (ifindex <= 0) + return; - cache_update_link_udev (platform, ifindex, NULL); + cache_update_link_udev(platform, ifindex, NULL); } static void -handle_udev_event (NMUdevClient *udev_client, - struct udev_device *udevice, - gpointer user_data) +handle_udev_event(NMUdevClient *udev_client, struct udev_device *udevice, gpointer user_data) { - nm_auto_pop_netns NMPNetns *netns = NULL; - NMPlatform *platform = NM_PLATFORM (user_data); - const char *subsys; - const char *ifindex; - guint64 seqnum; - const char *action; + nm_auto_pop_netns NMPNetns *netns = NULL; + NMPlatform * platform = NM_PLATFORM(user_data); + const char * subsys; + const char * ifindex; + guint64 seqnum; + const char * action; - action = udev_device_get_action (udevice); - g_return_if_fail (action); + action = udev_device_get_action(udevice); + g_return_if_fail(action); - subsys = udev_device_get_subsystem (udevice); - g_return_if_fail (nm_streq0 (subsys, "net")); + subsys = udev_device_get_subsystem(udevice); + g_return_if_fail(nm_streq0(subsys, "net")); - if (!nm_platform_netns_push (platform, &netns)) - return; + if (!nm_platform_netns_push(platform, &netns)) + return; - ifindex = udev_device_get_property_value (udevice, "IFINDEX"); - seqnum = udev_device_get_seqnum (udevice); - _LOGD ("UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, - action, subsys, udev_device_get_sysname (udevice), - ifindex ?: "unknown", seqnum); + ifindex = udev_device_get_property_value(udevice, "IFINDEX"); + seqnum = udev_device_get_seqnum(udevice); + _LOGD("UDEV event: action '%s' subsys '%s' device '%s' (%s); seqnum=%" G_GUINT64_FORMAT, + action, + subsys, + udev_device_get_sysname(udevice), + ifindex ?: "unknown", + seqnum); - if (NM_IN_STRSET (action, "add", "move")) - udev_device_added (platform, udevice); - else if (NM_IN_STRSET (action, "remove")) - udev_device_removed (platform, udevice); + if (NM_IN_STRSET(action, "add", "move")) + udev_device_added(platform, udevice); + else if (NM_IN_STRSET(action, "remove")) + udev_device_removed(platform, udevice); } /*****************************************************************************/ void -nm_linux_platform_setup (void) +nm_linux_platform_setup(void) { - nm_platform_setup (nm_linux_platform_new (FALSE, FALSE)); + nm_platform_setup(nm_linux_platform_new(FALSE, FALSE)); } /*****************************************************************************/ static void -nm_linux_platform_init (NMLinuxPlatform *self) +nm_linux_platform_init(NMLinuxPlatform *self) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (self); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(self); - priv->delayed_action.list_master_connected = g_ptr_array_new (); - priv->delayed_action.list_refresh_link = g_ptr_array_new (); - priv->delayed_action.list_wait_for_nl_response = g_array_new (FALSE, TRUE, sizeof (DelayedActionWaitForNlResponseData)); + priv->delayed_action.list_master_connected = g_ptr_array_new(); + priv->delayed_action.list_refresh_link = g_ptr_array_new(); + priv->delayed_action.list_wait_for_nl_response = + g_array_new(FALSE, TRUE, sizeof(DelayedActionWaitForNlResponseData)); } static void -constructed (GObject *_object) -{ - NMPlatform *platform = NM_PLATFORM (_object); - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - int nle; - int fd; - - nm_assert (!platform->_netns || platform->_netns == nmp_netns_get_current ()); - - if (nm_platform_get_use_udev (platform)) { - priv->udev_client = nm_udev_client_new (NM_MAKE_STRV ("net"), - handle_udev_event, platform); - } - - _LOGD ("create (%s netns, %s, %s udev)", - !platform->_netns ? "ignore" : "use", - !platform->_netns && nmp_netns_is_initial () - ? "initial netns" - : (!nmp_netns_get_current () - ? "no netns support" - : nm_sprintf_bufa (100, "in netns[%p]%s", - nmp_netns_get_current (), - nmp_netns_get_current () == nmp_netns_get_initial () ? "/main" : "")), - nm_platform_get_use_udev (platform) ? "use" : "no"); - - - priv->genl = nl_socket_alloc (); - g_assert (priv->genl); - - nle = nl_connect (priv->genl, NETLINK_GENERIC); - if (nle) { - _LOGE ("unable to connect the generic netlink socket \"%s\" (%d)", - nm_strerror (nle), -nle); - nl_socket_free (priv->genl); - priv->genl = NULL; - } - - priv->nlh = nl_socket_alloc (); - g_assert (priv->nlh); - - nle = nl_connect (priv->nlh, NETLINK_ROUTE); - g_assert (!nle); - nle = nl_socket_set_passcred (priv->nlh, 1); - g_assert (!nle); - - /* No blocking for event socket, so that we can drain it safely. */ - nle = nl_socket_set_nonblocking (priv->nlh); - g_assert (!nle); - - /* use 8 MB for receive socket kernel queue. */ - nle = nl_socket_set_buffer_size (priv->nlh, 8*1024*1024, 0); - g_assert (!nle); - - nle = nl_socket_set_ext_ack (priv->nlh, TRUE); - if (nle) - _LOGD ("could not enable extended acks on netlink socket"); - - /* explicitly set the msg buffer size and disable MSG_PEEK. - * If we later encounter NME_NL_MSG_TRUNC, we will adjust the buffer size. */ - nl_socket_disable_msg_peek (priv->nlh); - nle = nl_socket_set_msg_buf_size (priv->nlh, 32 * 1024); - g_assert (!nle); - - nle = nl_socket_add_memberships (priv->nlh, - RTNLGRP_IPV4_IFADDR, - RTNLGRP_IPV4_ROUTE, - RTNLGRP_IPV4_RULE, - RTNLGRP_IPV6_RULE, - RTNLGRP_IPV6_IFADDR, - RTNLGRP_IPV6_ROUTE, - RTNLGRP_LINK, - RTNLGRP_TC, - 0); - g_assert (!nle); - - fd = nl_socket_get_fd (priv->nlh); - - _LOGD ("Netlink socket for events established: port=%u, fd=%d", nl_socket_get_local_port (priv->nlh), fd); - - priv->event_source = nm_g_unix_fd_source_new (fd, - G_IO_IN | G_IO_NVAL | G_IO_PRI | G_IO_ERR | G_IO_HUP, - G_PRIORITY_DEFAULT, - event_handler, - platform, - NULL); - g_source_attach (priv->event_source, NULL); - - /* complete construction of the GObject instance before populating the cache. */ - G_OBJECT_CLASS (nm_linux_platform_parent_class)->constructed (_object); - - _LOGD ("populate platform cache"); - delayed_action_schedule (platform, - DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES | - DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL | - DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS | - DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, - NULL); - - delayed_action_handle_all (platform, FALSE); - - /* Set up udev monitoring */ - if (priv->udev_client) { - struct udev_enumerate *enumerator; - struct udev_list_entry *devices, *l; - - /* And read initial device list */ - enumerator = nm_udev_client_enumerate_new (priv->udev_client); - - udev_enumerate_add_match_is_initialized (enumerator); - - udev_enumerate_scan_devices (enumerator); - - devices = udev_enumerate_get_list_entry (enumerator); - for (l = devices; l; l = udev_list_entry_get_next (l)) { - struct udev_device *udevice; - - udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator), - udev_list_entry_get_name (l)); - if (!udevice) - continue; - - udev_device_added (platform, udevice); - udev_device_unref (udevice); - } - - udev_enumerate_unref (enumerator); - } +constructed(GObject *_object) +{ + NMPlatform * platform = NM_PLATFORM(_object); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + int nle; + int fd; + + nm_assert(!platform->_netns || platform->_netns == nmp_netns_get_current()); + + if (nm_platform_get_use_udev(platform)) { + priv->udev_client = nm_udev_client_new(NM_MAKE_STRV("net"), handle_udev_event, platform); + } + + _LOGD("create (%s netns, %s, %s udev)", + !platform->_netns ? "ignore" : "use", + !platform->_netns && nmp_netns_is_initial() + ? "initial netns" + : (!nmp_netns_get_current() + ? "no netns support" + : nm_sprintf_bufa(100, + "in netns[%p]%s", + nmp_netns_get_current(), + nmp_netns_get_current() == nmp_netns_get_initial() ? "/main" + : "")), + nm_platform_get_use_udev(platform) ? "use" : "no"); + + priv->genl = nl_socket_alloc(); + g_assert(priv->genl); + + nle = nl_connect(priv->genl, NETLINK_GENERIC); + if (nle) { + _LOGE("unable to connect the generic netlink socket \"%s\" (%d)", nm_strerror(nle), -nle); + nl_socket_free(priv->genl); + priv->genl = NULL; + } + + priv->nlh = nl_socket_alloc(); + g_assert(priv->nlh); + + nle = nl_connect(priv->nlh, NETLINK_ROUTE); + g_assert(!nle); + nle = nl_socket_set_passcred(priv->nlh, 1); + g_assert(!nle); + + /* No blocking for event socket, so that we can drain it safely. */ + nle = nl_socket_set_nonblocking(priv->nlh); + g_assert(!nle); + + /* use 8 MB for receive socket kernel queue. */ + nle = nl_socket_set_buffer_size(priv->nlh, 8 * 1024 * 1024, 0); + g_assert(!nle); + + nle = nl_socket_set_ext_ack(priv->nlh, TRUE); + if (nle) + _LOGD("could not enable extended acks on netlink socket"); + + /* explicitly set the msg buffer size and disable MSG_PEEK. + * If we later encounter NME_NL_MSG_TRUNC, we will adjust the buffer size. */ + nl_socket_disable_msg_peek(priv->nlh); + nle = nl_socket_set_msg_buf_size(priv->nlh, 32 * 1024); + g_assert(!nle); + + nle = nl_socket_add_memberships(priv->nlh, + RTNLGRP_IPV4_IFADDR, + RTNLGRP_IPV4_ROUTE, + RTNLGRP_IPV4_RULE, + RTNLGRP_IPV6_RULE, + RTNLGRP_IPV6_IFADDR, + RTNLGRP_IPV6_ROUTE, + RTNLGRP_LINK, + RTNLGRP_TC, + 0); + g_assert(!nle); + + fd = nl_socket_get_fd(priv->nlh); + + _LOGD("Netlink socket for events established: port=%u, fd=%d", + nl_socket_get_local_port(priv->nlh), + fd); + + priv->event_source = + nm_g_unix_fd_source_new(fd, + G_IO_IN | G_IO_NVAL | G_IO_PRI | G_IO_ERR | G_IO_HUP, + G_PRIORITY_DEFAULT, + event_handler, + platform, + NULL); + g_source_attach(priv->event_source, NULL); + + /* complete construction of the GObject instance before populating the cache. */ + G_OBJECT_CLASS(nm_linux_platform_parent_class)->constructed(_object); + + _LOGD("populate platform cache"); + delayed_action_schedule( + platform, + DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES + | DELAYED_ACTION_TYPE_REFRESH_ALL_ROUTING_RULES_ALL + | DELAYED_ACTION_TYPE_REFRESH_ALL_QDISCS | DELAYED_ACTION_TYPE_REFRESH_ALL_TFILTERS, + NULL); + + delayed_action_handle_all(platform, FALSE); + + /* Set up udev monitoring */ + if (priv->udev_client) { + struct udev_enumerate * enumerator; + struct udev_list_entry *devices, *l; + + /* And read initial device list */ + enumerator = nm_udev_client_enumerate_new(priv->udev_client); + + udev_enumerate_add_match_is_initialized(enumerator); + + udev_enumerate_scan_devices(enumerator); + + devices = udev_enumerate_get_list_entry(enumerator); + for (l = devices; l; l = udev_list_entry_get_next(l)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), + udev_list_entry_get_name(l)); + if (!udevice) + continue; + + udev_device_added(platform, udevice); + udev_device_unref(udevice); + } + + udev_enumerate_unref(enumerator); + } } NMPlatform * -nm_linux_platform_new (gboolean log_with_ptr, gboolean netns_support) +nm_linux_platform_new(gboolean log_with_ptr, gboolean netns_support) { - gboolean use_udev = FALSE; + gboolean use_udev = FALSE; - if ( nmp_netns_is_initial () - && access ("/sys", W_OK) == 0) - use_udev = TRUE; + if (nmp_netns_is_initial() && access("/sys", W_OK) == 0) + use_udev = TRUE; - return g_object_new (NM_TYPE_LINUX_PLATFORM, - NM_PLATFORM_LOG_WITH_PTR, log_with_ptr, - NM_PLATFORM_USE_UDEV, use_udev, - NM_PLATFORM_NETNS_SUPPORT, netns_support, - NULL); + return g_object_new(NM_TYPE_LINUX_PLATFORM, + NM_PLATFORM_LOG_WITH_PTR, + log_with_ptr, + NM_PLATFORM_USE_UDEV, + use_udev, + NM_PLATFORM_NETNS_SUPPORT, + netns_support, + NULL); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMPlatform *platform = NM_PLATFORM (object); - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + NMPlatform * platform = NM_PLATFORM(object); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); - _LOGD ("dispose"); + _LOGD("dispose"); - delayed_action_wait_for_nl_response_complete_all (platform, - WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING); + delayed_action_wait_for_nl_response_complete_all(platform, + WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING); - priv->delayed_action.flags = DELAYED_ACTION_TYPE_NONE; - g_ptr_array_set_size (priv->delayed_action.list_master_connected, 0); - g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0); + priv->delayed_action.flags = DELAYED_ACTION_TYPE_NONE; + g_ptr_array_set_size(priv->delayed_action.list_master_connected, 0); + g_ptr_array_set_size(priv->delayed_action.list_refresh_link, 0); - G_OBJECT_CLASS (nm_linux_platform_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_linux_platform_parent_class)->dispose(object); } static void -finalize (GObject *object) +finalize(GObject *object) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (object); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(object); - g_ptr_array_unref (priv->delayed_action.list_master_connected); - g_ptr_array_unref (priv->delayed_action.list_refresh_link); - g_array_unref (priv->delayed_action.list_wait_for_nl_response); + g_ptr_array_unref(priv->delayed_action.list_master_connected); + g_ptr_array_unref(priv->delayed_action.list_refresh_link); + g_array_unref(priv->delayed_action.list_wait_for_nl_response); - nl_socket_free (priv->genl); + nl_socket_free(priv->genl); - nm_clear_g_source_inst (&priv->event_source); + nm_clear_g_source_inst(&priv->event_source); - nl_socket_free (priv->nlh); + nl_socket_free(priv->nlh); - if (priv->sysctl_get_prev_values) { - sysctl_clear_cache_list = g_slist_remove (sysctl_clear_cache_list, object); - g_hash_table_destroy (priv->sysctl_get_prev_values); - } + if (priv->sysctl_get_prev_values) { + sysctl_clear_cache_list = g_slist_remove(sysctl_clear_cache_list, object); + g_hash_table_destroy(priv->sysctl_get_prev_values); + } - priv->udev_client = nm_udev_client_unref (priv->udev_client); + priv->udev_client = nm_udev_client_unref(priv->udev_client); - G_OBJECT_CLASS (nm_linux_platform_parent_class)->finalize (object); + G_OBJECT_CLASS(nm_linux_platform_parent_class)->finalize(object); } static void -nm_linux_platform_class_init (NMLinuxPlatformClass *klass) +nm_linux_platform_class_init(NMLinuxPlatformClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMPlatformClass *platform_class = NM_PLATFORM_CLASS (klass); + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMPlatformClass *platform_class = NM_PLATFORM_CLASS(klass); - object_class->constructed = constructed; - object_class->dispose = dispose; - object_class->finalize = finalize; + object_class->constructed = constructed; + object_class->dispose = dispose; + object_class->finalize = finalize; - platform_class->sysctl_set = sysctl_set; - platform_class->sysctl_set_async = sysctl_set_async; - platform_class->sysctl_get = sysctl_get; + platform_class->sysctl_set = sysctl_set; + platform_class->sysctl_set_async = sysctl_set_async; + platform_class->sysctl_get = sysctl_get; - platform_class->link_add = link_add; - platform_class->link_delete = link_delete; + platform_class->link_add = link_add; + platform_class->link_delete = link_delete; - platform_class->link_refresh = link_refresh; + platform_class->link_refresh = link_refresh; - platform_class->link_set_netns = link_set_netns; + platform_class->link_set_netns = link_set_netns; - platform_class->link_set_up = link_set_up; - platform_class->link_set_down = link_set_down; - platform_class->link_set_arp = link_set_arp; - platform_class->link_set_noarp = link_set_noarp; + platform_class->link_set_up = link_set_up; + platform_class->link_set_down = link_set_down; + platform_class->link_set_arp = link_set_arp; + platform_class->link_set_noarp = link_set_noarp; - platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled; - platform_class->link_set_token = link_set_token; + platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled; + platform_class->link_set_token = link_set_token; - platform_class->link_set_address = link_set_address; - platform_class->link_get_permanent_address = link_get_permanent_address; - platform_class->link_set_mtu = link_set_mtu; - platform_class->link_set_name = link_set_name; - platform_class->link_set_sriov_params_async = link_set_sriov_params_async; - platform_class->link_set_sriov_vfs = link_set_sriov_vfs; - platform_class->link_set_bridge_vlans = link_set_bridge_vlans; + platform_class->link_set_address = link_set_address; + platform_class->link_get_permanent_address = link_get_permanent_address; + platform_class->link_set_mtu = link_set_mtu; + platform_class->link_set_name = link_set_name; + platform_class->link_set_sriov_params_async = link_set_sriov_params_async; + platform_class->link_set_sriov_vfs = link_set_sriov_vfs; + platform_class->link_set_bridge_vlans = link_set_bridge_vlans; - platform_class->link_get_physical_port_id = link_get_physical_port_id; - platform_class->link_get_dev_id = link_get_dev_id; - platform_class->link_get_wake_on_lan = link_get_wake_on_lan; - platform_class->link_get_driver_info = link_get_driver_info; + platform_class->link_get_physical_port_id = link_get_physical_port_id; + platform_class->link_get_dev_id = link_get_dev_id; + platform_class->link_get_wake_on_lan = link_get_wake_on_lan; + platform_class->link_get_driver_info = link_get_driver_info; - platform_class->link_supports_carrier_detect = link_supports_carrier_detect; - platform_class->link_supports_vlans = link_supports_vlans; - platform_class->link_supports_sriov = link_supports_sriov; + platform_class->link_supports_carrier_detect = link_supports_carrier_detect; + platform_class->link_supports_vlans = link_supports_vlans; + platform_class->link_supports_sriov = link_supports_sriov; - platform_class->link_enslave = link_enslave; - platform_class->link_release = link_release; + platform_class->link_enslave = link_enslave; + platform_class->link_release = link_release; - platform_class->link_can_assume = link_can_assume; + platform_class->link_can_assume = link_can_assume; - platform_class->link_vlan_change = link_vlan_change; - platform_class->link_wireguard_change = link_wireguard_change; + platform_class->link_vlan_change = link_vlan_change; + platform_class->link_wireguard_change = link_wireguard_change; - platform_class->infiniband_partition_add = infiniband_partition_add; - platform_class->infiniband_partition_delete = infiniband_partition_delete; + platform_class->infiniband_partition_add = infiniband_partition_add; + platform_class->infiniband_partition_delete = infiniband_partition_delete; - platform_class->wifi_get_capabilities = wifi_get_capabilities; - platform_class->wifi_get_bssid = wifi_get_bssid; - platform_class->wifi_get_frequency = wifi_get_frequency; - platform_class->wifi_get_quality = wifi_get_quality; - platform_class->wifi_get_rate = wifi_get_rate; - platform_class->wifi_get_mode = wifi_get_mode; - platform_class->wifi_set_mode = wifi_set_mode; - platform_class->wifi_set_powersave = wifi_set_powersave; - platform_class->wifi_find_frequency = wifi_find_frequency; - platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; - platform_class->wifi_get_wake_on_wlan = wifi_get_wake_on_wlan; - platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan; + platform_class->wifi_get_capabilities = wifi_get_capabilities; + platform_class->wifi_get_bssid = wifi_get_bssid; + platform_class->wifi_get_frequency = wifi_get_frequency; + platform_class->wifi_get_quality = wifi_get_quality; + platform_class->wifi_get_rate = wifi_get_rate; + platform_class->wifi_get_mode = wifi_get_mode; + platform_class->wifi_set_mode = wifi_set_mode; + platform_class->wifi_set_powersave = wifi_set_powersave; + platform_class->wifi_find_frequency = wifi_find_frequency; + platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; + platform_class->wifi_get_wake_on_wlan = wifi_get_wake_on_wlan; + platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan; - platform_class->mesh_get_channel = mesh_get_channel; - platform_class->mesh_set_channel = mesh_set_channel; - platform_class->mesh_set_ssid = mesh_set_ssid; + platform_class->mesh_get_channel = mesh_get_channel; + platform_class->mesh_set_channel = mesh_set_channel; + platform_class->mesh_set_ssid = mesh_set_ssid; - platform_class->wpan_get_pan_id = wpan_get_pan_id; - platform_class->wpan_set_pan_id = wpan_set_pan_id; - platform_class->wpan_get_short_addr = wpan_get_short_addr; - platform_class->wpan_set_short_addr = wpan_set_short_addr; - platform_class->wpan_set_channel = wpan_set_channel; + platform_class->wpan_get_pan_id = wpan_get_pan_id; + platform_class->wpan_set_pan_id = wpan_set_pan_id; + platform_class->wpan_get_short_addr = wpan_get_short_addr; + platform_class->wpan_set_short_addr = wpan_set_short_addr; + platform_class->wpan_set_channel = wpan_set_channel; - platform_class->link_tun_add = link_tun_add; + platform_class->link_tun_add = link_tun_add; - platform_class->object_delete = object_delete; - platform_class->ip4_address_add = ip4_address_add; - platform_class->ip6_address_add = ip6_address_add; - platform_class->ip4_address_delete = ip4_address_delete; - platform_class->ip6_address_delete = ip6_address_delete; + platform_class->object_delete = object_delete; + platform_class->ip4_address_add = ip4_address_add; + platform_class->ip6_address_add = ip6_address_add; + platform_class->ip4_address_delete = ip4_address_delete; + platform_class->ip6_address_delete = ip6_address_delete; - platform_class->ip_route_add = ip_route_add; - platform_class->ip_route_get = ip_route_get; + platform_class->ip_route_add = ip_route_add; + platform_class->ip_route_get = ip_route_get; - platform_class->routing_rule_add = routing_rule_add; + platform_class->routing_rule_add = routing_rule_add; - platform_class->qdisc_add = qdisc_add; - platform_class->tfilter_add = tfilter_add; + platform_class->qdisc_add = qdisc_add; + platform_class->tfilter_add = tfilter_add; - platform_class->process_events = process_events; + platform_class->process_events = process_events; } - diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h index 90b9a17a..98935b98 100644 --- a/src/platform/nm-linux-platform.h +++ b/src/platform/nm-linux-platform.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2012 Red Hat, Inc. */ @@ -8,20 +8,23 @@ #include "nm-platform.h" -#define NM_TYPE_LINUX_PLATFORM (nm_linux_platform_get_type ()) -#define NM_LINUX_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatform)) -#define NM_LINUX_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) -#define NM_IS_LINUX_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_LINUX_PLATFORM)) -#define NM_IS_LINUX_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_LINUX_PLATFORM)) -#define NM_LINUX_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) - -typedef struct _NMLinuxPlatform NMLinuxPlatform; +#define NM_TYPE_LINUX_PLATFORM (nm_linux_platform_get_type()) +#define NM_LINUX_PLATFORM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatform)) +#define NM_LINUX_PLATFORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) +#define NM_IS_LINUX_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_LINUX_PLATFORM)) +#define NM_IS_LINUX_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_LINUX_PLATFORM)) +#define NM_LINUX_PLATFORM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformClass)) + +typedef struct _NMLinuxPlatform NMLinuxPlatform; typedef struct _NMLinuxPlatformClass NMLinuxPlatformClass; -GType nm_linux_platform_get_type (void); +GType nm_linux_platform_get_type(void); -NMPlatform *nm_linux_platform_new (gboolean log_with_ptr, gboolean netns_support); +NMPlatform *nm_linux_platform_new(gboolean log_with_ptr, gboolean netns_support); -void nm_linux_platform_setup (void); +void nm_linux_platform_setup(void); #endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */ diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c index d133d351..965a73bc 100644 --- a/src/platform/nm-netlink.c +++ b/src/platform/nm-netlink.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2018 Red Hat, Inc. */ @@ -13,256 +13,306 @@ /*****************************************************************************/ #ifndef SOL_NETLINK -#define SOL_NETLINK 270 + #define SOL_NETLINK 270 #endif /*****************************************************************************/ -#define NL_SOCK_PASSCRED (1<<1) -#define NL_MSG_PEEK (1<<3) -#define NL_MSG_PEEK_EXPLICIT (1<<4) -#define NL_NO_AUTO_ACK (1<<5) +#define NL_SOCK_PASSCRED (1 << 1) +#define NL_MSG_PEEK (1 << 3) +#define NL_MSG_PEEK_EXPLICIT (1 << 4) +#define NL_NO_AUTO_ACK (1 << 5) #ifndef NETLINK_EXT_ACK -#define NETLINK_EXT_ACK 11 + #define NETLINK_EXT_ACK 11 #endif struct nl_msg { - int nm_protocol; - struct sockaddr_nl nm_src; - struct sockaddr_nl nm_dst; - struct ucred nm_creds; - struct nlmsghdr * nm_nlh; - size_t nm_size; - bool nm_creds_has:1; + int nm_protocol; + struct sockaddr_nl nm_src; + struct sockaddr_nl nm_dst; + struct ucred nm_creds; + struct nlmsghdr * nm_nlh; + size_t nm_size; + bool nm_creds_has : 1; }; struct nl_sock { - struct sockaddr_nl s_local; - struct sockaddr_nl s_peer; - int s_fd; - int s_proto; - unsigned int s_seq_next; - unsigned int s_seq_expect; - int s_flags; - size_t s_bufsize; + struct sockaddr_nl s_local; + struct sockaddr_nl s_peer; + int s_fd; + int s_proto; + unsigned int s_seq_next; + unsigned int s_seq_expect; + int s_flags; + size_t s_bufsize; }; /*****************************************************************************/ -NM_UTILS_ENUM2STR_DEFINE (nl_nlmsgtype2str, int, - NM_UTILS_ENUM2STR (NLMSG_NOOP, "NOOP"), - NM_UTILS_ENUM2STR (NLMSG_ERROR, "ERROR"), - NM_UTILS_ENUM2STR (NLMSG_DONE, "DONE"), - NM_UTILS_ENUM2STR (NLMSG_OVERRUN, "OVERRUN"), -); - -NM_UTILS_FLAGS2STR_DEFINE (nl_nlmsg_flags2str, int, - NM_UTILS_FLAGS2STR (NLM_F_REQUEST, "REQUEST"), - NM_UTILS_FLAGS2STR (NLM_F_MULTI, "MULTI"), - NM_UTILS_FLAGS2STR (NLM_F_ACK, "ACK"), - NM_UTILS_FLAGS2STR (NLM_F_ECHO, "ECHO"), - NM_UTILS_FLAGS2STR (NLM_F_ROOT, "ROOT"), - NM_UTILS_FLAGS2STR (NLM_F_MATCH, "MATCH"), - NM_UTILS_FLAGS2STR (NLM_F_ATOMIC, "ATOMIC"), - NM_UTILS_FLAGS2STR (NLM_F_REPLACE, "REPLACE"), - NM_UTILS_FLAGS2STR (NLM_F_EXCL, "EXCL"), - NM_UTILS_FLAGS2STR (NLM_F_CREATE, "CREATE"), - NM_UTILS_FLAGS2STR (NLM_F_APPEND, "APPEND"), -); +NM_UTILS_ENUM2STR_DEFINE(nl_nlmsgtype2str, + int, + NM_UTILS_ENUM2STR(NLMSG_NOOP, "NOOP"), + NM_UTILS_ENUM2STR(NLMSG_ERROR, "ERROR"), + NM_UTILS_ENUM2STR(NLMSG_DONE, "DONE"), + NM_UTILS_ENUM2STR(NLMSG_OVERRUN, "OVERRUN"), ); + +NM_UTILS_FLAGS2STR_DEFINE(nl_nlmsg_flags2str, + int, + NM_UTILS_FLAGS2STR(NLM_F_REQUEST, "REQUEST"), + NM_UTILS_FLAGS2STR(NLM_F_MULTI, "MULTI"), + NM_UTILS_FLAGS2STR(NLM_F_ACK, "ACK"), + NM_UTILS_FLAGS2STR(NLM_F_ECHO, "ECHO"), + NM_UTILS_FLAGS2STR(NLM_F_ROOT, "ROOT"), + NM_UTILS_FLAGS2STR(NLM_F_MATCH, "MATCH"), + NM_UTILS_FLAGS2STR(NLM_F_ATOMIC, "ATOMIC"), + NM_UTILS_FLAGS2STR(NLM_F_REPLACE, "REPLACE"), + NM_UTILS_FLAGS2STR(NLM_F_EXCL, "EXCL"), + NM_UTILS_FLAGS2STR(NLM_F_CREATE, "CREATE"), + NM_UTILS_FLAGS2STR(NLM_F_APPEND, "APPEND"), ); /*****************************************************************************/ const char * -nl_nlmsghdr_to_str (const struct nlmsghdr *hdr, char *buf, gsize len) +nl_nlmsghdr_to_str(const struct nlmsghdr *hdr, char *buf, gsize len) { - const char *b; - const char *s; - guint flags, flags_before; - const char *prefix; - - if (!nm_utils_to_string_buffer_init_null (hdr, &buf, &len)) - return buf; - - b = buf; - - switch (hdr->nlmsg_type) { - case RTM_GETLINK: s = "RTM_GETLINK"; break; - case RTM_NEWLINK: s = "RTM_NEWLINK"; break; - case RTM_DELLINK: s = "RTM_DELLINK"; break; - case RTM_SETLINK: s = "RTM_SETLINK"; break; - case RTM_GETADDR: s = "RTM_GETADDR"; break; - case RTM_NEWADDR: s = "RTM_NEWADDR"; break; - case RTM_DELADDR: s = "RTM_DELADDR"; break; - case RTM_GETROUTE: s = "RTM_GETROUTE"; break; - case RTM_NEWROUTE: s = "RTM_NEWROUTE"; break; - case RTM_DELROUTE: s = "RTM_DELROUTE"; break; - case RTM_GETRULE: s = "RTM_GETRULE"; break; - case RTM_NEWRULE: s = "RTM_NEWRULE"; break; - case RTM_DELRULE: s = "RTM_DELRULE"; break; - case RTM_GETQDISC: s = "RTM_GETQDISC"; break; - case RTM_NEWQDISC: s = "RTM_NEWQDISC"; break; - case RTM_DELQDISC: s = "RTM_DELQDISC"; break; - case RTM_GETTFILTER: s = "RTM_GETTFILTER"; break; - case RTM_NEWTFILTER: s = "RTM_NEWTFILTER"; break; - case RTM_DELTFILTER: s = "RTM_DELTFILTER"; break; - case NLMSG_NOOP: s = "NLMSG_NOOP"; break; - case NLMSG_ERROR: s = "NLMSG_ERROR"; break; - case NLMSG_DONE: s = "NLMSG_DONE"; break; - case NLMSG_OVERRUN: s = "NLMSG_OVERRUN"; break; - default: s = NULL; break; - } - - if (s) - nm_utils_strbuf_append_str (&buf, &len, s); - else - nm_utils_strbuf_append (&buf, &len, "(%u)", (unsigned) hdr->nlmsg_type); - - flags = hdr->nlmsg_flags; - - if (!flags) { - nm_utils_strbuf_append_str (&buf, &len, ", flags 0"); - goto flags_done; - } - -#define _F(f, n) \ - G_STMT_START { \ - if (NM_FLAGS_ALL (flags, f)) { \ - flags &= ~(f); \ - nm_utils_strbuf_append (&buf, &len, "%s%s", prefix, n); \ - if (!flags) \ - goto flags_done; \ - prefix = ","; \ - } \ - } G_STMT_END - - prefix = ", flags "; - flags_before = flags; - _F (NLM_F_REQUEST, "request"); - _F (NLM_F_MULTI, "multi"); - _F (NLM_F_ACK, "ack"); - _F (NLM_F_ECHO, "echo"); - _F (NLM_F_DUMP_INTR, "dump_intr"); - _F (0x20 /*NLM_F_DUMP_FILTERED*/, "dump_filtered"); - - if (flags_before != flags) - prefix = ";"; - - switch (hdr->nlmsg_type) { - case RTM_NEWLINK: - case RTM_NEWADDR: - case RTM_NEWROUTE: - case RTM_NEWQDISC: - case RTM_NEWTFILTER: - _F (NLM_F_REPLACE, "replace"); - _F (NLM_F_EXCL, "excl"); - _F (NLM_F_CREATE, "create"); - _F (NLM_F_APPEND, "append"); - break; - case RTM_GETLINK: - case RTM_GETADDR: - case RTM_GETROUTE: - case RTM_DELQDISC: - case RTM_DELTFILTER: - _F (NLM_F_DUMP, "dump"); - _F (NLM_F_ROOT, "root"); - _F (NLM_F_MATCH, "match"); - _F (NLM_F_ATOMIC, "atomic"); - break; - } + const char *b; + const char *s; + guint flags, flags_before; + const char *prefix; + + if (!nm_utils_to_string_buffer_init_null(hdr, &buf, &len)) + return buf; + + b = buf; + + switch (hdr->nlmsg_type) { + case RTM_GETLINK: + s = "RTM_GETLINK"; + break; + case RTM_NEWLINK: + s = "RTM_NEWLINK"; + break; + case RTM_DELLINK: + s = "RTM_DELLINK"; + break; + case RTM_SETLINK: + s = "RTM_SETLINK"; + break; + case RTM_GETADDR: + s = "RTM_GETADDR"; + break; + case RTM_NEWADDR: + s = "RTM_NEWADDR"; + break; + case RTM_DELADDR: + s = "RTM_DELADDR"; + break; + case RTM_GETROUTE: + s = "RTM_GETROUTE"; + break; + case RTM_NEWROUTE: + s = "RTM_NEWROUTE"; + break; + case RTM_DELROUTE: + s = "RTM_DELROUTE"; + break; + case RTM_GETRULE: + s = "RTM_GETRULE"; + break; + case RTM_NEWRULE: + s = "RTM_NEWRULE"; + break; + case RTM_DELRULE: + s = "RTM_DELRULE"; + break; + case RTM_GETQDISC: + s = "RTM_GETQDISC"; + break; + case RTM_NEWQDISC: + s = "RTM_NEWQDISC"; + break; + case RTM_DELQDISC: + s = "RTM_DELQDISC"; + break; + case RTM_GETTFILTER: + s = "RTM_GETTFILTER"; + break; + case RTM_NEWTFILTER: + s = "RTM_NEWTFILTER"; + break; + case RTM_DELTFILTER: + s = "RTM_DELTFILTER"; + break; + case NLMSG_NOOP: + s = "NLMSG_NOOP"; + break; + case NLMSG_ERROR: + s = "NLMSG_ERROR"; + break; + case NLMSG_DONE: + s = "NLMSG_DONE"; + break; + case NLMSG_OVERRUN: + s = "NLMSG_OVERRUN"; + break; + default: + s = NULL; + break; + } + + if (s) + nm_utils_strbuf_append_str(&buf, &len, s); + else + nm_utils_strbuf_append(&buf, &len, "(%u)", (unsigned) hdr->nlmsg_type); + + flags = hdr->nlmsg_flags; + + if (!flags) { + nm_utils_strbuf_append_str(&buf, &len, ", flags 0"); + goto flags_done; + } + +#define _F(f, n) \ + G_STMT_START \ + { \ + if (NM_FLAGS_ALL(flags, f)) { \ + flags &= ~(f); \ + nm_utils_strbuf_append(&buf, &len, "%s%s", prefix, n); \ + if (!flags) \ + goto flags_done; \ + prefix = ","; \ + } \ + } \ + G_STMT_END + + prefix = ", flags "; + flags_before = flags; + _F(NLM_F_REQUEST, "request"); + _F(NLM_F_MULTI, "multi"); + _F(NLM_F_ACK, "ack"); + _F(NLM_F_ECHO, "echo"); + _F(NLM_F_DUMP_INTR, "dump_intr"); + _F(0x20 /*NLM_F_DUMP_FILTERED*/, "dump_filtered"); + + if (flags_before != flags) + prefix = ";"; + + switch (hdr->nlmsg_type) { + case RTM_NEWLINK: + case RTM_NEWADDR: + case RTM_NEWROUTE: + case RTM_NEWQDISC: + case RTM_NEWTFILTER: + _F(NLM_F_REPLACE, "replace"); + _F(NLM_F_EXCL, "excl"); + _F(NLM_F_CREATE, "create"); + _F(NLM_F_APPEND, "append"); + break; + case RTM_GETLINK: + case RTM_GETADDR: + case RTM_GETROUTE: + case RTM_DELQDISC: + case RTM_DELTFILTER: + _F(NLM_F_DUMP, "dump"); + _F(NLM_F_ROOT, "root"); + _F(NLM_F_MATCH, "match"); + _F(NLM_F_ATOMIC, "atomic"); + break; + } #undef _F - if (flags_before != flags) - prefix = ";"; - nm_utils_strbuf_append (&buf, &len, "%s0x%04x", prefix, flags); + if (flags_before != flags) + prefix = ";"; + nm_utils_strbuf_append(&buf, &len, "%s0x%04x", prefix, flags); flags_done: - nm_utils_strbuf_append (&buf, &len, ", seq %u", (unsigned) hdr->nlmsg_seq); + nm_utils_strbuf_append(&buf, &len, ", seq %u", (unsigned) hdr->nlmsg_seq); - return b; + return b; } /*****************************************************************************/ struct nlmsghdr * -nlmsg_hdr (struct nl_msg *n) +nlmsg_hdr(struct nl_msg *n) { - return n->nm_nlh; + return n->nm_nlh; } void * -nlmsg_reserve (struct nl_msg *n, size_t len, int pad) +nlmsg_reserve(struct nl_msg *n, size_t len, int pad) { - char *buf = (char *) n->nm_nlh; - size_t nlmsg_len = n->nm_nlh->nlmsg_len; - size_t tlen; + char * buf = (char *) n->nm_nlh; + size_t nlmsg_len = n->nm_nlh->nlmsg_len; + size_t tlen; - nm_assert (pad >= 0); + nm_assert(pad >= 0); - if (len > n->nm_size) - return NULL; + if (len > n->nm_size) + return NULL; - tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len; + tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len; - if ((tlen + nlmsg_len) > n->nm_size) - return NULL; + if ((tlen + nlmsg_len) > n->nm_size) + return NULL; - buf += nlmsg_len; - n->nm_nlh->nlmsg_len += tlen; + buf += nlmsg_len; + n->nm_nlh->nlmsg_len += tlen; - if (tlen > len) - memset (buf + len, 0, tlen - len); + if (tlen > len) + memset(buf + len, 0, tlen - len); - return buf; + return buf; } /*****************************************************************************/ struct nlattr * -nla_reserve (struct nl_msg *msg, int attrtype, int attrlen) +nla_reserve(struct nl_msg *msg, int attrtype, int attrlen) { - struct nlattr *nla; - int tlen; + struct nlattr *nla; + int tlen; - if (attrlen < 0) - return NULL; + if (attrlen < 0) + return NULL; - tlen = NLMSG_ALIGN (msg->nm_nlh->nlmsg_len) + nla_total_size (attrlen); + tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen); - if (tlen > msg->nm_size) - return NULL; + if (tlen > msg->nm_size) + return NULL; - nla = (struct nlattr *) nlmsg_tail (msg->nm_nlh); - nla->nla_type = attrtype; - nla->nla_len = nla_attr_size (attrlen); + nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh); + nla->nla_type = attrtype; + nla->nla_len = nla_attr_size(attrlen); - if (attrlen) - memset ((unsigned char *) nla + nla->nla_len, 0, nla_padlen (attrlen)); - msg->nm_nlh->nlmsg_len = tlen; + if (attrlen) + memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); + msg->nm_nlh->nlmsg_len = tlen; - return nla; + return nla; } /*****************************************************************************/ struct nl_msg * -nlmsg_alloc_size (size_t len) +nlmsg_alloc_size(size_t len) { - struct nl_msg *nm; - - if (len < sizeof (struct nlmsghdr)) - len = sizeof (struct nlmsghdr); - - nm = g_slice_new (struct nl_msg); - *nm = (struct nl_msg) { - .nm_protocol = -1, - .nm_size = len, - .nm_nlh = g_malloc0 (len), - }; - nm->nm_nlh->nlmsg_len = nlmsg_total_size (0); - return nm; + struct nl_msg *nm; + + if (len < sizeof(struct nlmsghdr)) + len = sizeof(struct nlmsghdr); + + nm = g_slice_new(struct nl_msg); + *nm = (struct nl_msg){ + .nm_protocol = -1, + .nm_size = len, + .nm_nlh = g_malloc0(len), + }; + nm->nm_nlh->nlmsg_len = nlmsg_total_size(0); + return nm; } /** @@ -275,1201 +325,1194 @@ nlmsg_alloc_size (size_t len) * @return Newly allocated netlink message or NULL. */ struct nl_msg * -nlmsg_alloc (void) +nlmsg_alloc(void) { - return nlmsg_alloc_size (nm_utils_getpagesize ()); + return nlmsg_alloc_size(nm_utils_getpagesize()); } struct nl_msg * -nlmsg_alloc_convert (struct nlmsghdr *hdr) +nlmsg_alloc_convert(struct nlmsghdr *hdr) { - struct nl_msg *nm; + struct nl_msg *nm; - nm = nlmsg_alloc_size (NLMSG_ALIGN (hdr->nlmsg_len)); - memcpy (nm->nm_nlh, hdr, hdr->nlmsg_len); - return nm; + nm = nlmsg_alloc_size(NLMSG_ALIGN(hdr->nlmsg_len)); + memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len); + return nm; } struct nl_msg * -nlmsg_alloc_simple (int nlmsgtype, int flags) +nlmsg_alloc_simple(int nlmsgtype, int flags) { - struct nl_msg *nm; - struct nlmsghdr *new; - - nm = nlmsg_alloc (); - new = nm->nm_nlh; - new->nlmsg_type = nlmsgtype; - new->nlmsg_flags = flags; - return nm; + struct nl_msg *nm; + struct nlmsghdr *new; + + nm = nlmsg_alloc(); + new = nm->nm_nlh; + new->nlmsg_type = nlmsgtype; + new->nlmsg_flags = flags; + return nm; } -void nlmsg_free (struct nl_msg *msg) +void +nlmsg_free(struct nl_msg *msg) { - if (!msg) - return; + if (!msg) + return; - g_free (msg->nm_nlh); - g_slice_free (struct nl_msg, msg); + g_free(msg->nm_nlh); + g_slice_free(struct nl_msg, msg); } /*****************************************************************************/ int -nlmsg_append (struct nl_msg *n, - const void *data, - size_t len, - int pad) +nlmsg_append(struct nl_msg *n, const void *data, size_t len, int pad) { - void *tmp; + void *tmp; - nm_assert (n); - nm_assert (data); - nm_assert (len > 0); - nm_assert (pad >= 0); + nm_assert(n); + nm_assert(data); + nm_assert(len > 0); + nm_assert(pad >= 0); - tmp = nlmsg_reserve (n, len, pad); - if (tmp == NULL) - return -ENOMEM; + tmp = nlmsg_reserve(n, len, pad); + if (tmp == NULL) + return -ENOMEM; - memcpy (tmp, data, len); - return 0; + memcpy(tmp, data, len); + return 0; } /*****************************************************************************/ int -nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], - int maxtype, const struct nla_policy *policy) +nlmsg_parse(struct nlmsghdr * nlh, + int hdrlen, + struct nlattr * tb[], + int maxtype, + const struct nla_policy *policy) { - if (!nlmsg_valid_hdr (nlh, hdrlen)) - return -NME_NL_MSG_TOOSHORT; + if (!nlmsg_valid_hdr(nlh, hdrlen)) + return -NME_NL_MSG_TOOSHORT; - return nla_parse (tb, maxtype, nlmsg_attrdata (nlh, hdrlen), - nlmsg_attrlen (nlh, hdrlen), policy); + return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), policy); } struct nlmsghdr * -nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq, - int type, int payload, int flags) +nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags) { - struct nlmsghdr *nlh; + struct nlmsghdr *nlh; - if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN) - g_return_val_if_reached (NULL); + if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN) + g_return_val_if_reached(NULL); - nlh = (struct nlmsghdr *) n->nm_nlh; - nlh->nlmsg_type = type; - nlh->nlmsg_flags = flags; - nlh->nlmsg_pid = pid; - nlh->nlmsg_seq = seq; + nlh = (struct nlmsghdr *) n->nm_nlh; + nlh->nlmsg_type = type; + nlh->nlmsg_flags = flags; + nlh->nlmsg_pid = pid; + nlh->nlmsg_seq = seq; - if ( payload > 0 - && nlmsg_reserve (n, payload, NLMSG_ALIGNTO) == NULL) - return NULL; + if (payload > 0 && nlmsg_reserve(n, payload, NLMSG_ALIGNTO) == NULL) + return NULL; - return nlh; + return nlh; } size_t -nla_strlcpy (char *dst, - const struct nlattr *nla, - size_t dstsize) +nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) { - const char *src; - size_t srclen; - size_t len; - - /* - Always writes @dstsize bytes to @dst - * - Copies the first non-NUL characters to @dst. - * Any characters after the first NUL bytes in @nla are ignored. - * - If the string @nla is longer than @dstsize, the string - * gets truncated. @dst will always be NUL terminated. */ - - if (G_UNLIKELY (dstsize <= 1)) { - if (dstsize == 1) - dst[0] = '\0'; - if ( nla - && (srclen = nla_len (nla)) > 0) - return strnlen (nla_data (nla), srclen); - return 0; - } - - nm_assert (dst); - - if (nla) { - srclen = nla_len (nla); - if (srclen > 0) { - src = nla_data (nla); - srclen = strnlen (src, srclen); - if (srclen > 0) { - len = NM_MIN (dstsize - 1, srclen); - memcpy (dst, src, len); - memset (&dst[len], 0, dstsize - len); - return srclen; - } - } - } - - memset (dst, 0, dstsize); - return 0; + const char *src; + size_t srclen; + size_t len; + + /* - Always writes @dstsize bytes to @dst + * - Copies the first non-NUL characters to @dst. + * Any characters after the first NUL bytes in @nla are ignored. + * - If the string @nla is longer than @dstsize, the string + * gets truncated. @dst will always be NUL terminated. */ + + if (G_UNLIKELY(dstsize <= 1)) { + if (dstsize == 1) + dst[0] = '\0'; + if (nla && (srclen = nla_len(nla)) > 0) + return strnlen(nla_data(nla), srclen); + return 0; + } + + nm_assert(dst); + + if (nla) { + srclen = nla_len(nla); + if (srclen > 0) { + src = nla_data(nla); + srclen = strnlen(src, srclen); + if (srclen > 0) { + len = NM_MIN(dstsize - 1, srclen); + memcpy(dst, src, len); + memset(&dst[len], 0, dstsize - len); + return srclen; + } + } + } + + memset(dst, 0, dstsize); + return 0; } size_t -nla_memcpy (void *dst, const struct nlattr *nla, size_t dstsize) +nla_memcpy(void *dst, const struct nlattr *nla, size_t dstsize) { - size_t len; - int srclen; - - if (!nla) - return 0; - - srclen = nla_len (nla); - - if (srclen <= 0) { - nm_assert (srclen == 0); - return 0; - } - - len = NM_MIN ((size_t) srclen, dstsize); - if (len > 0) { - /* there is a crucial difference between nla_strlcpy() and nla_memcpy(). - * The former always write @dstsize bytes (akin to strncpy()), here, we only - * write the bytes that we actually have (leaving the remainder undefined). */ - memcpy (dst, - nla_data (nla), - len); - } - - return srclen; + size_t len; + int srclen; + + if (!nla) + return 0; + + srclen = nla_len(nla); + + if (srclen <= 0) { + nm_assert(srclen == 0); + return 0; + } + + len = NM_MIN((size_t) srclen, dstsize); + if (len > 0) { + /* there is a crucial difference between nla_strlcpy() and nla_memcpy(). + * The former always write @dstsize bytes (akin to strncpy()), here, we only + * write the bytes that we actually have (leaving the remainder undefined). */ + memcpy(dst, nla_data(nla), len); + } + + return srclen; } int -nla_put (struct nl_msg *msg, int attrtype, int datalen, const void *data) +nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) { - struct nlattr *nla; + struct nlattr *nla; - nla = nla_reserve (msg, attrtype, datalen); - if (!nla) { - if (datalen < 0) - g_return_val_if_reached (-NME_BUG); + nla = nla_reserve(msg, attrtype, datalen); + if (!nla) { + if (datalen < 0) + g_return_val_if_reached(-NME_BUG); - return -ENOMEM; - } + return -ENOMEM; + } - if (datalen > 0) - memcpy (nla_data (nla), data, datalen); + if (datalen > 0) + memcpy(nla_data(nla), data, datalen); - return 0; + return 0; } struct nlattr * -nla_find (const struct nlattr *head, int len, int attrtype) +nla_find(const struct nlattr *head, int len, int attrtype) { - const struct nlattr *nla; - int rem; + const struct nlattr *nla; + int rem; - nla_for_each_attr (nla, head, len, rem) { - if (nla_type (nla) == attrtype) - return (struct nlattr*)nla; - } + nla_for_each_attr (nla, head, len, rem) { + if (nla_type(nla) == attrtype) + return (struct nlattr *) nla; + } - return NULL; + return NULL; } void -nla_nest_cancel (struct nl_msg *msg, const struct nlattr *attr) +nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr) { - ssize_t len; - - len = (char *) nlmsg_tail (msg->nm_nlh) - (char *) attr; - if (len < 0) - g_return_if_reached (); - else if (len > 0) { - msg->nm_nlh->nlmsg_len -= len; - memset (nlmsg_tail (msg->nm_nlh), 0, len); - } + ssize_t len; + + len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) attr; + if (len < 0) + g_return_if_reached(); + else if (len > 0) { + msg->nm_nlh->nlmsg_len -= len; + memset(nlmsg_tail(msg->nm_nlh), 0, len); + } } struct nlattr * -nla_nest_start (struct nl_msg *msg, int attrtype) +nla_nest_start(struct nl_msg *msg, int attrtype) { - struct nlattr *start = (struct nlattr *) nlmsg_tail (msg->nm_nlh); + struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh); - if (nla_put (msg, NLA_F_NESTED | attrtype, 0, NULL) < 0) - return NULL; + if (nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0) + return NULL; - return start; + return start; } static int -_nest_end (struct nl_msg *msg, struct nlattr *start, int keep_empty) +_nest_end(struct nl_msg *msg, struct nlattr *start, int keep_empty) { - size_t pad, len; - - len = (char *) nlmsg_tail (msg->nm_nlh) - (char *) start; - - if ( len > USHRT_MAX - || (!keep_empty && len == NLA_HDRLEN)) { - /* - * Max nlattr size exceeded or empty nested attribute, trim the - * attribute header again - */ - nla_nest_cancel (msg, start); - - /* Return error only if nlattr size was exceeded */ - return (len == NLA_HDRLEN) ? 0 : -NME_NL_ATTRSIZE; - } - - start->nla_len = len; - - pad = NLMSG_ALIGN (msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len; - if (pad > 0) { - /* - * Data inside attribute does not end at a alignment boundary. - * Pad accordingly and accoun for the additional space in - * the message. nlmsg_reserve() may never fail in this situation, - * the allocate message buffer must be a multiple of NLMSG_ALIGNTO. - */ - if (!nlmsg_reserve (msg, pad, 0)) - g_return_val_if_reached (-NME_BUG); - } - - return 0; + size_t pad, len; + + len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) start; + + if (len > USHRT_MAX || (!keep_empty && len == NLA_HDRLEN)) { + /* + * Max nlattr size exceeded or empty nested attribute, trim the + * attribute header again + */ + nla_nest_cancel(msg, start); + + /* Return error only if nlattr size was exceeded */ + return (len == NLA_HDRLEN) ? 0 : -NME_NL_ATTRSIZE; + } + + start->nla_len = len; + + pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len; + if (pad > 0) { + /* + * Data inside attribute does not end at a alignment boundary. + * Pad accordingly and account for the additional space in + * the message. nlmsg_reserve() may never fail in this situation, + * the allocate message buffer must be a multiple of NLMSG_ALIGNTO. + */ + if (!nlmsg_reserve(msg, pad, 0)) + g_return_val_if_reached(-NME_BUG); + } + + return 0; } int -nla_nest_end (struct nl_msg *msg, struct nlattr *start) +nla_nest_end(struct nl_msg *msg, struct nlattr *start) { - return _nest_end (msg, start, 0); + return _nest_end(msg, start, 0); } -static const uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = { - [NLA_U8] = sizeof (uint8_t), - [NLA_U16] = sizeof (uint16_t), - [NLA_U32] = sizeof (uint32_t), - [NLA_U64] = sizeof (uint64_t), - [NLA_STRING] = 1, - [NLA_FLAG] = 0, +static const uint16_t nla_attr_minlen[NLA_TYPE_MAX + 1] = { + [NLA_U8] = sizeof(uint8_t), + [NLA_U16] = sizeof(uint16_t), + [NLA_U32] = sizeof(uint32_t), + [NLA_U64] = sizeof(uint64_t), + [NLA_STRING] = 1, + [NLA_FLAG] = 0, }; static int -validate_nla (const struct nlattr *nla, int maxtype, - const struct nla_policy *policy) +validate_nla(const struct nlattr *nla, int maxtype, const struct nla_policy *policy) { - const struct nla_policy *pt; - unsigned int minlen = 0; - int type = nla_type (nla); + const struct nla_policy *pt; + unsigned int minlen = 0; + int type = nla_type(nla); - if (type < 0 || type > maxtype) - return 0; + if (type < 0 || type > maxtype) + return 0; - pt = &policy[type]; + pt = &policy[type]; - if (pt->type > NLA_TYPE_MAX) - g_return_val_if_reached (-NME_BUG); + if (pt->type > NLA_TYPE_MAX) + g_return_val_if_reached(-NME_BUG); - if (pt->minlen) - minlen = pt->minlen; - else if (pt->type != NLA_UNSPEC) - minlen = nla_attr_minlen[pt->type]; + if (pt->minlen) + minlen = pt->minlen; + else if (pt->type != NLA_UNSPEC) + minlen = nla_attr_minlen[pt->type]; - if (nla_len (nla) < minlen) - return -NME_UNSPEC; + if (nla_len(nla) < minlen) + return -NME_UNSPEC; - if (pt->maxlen && nla_len (nla) > pt->maxlen) - return -NME_UNSPEC; + if (pt->maxlen && nla_len(nla) > pt->maxlen) + return -NME_UNSPEC; - if (pt->type == NLA_STRING) { - const char *data; + if (pt->type == NLA_STRING) { + const char *data; - nm_assert (minlen > 0); + nm_assert(minlen > 0); - data = nla_data (nla); - if (data[nla_len (nla) - 1] != '\0') - return -NME_UNSPEC; - } + data = nla_data(nla); + if (data[nla_len(nla) - 1] != '\0') + return -NME_UNSPEC; + } - return 0; + return 0; } int -nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len, - const struct nla_policy *policy) +nla_parse(struct nlattr * tb[], + int maxtype, + struct nlattr * head, + int len, + const struct nla_policy *policy) { - struct nlattr *nla; - int rem, nmerr; + struct nlattr *nla; + int rem, nmerr; - memset (tb, 0, sizeof (struct nlattr *) * (maxtype + 1)); + memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); - nla_for_each_attr (nla, head, len, rem) { - int type = nla_type (nla); + nla_for_each_attr (nla, head, len, rem) { + int type = nla_type(nla); - if (type > maxtype) - continue; + if (type > maxtype) + continue; - if (policy) { - nmerr = validate_nla (nla, maxtype, policy); - if (nmerr < 0) - return nmerr; - } + if (policy) { + nmerr = validate_nla(nla, maxtype, policy); + if (nmerr < 0) + return nmerr; + } - tb[type] = nla; - } + tb[type] = nla; + } - return 0; + return 0; } /*****************************************************************************/ int -nlmsg_get_proto (struct nl_msg *msg) +nlmsg_get_proto(struct nl_msg *msg) { - return msg->nm_protocol; + return msg->nm_protocol; } void -nlmsg_set_proto (struct nl_msg *msg, int protocol) +nlmsg_set_proto(struct nl_msg *msg, int protocol) { - msg->nm_protocol = protocol; + msg->nm_protocol = protocol; } void -nlmsg_set_src (struct nl_msg *msg, struct sockaddr_nl *addr) +nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr) { - memcpy (&msg->nm_src, addr, sizeof (*addr)); + memcpy(&msg->nm_src, addr, sizeof(*addr)); } struct ucred * -nlmsg_get_creds (struct nl_msg *msg) +nlmsg_get_creds(struct nl_msg *msg) { - if (msg->nm_creds_has) - return &msg->nm_creds; - return NULL; + if (msg->nm_creds_has) + return &msg->nm_creds; + return NULL; } void -nlmsg_set_creds (struct nl_msg *msg, struct ucred *creds) +nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds) { - if (creds) { - memcpy (&msg->nm_creds, creds, sizeof (*creds)); - msg->nm_creds_has = TRUE; - } else - msg->nm_creds_has = FALSE; + if (creds) { + memcpy(&msg->nm_creds, creds, sizeof(*creds)); + msg->nm_creds_has = TRUE; + } else + msg->nm_creds_has = FALSE; } /*****************************************************************************/ void * -genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family, - int hdrlen, int flags, uint8_t cmd, uint8_t version) +genlmsg_put(struct nl_msg *msg, + uint32_t port, + uint32_t seq, + int family, + int hdrlen, + int flags, + uint8_t cmd, + uint8_t version) { - struct nlmsghdr *nlh; - struct genlmsghdr hdr = { - .cmd = cmd, - .version = version, - }; + struct nlmsghdr * nlh; + struct genlmsghdr hdr = { + .cmd = cmd, + .version = version, + }; - nlh = nlmsg_put (msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); - if (nlh == NULL) - return NULL; + nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); + if (nlh == NULL) + return NULL; - memcpy (nlmsg_data (nlh), &hdr, sizeof (hdr)); + memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr)); - return (char *) nlmsg_data (nlh) + GENL_HDRLEN; + return (char *) nlmsg_data(nlh) + GENL_HDRLEN; } void * -genlmsg_data (const struct genlmsghdr *gnlh) +genlmsg_data(const struct genlmsghdr *gnlh) { - return ((unsigned char *) gnlh + GENL_HDRLEN); + return ((unsigned char *) gnlh + GENL_HDRLEN); } void * -genlmsg_user_hdr (const struct genlmsghdr *gnlh) +genlmsg_user_hdr(const struct genlmsghdr *gnlh) { - return genlmsg_data (gnlh); + return genlmsg_data(gnlh); } struct genlmsghdr * -genlmsg_hdr (struct nlmsghdr *nlh) +genlmsg_hdr(struct nlmsghdr *nlh) { - return nlmsg_data (nlh); + return nlmsg_data(nlh); } void * -genlmsg_user_data (const struct genlmsghdr *gnlh, const int hdrlen) +genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen) { - return (char *) genlmsg_user_hdr (gnlh) + NLMSG_ALIGN (hdrlen); + return (char *) genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); } struct nlattr * -genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen) +genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) { - return genlmsg_user_data (gnlh, hdrlen); + return genlmsg_user_data(gnlh, hdrlen); } int -genlmsg_len (const struct genlmsghdr *gnlh) +genlmsg_len(const struct genlmsghdr *gnlh) { - const struct nlmsghdr *nlh; + const struct nlmsghdr *nlh; - nlh = (const struct nlmsghdr *) ((const unsigned char *) gnlh - NLMSG_HDRLEN); - return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); + nlh = (const struct nlmsghdr *) ((const unsigned char *) gnlh - NLMSG_HDRLEN); + return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); } int -genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen) +genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) { - return genlmsg_len (gnlh) - NLMSG_ALIGN (hdrlen); + return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); } int -genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen) +genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) { - struct genlmsghdr *ghdr; + struct genlmsghdr *ghdr; - if (!nlmsg_valid_hdr (nlh, GENL_HDRLEN)) - return 0; + if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN)) + return 0; - ghdr = nlmsg_data (nlh); - if (genlmsg_len (ghdr) < NLMSG_ALIGN (hdrlen)) - return 0; + ghdr = nlmsg_data(nlh); + if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen)) + return 0; - return 1; + return 1; } int -genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], - int maxtype, const struct nla_policy *policy) +genlmsg_parse(struct nlmsghdr * nlh, + int hdrlen, + struct nlattr * tb[], + int maxtype, + const struct nla_policy *policy) { - struct genlmsghdr *ghdr; + struct genlmsghdr *ghdr; - if (!genlmsg_valid_hdr (nlh, hdrlen)) - return -NME_NL_MSG_TOOSHORT; + if (!genlmsg_valid_hdr(nlh, hdrlen)) + return -NME_NL_MSG_TOOSHORT; - ghdr = nlmsg_data (nlh); - return nla_parse (tb, maxtype, genlmsg_attrdata (ghdr, hdrlen), - genlmsg_attrlen (ghdr, hdrlen), policy); + ghdr = nlmsg_data(nlh); + return nla_parse(tb, + maxtype, + genlmsg_attrdata(ghdr, hdrlen), + genlmsg_attrlen(ghdr, hdrlen), + policy); } static int -_genl_parse_getfamily (struct nl_msg *msg, void *arg) +_genl_parse_getfamily(struct nl_msg *msg, void *arg) { - static const struct nla_policy ctrl_policy[] = { - [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, - [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING, - .maxlen = GENL_NAMSIZ }, - [CTRL_ATTR_VERSION] = { .type = NLA_U32 }, - [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 }, - [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, - [CTRL_ATTR_OPS] = { .type = NLA_NESTED }, - [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED }, - }; - struct nlattr *tb[G_N_ELEMENTS (ctrl_policy)]; - struct nlmsghdr *nlh = nlmsg_hdr (msg); - gint32 *response_data = arg; - - if (genlmsg_parse_arr (nlh, 0, tb, ctrl_policy) < 0) - return NL_SKIP; - - if (tb[CTRL_ATTR_FAMILY_ID]) - *response_data = nla_get_u16 (tb[CTRL_ATTR_FAMILY_ID]); - - return NL_STOP; + static const struct nla_policy ctrl_policy[] = { + [CTRL_ATTR_FAMILY_ID] = {.type = NLA_U16}, + [CTRL_ATTR_FAMILY_NAME] = {.type = NLA_STRING, .maxlen = GENL_NAMSIZ}, + [CTRL_ATTR_VERSION] = {.type = NLA_U32}, + [CTRL_ATTR_HDRSIZE] = {.type = NLA_U32}, + [CTRL_ATTR_MAXATTR] = {.type = NLA_U32}, + [CTRL_ATTR_OPS] = {.type = NLA_NESTED}, + [CTRL_ATTR_MCAST_GROUPS] = {.type = NLA_NESTED}, + }; + struct nlattr * tb[G_N_ELEMENTS(ctrl_policy)]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + gint32 * response_data = arg; + + if (genlmsg_parse_arr(nlh, 0, tb, ctrl_policy) < 0) + return NL_SKIP; + + if (tb[CTRL_ATTR_FAMILY_ID]) + *response_data = nla_get_u16(tb[CTRL_ATTR_FAMILY_ID]); + + return NL_STOP; } int -genl_ctrl_resolve (struct nl_sock *sk, const char *name) +genl_ctrl_resolve(struct nl_sock *sk, const char *name) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - int nmerr; - gint32 response_data = -1; - const struct nl_cb cb = { - .valid_cb = _genl_parse_getfamily, - .valid_arg = &response_data, - }; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int nmerr; + gint32 response_data = -1; + const struct nl_cb cb = { + .valid_cb = _genl_parse_getfamily, + .valid_arg = &response_data, + }; - msg = nlmsg_alloc (); + msg = nlmsg_alloc(); - if (!genlmsg_put (msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, - 0, 0, CTRL_CMD_GETFAMILY, 1)) - return -ENOMEM; + if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1)) + return -ENOMEM; - nmerr = nla_put_string (msg, CTRL_ATTR_FAMILY_NAME, name); - if (nmerr < 0) - return nmerr; + nmerr = nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name); + if (nmerr < 0) + return nmerr; - nmerr = nl_send_auto (sk, msg); - if (nmerr < 0) - return nmerr; + nmerr = nl_send_auto(sk, msg); + if (nmerr < 0) + return nmerr; - nmerr = nl_recvmsgs (sk, &cb); - if (nmerr < 0) - return nmerr; + nmerr = nl_recvmsgs(sk, &cb); + if (nmerr < 0) + return nmerr; - /* If search was successful, request may be ACKed after data */ - nmerr = nl_wait_for_ack (sk, NULL); - if (nmerr < 0) - return nmerr; + /* If search was successful, request may be ACKed after data */ + nmerr = nl_wait_for_ack(sk, NULL); + if (nmerr < 0) + return nmerr; - if (response_data < 0) - return -NME_UNSPEC; + if (response_data < 0) + return -NME_UNSPEC; - return response_data; + return response_data; } /*****************************************************************************/ struct nl_sock * -nl_socket_alloc (void) +nl_socket_alloc(void) { - struct nl_sock *sk; + struct nl_sock *sk; - sk = g_slice_new0 (struct nl_sock); + sk = g_slice_new0(struct nl_sock); - sk->s_fd = -1; - sk->s_local.nl_family = AF_NETLINK; - sk->s_peer.nl_family = AF_NETLINK; - sk->s_seq_expect = sk->s_seq_next = time (NULL); + sk->s_fd = -1; + sk->s_local.nl_family = AF_NETLINK; + sk->s_peer.nl_family = AF_NETLINK; + sk->s_seq_expect = sk->s_seq_next = time(NULL); - return sk; + return sk; } void -nl_socket_free (struct nl_sock *sk) +nl_socket_free(struct nl_sock *sk) { - if (!sk) - return; + if (!sk) + return; - if (sk->s_fd >= 0) - nm_close (sk->s_fd); - g_slice_free (struct nl_sock, sk); + if (sk->s_fd >= 0) + nm_close(sk->s_fd); + g_slice_free(struct nl_sock, sk); } int -nl_socket_get_fd (const struct nl_sock *sk) +nl_socket_get_fd(const struct nl_sock *sk) { - return sk->s_fd; + return sk->s_fd; } uint32_t -nl_socket_get_local_port (const struct nl_sock *sk) +nl_socket_get_local_port(const struct nl_sock *sk) { - return sk->s_local.nl_pid; + return sk->s_local.nl_pid; } size_t -nl_socket_get_msg_buf_size (struct nl_sock *sk) +nl_socket_get_msg_buf_size(struct nl_sock *sk) { - return sk->s_bufsize; + return sk->s_bufsize; } int -nl_socket_set_passcred (struct nl_sock *sk, int state) +nl_socket_set_passcred(struct nl_sock *sk, int state) { - int err; + int err; - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; + if (sk->s_fd == -1) + return -NME_NL_BAD_SOCK; - err = setsockopt (sk->s_fd, SOL_SOCKET, SO_PASSCRED, - &state, sizeof (state)); - if (err < 0) - return -nm_errno_from_native (errno); + err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED, &state, sizeof(state)); + if (err < 0) + return -nm_errno_from_native(errno); - if (state) - sk->s_flags |= NL_SOCK_PASSCRED; - else - sk->s_flags &= ~NL_SOCK_PASSCRED; + if (state) + sk->s_flags |= NL_SOCK_PASSCRED; + else + sk->s_flags &= ~NL_SOCK_PASSCRED; - return 0; + return 0; } int -nl_socket_set_msg_buf_size (struct nl_sock *sk, size_t bufsize) +nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize) { - sk->s_bufsize = bufsize; + sk->s_bufsize = bufsize; - return 0; + return 0; } struct sockaddr_nl * -nlmsg_get_dst (struct nl_msg *msg) +nlmsg_get_dst(struct nl_msg *msg) { - return &msg->nm_dst; + return &msg->nm_dst; } int -nl_socket_set_nonblocking (const struct nl_sock *sk) +nl_socket_set_nonblocking(const struct nl_sock *sk) { - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; + if (sk->s_fd == -1) + return -NME_NL_BAD_SOCK; - if (fcntl (sk->s_fd, F_SETFL, O_NONBLOCK) < 0) - return -nm_errno_from_native (errno); + if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0) + return -nm_errno_from_native(errno); - return 0; + return 0; } int -nl_socket_set_buffer_size (struct nl_sock *sk, int rxbuf, int txbuf) +nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) { - int err; + int err; - if (rxbuf <= 0) - rxbuf = 32768; + if (rxbuf <= 0) + rxbuf = 32768; - if (txbuf <= 0) - txbuf = 32768; + if (txbuf <= 0) + txbuf = 32768; - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; + if (sk->s_fd == -1) + return -NME_NL_BAD_SOCK; - err = setsockopt (sk->s_fd, SOL_SOCKET, SO_SNDBUF, - &txbuf, sizeof (txbuf)); - if (err < 0) { - return -nm_errno_from_native (errno); - } + err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF, &txbuf, sizeof(txbuf)); + if (err < 0) { + return -nm_errno_from_native(errno); + } - err = setsockopt (sk->s_fd, SOL_SOCKET, SO_RCVBUF, - &rxbuf, sizeof (rxbuf)); - if (err < 0) { - return -nm_errno_from_native (errno); - } + err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF, &rxbuf, sizeof(rxbuf)); + if (err < 0) { + return -nm_errno_from_native(errno); + } - return 0; + return 0; } int -nl_socket_add_memberships (struct nl_sock *sk, int group, ...) +nl_socket_add_memberships(struct nl_sock *sk, int group, ...) { - int err; - va_list ap; + int err; + va_list ap; - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; + if (sk->s_fd == -1) + return -NME_NL_BAD_SOCK; - va_start (ap, group); + va_start(ap, group); - while (group != 0) { - if (group < 0) { - va_end (ap); - g_return_val_if_reached (-NME_BUG); - } + while (group != 0) { + if (group < 0) { + va_end(ap); + g_return_val_if_reached(-NME_BUG); + } - err = setsockopt (sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, - &group, sizeof (group)); - if (err < 0) { - int errsv = errno; + err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); + if (err < 0) { + int errsv = errno; - va_end (ap); - return -nm_errno_from_native (errsv); - } + va_end(ap); + return -nm_errno_from_native(errsv); + } - group = va_arg (ap, int); - } + group = va_arg(ap, int); + } - va_end (ap); + va_end(ap); - return 0; + return 0; } int -nl_socket_set_ext_ack (struct nl_sock *sk, gboolean enable) +nl_socket_set_ext_ack(struct nl_sock *sk, gboolean enable) { - int err, val; + int err, val; - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; + if (sk->s_fd == -1) + return -NME_NL_BAD_SOCK; - val = !!enable; - err = setsockopt (sk->s_fd, SOL_NETLINK, NETLINK_EXT_ACK, &val, sizeof (val)); - if (err < 0) - return -nm_errno_from_native (errno); + val = !!enable; + err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_EXT_ACK, &val, sizeof(val)); + if (err < 0) + return -nm_errno_from_native(errno); - return 0; + return 0; } -void nl_socket_disable_msg_peek (struct nl_sock *sk) +void +nl_socket_disable_msg_peek(struct nl_sock *sk) { - sk->s_flags |= NL_MSG_PEEK_EXPLICIT; - sk->s_flags &= ~NL_MSG_PEEK; + sk->s_flags |= NL_MSG_PEEK_EXPLICIT; + sk->s_flags &= ~NL_MSG_PEEK; } int -nl_connect (struct nl_sock *sk, int protocol) +nl_connect(struct nl_sock *sk, int protocol) { - int err, nmerr; - socklen_t addrlen; - struct sockaddr_nl local = { 0 }; - - if (sk->s_fd != -1) - return -NME_NL_BAD_SOCK; - - sk->s_fd = socket (AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol); - if (sk->s_fd < 0) { - nmerr = -nm_errno_from_native (errno); - goto errout; - } - - nmerr = nl_socket_set_buffer_size (sk, 0, 0); - if (nmerr < 0) - goto errout; - - nm_assert (sk->s_local.nl_pid == 0); - - err = bind (sk->s_fd, (struct sockaddr*) &sk->s_local, - sizeof (sk->s_local)); - if (err != 0) { - nmerr = -nm_errno_from_native (errno); - goto errout; - } - - addrlen = sizeof (local); - err = getsockname (sk->s_fd, (struct sockaddr *) &local, - &addrlen); - if (err < 0) { - nmerr = -nm_errno_from_native (errno); - goto errout; - } - - if (addrlen != sizeof (local)) { - nmerr = -NME_UNSPEC; - goto errout; - } - - if (local.nl_family != AF_NETLINK) { - nmerr = -NME_UNSPEC; - goto errout; - } - - sk->s_local = local; - sk->s_proto = protocol; - - return 0; + int err, nmerr; + socklen_t addrlen; + struct sockaddr_nl local = {0}; + + if (sk->s_fd != -1) + return -NME_NL_BAD_SOCK; + + sk->s_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol); + if (sk->s_fd < 0) { + nmerr = -nm_errno_from_native(errno); + goto errout; + } + + nmerr = nl_socket_set_buffer_size(sk, 0, 0); + if (nmerr < 0) + goto errout; + + nm_assert(sk->s_local.nl_pid == 0); + + err = bind(sk->s_fd, (struct sockaddr *) &sk->s_local, sizeof(sk->s_local)); + if (err != 0) { + nmerr = -nm_errno_from_native(errno); + goto errout; + } + + addrlen = sizeof(local); + err = getsockname(sk->s_fd, (struct sockaddr *) &local, &addrlen); + if (err < 0) { + nmerr = -nm_errno_from_native(errno); + goto errout; + } + + if (addrlen != sizeof(local)) { + nmerr = -NME_UNSPEC; + goto errout; + } + + if (local.nl_family != AF_NETLINK) { + nmerr = -NME_UNSPEC; + goto errout; + } + + sk->s_local = local; + sk->s_proto = protocol; + + return 0; errout: - if (sk->s_fd != -1) { - close (sk->s_fd); - sk->s_fd = -1; - } - return nmerr; + if (sk->s_fd != -1) { + close(sk->s_fd); + sk->s_fd = -1; + } + return nmerr; } /*****************************************************************************/ static void -_cb_init (struct nl_cb *dst, const struct nl_cb *src) +_cb_init(struct nl_cb *dst, const struct nl_cb *src) { - nm_assert (dst); + nm_assert(dst); - if (src) - *dst = *src; - else - memset (dst, 0, sizeof (*dst)); + if (src) + *dst = *src; + else + memset(dst, 0, sizeof(*dst)); } -static int ack_wait_handler (struct nl_msg *msg, void *arg) +static int +ack_wait_handler(struct nl_msg *msg, void *arg) { - return NL_STOP; + return NL_STOP; } int -nl_wait_for_ack (struct nl_sock *sk, - const struct nl_cb *cb) +nl_wait_for_ack(struct nl_sock *sk, const struct nl_cb *cb) { - struct nl_cb cb2; + struct nl_cb cb2; - _cb_init (&cb2, cb); - cb2.ack_cb = ack_wait_handler; - return nl_recvmsgs (sk, &cb2); + _cb_init(&cb2, cb); + cb2.ack_cb = ack_wait_handler; + return nl_recvmsgs(sk, &cb2); } -#define NL_CB_CALL(cb, type, msg) \ -do { \ - const struct nl_cb *_cb = (cb); \ - \ - if (_cb && _cb->type##_cb) { \ - /* the returned value here must be either a negative - * netlink error number, or one of NL_SKIP, NL_STOP, NL_OK. */ \ - nmerr = _cb->type##_cb ((msg), _cb->type##_arg); \ - switch (nmerr) { \ - case NL_OK: \ - nm_assert (nmerr == 0); \ - break; \ - case NL_SKIP: \ - goto skip; \ - case NL_STOP: \ - goto stop; \ - default: \ - if (nmerr >= 0) { \ - nm_assert_not_reached (); \ - nmerr = -NME_BUG; \ - } \ - goto out; \ - } \ - } \ -} while (0) +#define NL_CB_CALL(cb, type, msg) \ + do { \ + const struct nl_cb *_cb = (cb); \ + \ + if (_cb && _cb->type##_cb) { \ + /* the returned value here must be either a negative + * netlink error number, or one of NL_SKIP, NL_STOP, NL_OK. */ \ + nmerr = _cb->type##_cb((msg), _cb->type##_arg); \ + switch (nmerr) { \ + case NL_OK: \ + nm_assert(nmerr == 0); \ + break; \ + case NL_SKIP: \ + goto skip; \ + case NL_STOP: \ + goto stop; \ + default: \ + if (nmerr >= 0) { \ + nm_assert_not_reached(); \ + nmerr = -NME_BUG; \ + } \ + goto out; \ + } \ + } \ + } while (0) int -nl_recvmsgs (struct nl_sock *sk, const struct nl_cb *cb) +nl_recvmsgs(struct nl_sock *sk, const struct nl_cb *cb) { - int n, nmerr = 0, multipart = 0, interrupted = 0, nrecv = 0; - gs_free unsigned char *buf = NULL; - struct nlmsghdr *hdr; - struct sockaddr_nl nla = { 0 }; - struct ucred creds; - gboolean creds_has; + int n, nmerr = 0, multipart = 0, interrupted = 0, nrecv = 0; + gs_free unsigned char *buf = NULL; + struct nlmsghdr * hdr; + struct sockaddr_nl nla = {0}; + struct ucred creds; + gboolean creds_has; continue_reading: - n = nl_recv (sk, &nla, &buf, &creds, &creds_has); - if (n <= 0) - return n; - - hdr = (struct nlmsghdr *) buf; - while (nlmsg_ok (hdr, n)) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - - msg = nlmsg_alloc_convert (hdr); - - nlmsg_set_proto (msg, sk->s_proto); - nlmsg_set_src (msg, &nla); - nlmsg_set_creds (msg, creds_has ? &creds : NULL); - - nrecv++; - - /* Only do sequence checking if auto-ack mode is enabled */ - if (! (sk->s_flags & NL_NO_AUTO_ACK)) { - if (hdr->nlmsg_seq != sk->s_seq_expect) { - nmerr = -NME_NL_SEQ_MISMATCH; - goto out; - } - } - - if (hdr->nlmsg_type == NLMSG_DONE || - hdr->nlmsg_type == NLMSG_ERROR || - hdr->nlmsg_type == NLMSG_NOOP || - hdr->nlmsg_type == NLMSG_OVERRUN) { - /* We can't check for !NLM_F_MULTI since some netlink - * users in the kernel are broken. */ - sk->s_seq_expect++; - } - - if (hdr->nlmsg_flags & NLM_F_MULTI) - multipart = 1; - - if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { - /* - * We have to continue reading to clear - * all messages until a NLMSG_DONE is - * received and report the inconsistency. - */ - interrupted = 1; - } - - /* messages terminates a multipart message, this is - * usually the end of a message and therefore we slip - * out of the loop by default. the user may overrule - * this action by skipping this packet. */ - if (hdr->nlmsg_type == NLMSG_DONE) { - multipart = 0; - NL_CB_CALL (cb, finish, msg); - } - - /* Message to be ignored, the default action is to - * skip this message if no callback is specified. The - * user may overrule this action by returning - * NL_PROCEED. */ - else if (hdr->nlmsg_type == NLMSG_NOOP) - goto skip; - - /* Data got lost, report back to user. The default action is to - * quit parsing. The user may overrule this action by retuning - * NL_SKIP or NL_PROCEED (dangerous) */ - else if (hdr->nlmsg_type == NLMSG_OVERRUN) { - nmerr = -NME_NL_MSG_OVERFLOW; - goto out; - } - - /* Message carries a nlmsgerr */ - else if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *e = nlmsg_data (hdr); - - if (hdr->nlmsg_len < nlmsg_size (sizeof (*e))) { - /* Truncated error message, the default action - * is to stop parsing. The user may overrule - * this action by returning NL_SKIP or - * NL_PROCEED (dangerous) */ - nmerr = -NME_NL_MSG_TRUNC; - goto out; - } - if (e->error) { - /* Error message reported back from kernel. */ - if (cb && cb->err_cb) { - /* the returned value here must be either a negative - * netlink error number, or one of NL_SKIP, NL_STOP, NL_OK. */ - nmerr = cb->err_cb (&nla, e, - cb->err_arg); - if (nmerr < 0) - goto out; - else if (nmerr == NL_SKIP) - goto skip; - else if (nmerr == NL_STOP) { - nmerr = -nm_errno_from_native (e->error); - goto out; - } - nm_assert (nmerr == NL_OK); - } else { - nmerr = -nm_errno_from_native (e->error); - goto out; - } - } else - NL_CB_CALL (cb, ack, msg); - } else { - /* Valid message (not checking for MULTIPART bit to - * get along with broken kernels. NL_SKIP has no - * effect on this. */ - NL_CB_CALL (cb, valid, msg); - } + n = nl_recv(sk, &nla, &buf, &creds, &creds_has); + if (n <= 0) + return n; + + hdr = (struct nlmsghdr *) buf; + while (nlmsg_ok(hdr, n)) { + nm_auto_nlmsg struct nl_msg *msg = NULL; + + msg = nlmsg_alloc_convert(hdr); + + nlmsg_set_proto(msg, sk->s_proto); + nlmsg_set_src(msg, &nla); + nlmsg_set_creds(msg, creds_has ? &creds : NULL); + + nrecv++; + + /* Only do sequence checking if auto-ack mode is enabled */ + if (!(sk->s_flags & NL_NO_AUTO_ACK)) { + if (hdr->nlmsg_seq != sk->s_seq_expect) { + nmerr = -NME_NL_SEQ_MISMATCH; + goto out; + } + } + + if (hdr->nlmsg_type == NLMSG_DONE || hdr->nlmsg_type == NLMSG_ERROR + || hdr->nlmsg_type == NLMSG_NOOP || hdr->nlmsg_type == NLMSG_OVERRUN) { + /* We can't check for !NLM_F_MULTI since some netlink + * users in the kernel are broken. */ + sk->s_seq_expect++; + } + + if (hdr->nlmsg_flags & NLM_F_MULTI) + multipart = 1; + + if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { + /* + * We have to continue reading to clear + * all messages until a NLMSG_DONE is + * received and report the inconsistency. + */ + interrupted = 1; + } + + /* messages terminates a multipart message, this is + * usually the end of a message and therefore we slip + * out of the loop by default. the user may overrule + * this action by skipping this packet. */ + if (hdr->nlmsg_type == NLMSG_DONE) { + multipart = 0; + NL_CB_CALL(cb, finish, msg); + } + + /* Message to be ignored, the default action is to + * skip this message if no callback is specified. The + * user may overrule this action by returning + * NL_PROCEED. */ + else if (hdr->nlmsg_type == NLMSG_NOOP) + goto skip; + + /* Data got lost, report back to user. The default action is to + * quit parsing. The user may overrule this action by returning + * NL_SKIP or NL_PROCEED (dangerous) */ + else if (hdr->nlmsg_type == NLMSG_OVERRUN) { + nmerr = -NME_NL_MSG_OVERFLOW; + goto out; + } + + /* Message carries a nlmsgerr */ + else if (hdr->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *e = nlmsg_data(hdr); + + if (hdr->nlmsg_len < nlmsg_size(sizeof(*e))) { + /* Truncated error message, the default action + * is to stop parsing. The user may overrule + * this action by returning NL_SKIP or + * NL_PROCEED (dangerous) */ + nmerr = -NME_NL_MSG_TRUNC; + goto out; + } + if (e->error) { + /* Error message reported back from kernel. */ + if (cb && cb->err_cb) { + /* the returned value here must be either a negative + * netlink error number, or one of NL_SKIP, NL_STOP, NL_OK. */ + nmerr = cb->err_cb(&nla, e, cb->err_arg); + if (nmerr < 0) + goto out; + else if (nmerr == NL_SKIP) + goto skip; + else if (nmerr == NL_STOP) { + nmerr = -nm_errno_from_native(e->error); + goto out; + } + nm_assert(nmerr == NL_OK); + } else { + nmerr = -nm_errno_from_native(e->error); + goto out; + } + } else + NL_CB_CALL(cb, ack, msg); + } else { + /* Valid message (not checking for MULTIPART bit to + * get along with broken kernels. NL_SKIP has no + * effect on this. */ + NL_CB_CALL(cb, valid, msg); + } skip: - nmerr = 0; - hdr = nlmsg_next (hdr, &n); - } + nmerr = 0; + hdr = nlmsg_next(hdr, &n); + } - if (multipart) { - /* Multipart message not yet complete, continue reading */ - nm_clear_g_free (&buf); + if (multipart) { + /* Multipart message not yet complete, continue reading */ + nm_clear_g_free(&buf); - nmerr = 0; - goto continue_reading; - } + nmerr = 0; + goto continue_reading; + } stop: - nmerr = 0; + nmerr = 0; out: - if (interrupted) - nmerr = -NME_NL_DUMP_INTR; + if (interrupted) + nmerr = -NME_NL_DUMP_INTR; - nm_assert (nmerr <= 0); - return nmerr ?: nrecv; + nm_assert(nmerr <= 0); + return nmerr ?: nrecv; } int -nl_sendmsg (struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) +nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) { - int ret; + int ret; - if (sk->s_fd < 0) - return -NME_NL_BAD_SOCK; + if (sk->s_fd < 0) + return -NME_NL_BAD_SOCK; - nlmsg_set_src (msg, &sk->s_local); + nlmsg_set_src(msg, &sk->s_local); - ret = sendmsg (sk->s_fd, hdr, 0); - if (ret < 0) - return -nm_errno_from_native (errno); + ret = sendmsg(sk->s_fd, hdr, 0); + if (ret < 0) + return -nm_errno_from_native(errno); - return ret; + return ret; } int -nl_send_iovec (struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen) +nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen) { - struct sockaddr_nl *dst; - struct ucred *creds; - struct msghdr hdr = { - .msg_name = (void *) &sk->s_peer, - .msg_namelen = sizeof (struct sockaddr_nl), - .msg_iov = iov, - .msg_iovlen = iovlen, - }; - char buf[CMSG_SPACE (sizeof (struct ucred))]; - - /* Overwrite destination if specified in the message itself, defaults - * to the peer address of the socket. - */ - dst = nlmsg_get_dst (msg); - if (dst->nl_family == AF_NETLINK) - hdr.msg_name = dst; - - /* Add credentials if present. */ - creds = nlmsg_get_creds (msg); - if (creds != NULL) { - struct cmsghdr *cmsg; - - hdr.msg_control = buf; - hdr.msg_controllen = sizeof (buf); - - cmsg = CMSG_FIRSTHDR (&hdr); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_CREDENTIALS; - cmsg->cmsg_len = CMSG_LEN (sizeof (struct ucred)); - memcpy (CMSG_DATA (cmsg), creds, sizeof (struct ucred)); - } - - return nl_sendmsg (sk, msg, &hdr); + struct sockaddr_nl *dst; + struct ucred * creds; + struct msghdr hdr = { + .msg_name = (void *) &sk->s_peer, + .msg_namelen = sizeof(struct sockaddr_nl), + .msg_iov = iov, + .msg_iovlen = iovlen, + }; + char buf[CMSG_SPACE(sizeof(struct ucred))]; + + /* Overwrite destination if specified in the message itself, defaults + * to the peer address of the socket. + */ + dst = nlmsg_get_dst(msg); + if (dst->nl_family == AF_NETLINK) + hdr.msg_name = dst; + + /* Add credentials if present. */ + creds = nlmsg_get_creds(msg); + if (creds != NULL) { + struct cmsghdr *cmsg; + + hdr.msg_control = buf; + hdr.msg_controllen = sizeof(buf); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred)); + } + + return nl_sendmsg(sk, msg, &hdr); } void -nl_complete_msg (struct nl_sock *sk, struct nl_msg *msg) +nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) { - struct nlmsghdr *nlh; + struct nlmsghdr *nlh; - nlh = nlmsg_hdr (msg); - if (nlh->nlmsg_pid == NL_AUTO_PORT) - nlh->nlmsg_pid = nl_socket_get_local_port (sk); + nlh = nlmsg_hdr(msg); + if (nlh->nlmsg_pid == NL_AUTO_PORT) + nlh->nlmsg_pid = nl_socket_get_local_port(sk); - if (nlh->nlmsg_seq == NL_AUTO_SEQ) - nlh->nlmsg_seq = sk->s_seq_next++; + if (nlh->nlmsg_seq == NL_AUTO_SEQ) + nlh->nlmsg_seq = sk->s_seq_next++; - if (msg->nm_protocol == -1) - msg->nm_protocol = sk->s_proto; + if (msg->nm_protocol == -1) + msg->nm_protocol = sk->s_proto; - nlh->nlmsg_flags |= NLM_F_REQUEST; + nlh->nlmsg_flags |= NLM_F_REQUEST; - if (!(sk->s_flags & NL_NO_AUTO_ACK)) - nlh->nlmsg_flags |= NLM_F_ACK; + if (!(sk->s_flags & NL_NO_AUTO_ACK)) + nlh->nlmsg_flags |= NLM_F_ACK; } int -nl_send (struct nl_sock *sk, struct nl_msg *msg) +nl_send(struct nl_sock *sk, struct nl_msg *msg) { - struct iovec iov = { - .iov_base = (void *) nlmsg_hdr (msg), - .iov_len = nlmsg_hdr (msg)->nlmsg_len, - }; + struct iovec iov = { + .iov_base = (void *) nlmsg_hdr(msg), + .iov_len = nlmsg_hdr(msg)->nlmsg_len, + }; - return nl_send_iovec (sk, msg, &iov, 1); + return nl_send_iovec(sk, msg, &iov, 1); } -int nl_send_auto (struct nl_sock *sk, struct nl_msg *msg) +int +nl_send_auto(struct nl_sock *sk, struct nl_msg *msg) { - nl_complete_msg (sk, msg); + nl_complete_msg(sk, msg); - return nl_send (sk, msg); + return nl_send(sk, msg); } int -nl_recv (struct nl_sock *sk, - struct sockaddr_nl *nla, - unsigned char **buf, - struct ucred *out_creds, - gboolean *out_creds_has) +nl_recv(struct nl_sock * sk, + struct sockaddr_nl *nla, + unsigned char ** buf, + struct ucred * out_creds, + gboolean * out_creds_has) { - ssize_t n; - int flags = 0; - struct iovec iov; - struct msghdr msg = { - .msg_name = (void *) nla, - .msg_namelen = sizeof (struct sockaddr_nl), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - struct ucred tmpcreds; - gboolean tmpcreds_has = FALSE; - int retval; - int errsv; - - nm_assert (nla); - nm_assert (buf && !*buf); - nm_assert (!out_creds_has == !out_creds); - - if ( (sk->s_flags & NL_MSG_PEEK) - || ( !(sk->s_flags & NL_MSG_PEEK_EXPLICIT) - && sk->s_bufsize == 0)) - flags |= MSG_PEEK | MSG_TRUNC; - - iov.iov_len = sk->s_bufsize - ?: (((size_t) nm_utils_getpagesize ()) * 4u); - iov.iov_base = g_malloc (iov.iov_len); - - if ( out_creds - && (sk->s_flags & NL_SOCK_PASSCRED)) { - msg.msg_controllen = CMSG_SPACE (sizeof (struct ucred)); - msg.msg_control = g_malloc (msg.msg_controllen); - } + ssize_t n; + int flags = 0; + struct iovec iov; + struct msghdr msg = { + .msg_name = (void *) nla, + .msg_namelen = sizeof(struct sockaddr_nl), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + struct ucred tmpcreds; + gboolean tmpcreds_has = FALSE; + int retval; + int errsv; + + nm_assert(nla); + nm_assert(buf && !*buf); + nm_assert(!out_creds_has == !out_creds); + + if ((sk->s_flags & NL_MSG_PEEK) + || (!(sk->s_flags & NL_MSG_PEEK_EXPLICIT) && sk->s_bufsize == 0)) + flags |= MSG_PEEK | MSG_TRUNC; + + iov.iov_len = sk->s_bufsize ?: (((size_t) nm_utils_getpagesize()) * 4u); + iov.iov_base = g_malloc(iov.iov_len); + + if (out_creds && (sk->s_flags & NL_SOCK_PASSCRED)) { + msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); + msg.msg_control = g_malloc(msg.msg_controllen); + } retry: - n = recvmsg (sk->s_fd, &msg, flags); - if (!n) { - retval = 0; - goto abort; - } - - if (n < 0) { - errsv = errno; - if (errsv == EINTR) - goto retry; - retval = -nm_errno_from_native (errsv); - goto abort; - } - - if (msg.msg_flags & MSG_CTRUNC) { - if (msg.msg_controllen == 0) { - retval = -NME_NL_MSG_TRUNC; - goto abort; - } - - msg.msg_controllen *= 2; - msg.msg_control = g_realloc (msg.msg_control, msg.msg_controllen); - goto retry; - } - - if ( iov.iov_len < n - || (msg.msg_flags & MSG_TRUNC)) { - /* respond with error to an incomplete message */ - if (flags == 0) { - retval = -NME_NL_MSG_TRUNC; - goto abort; - } - - /* Provided buffer is not long enough, enlarge it - * to size of n (which should be total length of the message) - * and try again. */ - iov.iov_base = g_realloc (iov.iov_base, n); - iov.iov_len = n; - flags = 0; - goto retry; - } - - if (flags != 0) { - /* Buffer is big enough, do the actual reading */ - flags = 0; - goto retry; - } - - if (msg.msg_namelen != sizeof (struct sockaddr_nl)) { - retval = -NME_UNSPEC; - goto abort; - } - - if (out_creds && (sk->s_flags & NL_SOCK_PASSCRED)) { - struct cmsghdr *cmsg; - - for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) { - if (cmsg->cmsg_level != SOL_SOCKET) - continue; - if (cmsg->cmsg_type != SCM_CREDENTIALS) - continue; - memcpy (&tmpcreds, CMSG_DATA (cmsg), sizeof (tmpcreds)); - tmpcreds_has = TRUE; - break; - } - } - - retval = n; + n = recvmsg(sk->s_fd, &msg, flags); + if (!n) { + retval = 0; + goto abort; + } + + if (n < 0) { + errsv = errno; + if (errsv == EINTR) + goto retry; + retval = -nm_errno_from_native(errsv); + goto abort; + } + + if (msg.msg_flags & MSG_CTRUNC) { + if (msg.msg_controllen == 0) { + retval = -NME_NL_MSG_TRUNC; + goto abort; + } + + msg.msg_controllen *= 2; + msg.msg_control = g_realloc(msg.msg_control, msg.msg_controllen); + goto retry; + } + + if (iov.iov_len < n || (msg.msg_flags & MSG_TRUNC)) { + /* respond with error to an incomplete message */ + if (flags == 0) { + retval = -NME_NL_MSG_TRUNC; + goto abort; + } + + /* Provided buffer is not long enough, enlarge it + * to size of n (which should be total length of the message) + * and try again. */ + iov.iov_base = g_realloc(iov.iov_base, n); + iov.iov_len = n; + flags = 0; + goto retry; + } + + if (flags != 0) { + /* Buffer is big enough, do the actual reading */ + flags = 0; + goto retry; + } + + if (msg.msg_namelen != sizeof(struct sockaddr_nl)) { + retval = -NME_UNSPEC; + goto abort; + } + + if (out_creds && (sk->s_flags & NL_SOCK_PASSCRED)) { + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET) + continue; + if (cmsg->cmsg_type != SCM_CREDENTIALS) + continue; + memcpy(&tmpcreds, CMSG_DATA(cmsg), sizeof(tmpcreds)); + tmpcreds_has = TRUE; + break; + } + } + + retval = n; abort: - g_free (msg.msg_control); - - if (retval <= 0) { - g_free (iov.iov_base); - return retval; - } - - *buf = iov.iov_base; - if (out_creds && tmpcreds_has) - *out_creds = tmpcreds; - NM_SET_OUT (out_creds_has, tmpcreds_has); - return retval; + g_free(msg.msg_control); + + if (retval <= 0) { + g_free(iov.iov_base); + return retval; + } + + *buf = iov.iov_base; + if (out_creds && tmpcreds_has) + *out_creds = tmpcreds; + NM_SET_OUT(out_creds_has, tmpcreds_has); + return retval; } diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h index a5124f52..52283e9f 100644 --- a/src/platform/nm-netlink.h +++ b/src/platform/nm-netlink.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2018 Red Hat, Inc. */ @@ -14,37 +14,37 @@ /*****************************************************************************/ -#define NLMSGERR_ATTR_UNUSED 0 -#define NLMSGERR_ATTR_MSG 1 -#define NLMSGERR_ATTR_OFFS 2 -#define NLMSGERR_ATTR_COOKIE 3 -#define NLMSGERR_ATTR_MAX 3 +#define NLMSGERR_ATTR_UNUSED 0 +#define NLMSGERR_ATTR_MSG 1 +#define NLMSGERR_ATTR_OFFS 2 +#define NLMSGERR_ATTR_COOKIE 3 +#define NLMSGERR_ATTR_MAX 3 #ifndef NLM_F_ACK_TLVS -#define NLM_F_ACK_TLVS 0x200 + #define NLM_F_ACK_TLVS 0x200 #endif /*****************************************************************************/ /* Basic attribute data types */ enum { - NLA_UNSPEC, /* Unspecified type, binary data chunk */ - NLA_U8, /* 8 bit integer */ - NLA_U16, /* 16 bit integer */ - NLA_U32, /* 32 bit integer */ - NLA_U64, /* 64 bit integer */ - NLA_STRING, /* NUL terminated character string */ - NLA_FLAG, /* Flag */ - NLA_MSECS, /* Micro seconds (64bit) */ - NLA_NESTED, /* Nested attributes */ - NLA_NESTED_COMPAT, - NLA_NUL_STRING, - NLA_BINARY, - NLA_S8, - NLA_S16, - NLA_S32, - NLA_S64, - __NLA_TYPE_MAX, + NLA_UNSPEC, /* Unspecified type, binary data chunk */ + NLA_U8, /* 8 bit integer */ + NLA_U16, /* 16 bit integer */ + NLA_U32, /* 32 bit integer */ + NLA_U64, /* 64 bit integer */ + NLA_STRING, /* NUL terminated character string */ + NLA_FLAG, /* Flag */ + NLA_MSECS, /* Micro seconds (64bit) */ + NLA_NESTED, /* Nested attributes */ + NLA_NESTED_COMPAT, + NLA_NUL_STRING, + NLA_BINARY, + NLA_S8, + NLA_S16, + NLA_S32, + NLA_S64, + __NLA_TYPE_MAX, }; #define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) @@ -53,456 +53,445 @@ struct nl_msg; /*****************************************************************************/ -const char *nl_nlmsgtype2str (int type, char *buf, size_t size); +const char *nl_nlmsgtype2str(int type, char *buf, size_t size); -const char *nl_nlmsg_flags2str (int flags, char *buf, size_t len); +const char *nl_nlmsg_flags2str(int flags, char *buf, size_t len); -const char *nl_nlmsghdr_to_str (const struct nlmsghdr *hdr, char *buf, gsize len); +const char *nl_nlmsghdr_to_str(const struct nlmsghdr *hdr, char *buf, gsize len); /*****************************************************************************/ struct nla_policy { - /* Type of attribute or NLA_UNSPEC */ - uint16_t type; + /* Type of attribute or NLA_UNSPEC */ + uint16_t type; - /* Minimal length of payload required */ - uint16_t minlen; + /* Minimal length of payload required */ + uint16_t minlen; - /* Maximal length of payload allowed */ - uint16_t maxlen; + /* Maximal length of payload allowed */ + uint16_t maxlen; }; /*****************************************************************************/ /* static asserts that @tb and @policy are suitable arguments to nla_parse(). */ -#define _nl_static_assert_tb(tb, policy) \ - G_STMT_START { \ - G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (tb) > 0); \ - \ - /* We allow @policy to be either a C array or NULL. The sizeof() - * must either match the expected array size or the sizeof(NULL), - * but not both. */ \ - G_STATIC_ASSERT_EXPR ( (sizeof (policy) == G_N_ELEMENTS (tb) * sizeof (struct nla_policy)) \ - ^ (sizeof (policy) == sizeof (NULL))); \ - } G_STMT_END +#define _nl_static_assert_tb(tb, policy) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(tb) > 0); \ + \ + /* We allow @policy to be either a C array or NULL. The sizeof() + * must either match the expected array size or the sizeof(NULL), + * but not both. */ \ + G_STATIC_ASSERT_EXPR((sizeof(policy) == G_N_ELEMENTS(tb) * sizeof(struct nla_policy)) \ + ^ (sizeof(policy) == sizeof(NULL))); \ + } \ + G_STMT_END /*****************************************************************************/ static inline int -nla_attr_size (int payload) +nla_attr_size(int payload) { - nm_assert (payload >= 0); + nm_assert(payload >= 0); - return NLA_HDRLEN + payload; + return NLA_HDRLEN + payload; } static inline int -nla_total_size (int payload) +nla_total_size(int payload) { - return NLA_ALIGN (nla_attr_size (payload)); + return NLA_ALIGN(nla_attr_size(payload)); } static inline int -nla_padlen (int payload) +nla_padlen(int payload) { - return nla_total_size (payload) - nla_attr_size (payload); + return nla_total_size(payload) - nla_attr_size(payload); } -struct nlattr *nla_reserve (struct nl_msg *msg, int attrtype, int attrlen); +struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen); static inline int -nla_len (const struct nlattr *nla) +nla_len(const struct nlattr *nla) { - nm_assert (nla); - nm_assert (nla->nla_len >= NLA_HDRLEN); + nm_assert(nla); + nm_assert(nla->nla_len >= NLA_HDRLEN); - return ((int) nla->nla_len) - NLA_HDRLEN; + return ((int) nla->nla_len) - NLA_HDRLEN; } static inline int -nla_type (const struct nlattr *nla) +nla_type(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= 0); + nm_assert(nla_len(nla) >= 0); - return nla->nla_type & NLA_TYPE_MASK; + return nla->nla_type & NLA_TYPE_MASK; } static inline void * -nla_data (const struct nlattr *nla) +nla_data(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= 0); + nm_assert(nla_len(nla) >= 0); - return &(((char *) nla)[NLA_HDRLEN]); + return &(((char *) nla)[NLA_HDRLEN]); } -#define nla_data_as(type, nla) \ - ({ \ - const struct nlattr *_nla = (nla); \ - \ - nm_assert (nla_len (_nla) >= sizeof (type)); \ - \ - /* note that casting the pointer is undefined behavior in C, if - * the data has wrong alignment. Netlink data is aligned to 4 bytes, - * that means, if the alignment is larger than 4, this is invalid. */ \ - G_STATIC_ASSERT_EXPR (_nm_alignof (type) <= NLA_ALIGNTO); \ - \ - (type *) nla_data (_nla); \ - }) +#define nla_data_as(type, nla) \ + ({ \ + const struct nlattr *_nla = (nla); \ + \ + nm_assert(nla_len(_nla) >= sizeof(type)); \ + \ + /* note that casting the pointer is undefined behavior in C, if + * the data has wrong alignment. Netlink data is aligned to 4 bytes, + * that means, if the alignment is larger than 4, this is invalid. */ \ + G_STATIC_ASSERT_EXPR(_nm_alignof(type) <= NLA_ALIGNTO); \ + \ + (type *) nla_data(_nla); \ + }) static inline uint8_t -nla_get_u8 (const struct nlattr *nla) +nla_get_u8(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= sizeof (uint8_t)); + nm_assert(nla_len(nla) >= sizeof(uint8_t)); - return *((const uint8_t *) nla_data (nla)); + return *((const uint8_t *) nla_data(nla)); } static inline int8_t -nla_get_s8 (const struct nlattr *nla) +nla_get_s8(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= sizeof (int8_t)); + nm_assert(nla_len(nla) >= sizeof(int8_t)); - return *((const int8_t *) nla_data (nla)); + return *((const int8_t *) nla_data(nla)); } static inline uint8_t -nla_get_u8_cond (/*const*/ struct nlattr *const*tb, int attr, uint8_t default_val) +nla_get_u8_cond(/*const*/ struct nlattr *const *tb, int attr, uint8_t default_val) { - nm_assert (tb); - nm_assert (attr >= 0); + nm_assert(tb); + nm_assert(attr >= 0); - return tb[attr] ? nla_get_u8 (tb[attr]) : default_val; + return tb[attr] ? nla_get_u8(tb[attr]) : default_val; } static inline uint16_t -nla_get_u16 (const struct nlattr *nla) +nla_get_u16(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= sizeof (uint16_t)); + nm_assert(nla_len(nla) >= sizeof(uint16_t)); - return *((const uint16_t *) nla_data (nla)); + return *((const uint16_t *) nla_data(nla)); } static inline uint32_t -nla_get_u32 (const struct nlattr *nla) +nla_get_u32(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= sizeof (uint32_t)); + nm_assert(nla_len(nla) >= sizeof(uint32_t)); - return *((const uint32_t *) nla_data (nla)); + return *((const uint32_t *) nla_data(nla)); } static inline int32_t -nla_get_s32 (const struct nlattr *nla) +nla_get_s32(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= sizeof (int32_t)); + nm_assert(nla_len(nla) >= sizeof(int32_t)); - return *((const int32_t *) nla_data (nla)); + return *((const int32_t *) nla_data(nla)); } static inline uint64_t -nla_get_u64 (const struct nlattr *nla) +nla_get_u64(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= sizeof (uint64_t)); + nm_assert(nla_len(nla) >= sizeof(uint64_t)); - return unaligned_read_ne64 (nla_data (nla)); + return unaligned_read_ne64(nla_data(nla)); } static inline uint64_t -nla_get_be64 (const struct nlattr *nla) +nla_get_be64(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= sizeof (uint64_t)); + nm_assert(nla_len(nla) >= sizeof(uint64_t)); - return unaligned_read_be64 (nla_data (nla)); + return unaligned_read_be64(nla_data(nla)); } static inline char * -nla_get_string (const struct nlattr *nla) +nla_get_string(const struct nlattr *nla) { - nm_assert (nla_len (nla) >= 0); + nm_assert(nla_len(nla) >= 0); - return (char *) nla_data (nla); + return (char *) nla_data(nla); } -size_t nla_strlcpy (char *dst, const struct nlattr *nla, size_t dstsize); +size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize); -size_t nla_memcpy (void *dst, const struct nlattr *nla, size_t dstsize); +size_t nla_memcpy(void *dst, const struct nlattr *nla, size_t dstsize); -#define nla_memcpy_checked_size(dst, nla, dstsize) \ - G_STMT_START { \ - void *const _dst = (dst); \ - const struct nlattr *const _nla = (nla); \ - const size_t _dstsize = (dstsize); \ - size_t _srcsize; \ - \ - /* assert that, if @nla is given, that it has the exact expected - * size. This implies that the caller previously verified the length - * of the attribute (via minlen/maxlen at nla_parse()). */ \ - \ - if (_nla) { \ - _srcsize = nla_memcpy (_dst, _nla, _dstsize); \ - nm_assert (_srcsize == _dstsize); \ - } \ - } G_STMT_END +#define nla_memcpy_checked_size(dst, nla, dstsize) \ + G_STMT_START \ + { \ + void *const _dst = (dst); \ + const struct nlattr *const _nla = (nla); \ + const size_t _dstsize = (dstsize); \ + size_t _srcsize; \ + \ + /* assert that, if @nla is given, that it has the exact expected + * size. This implies that the caller previously verified the length + * of the attribute (via minlen/maxlen at nla_parse()). */ \ + \ + if (_nla) { \ + _srcsize = nla_memcpy(_dst, _nla, _dstsize); \ + nm_assert(_srcsize == _dstsize); \ + } \ + } \ + G_STMT_END -int nla_put (struct nl_msg *msg, int attrtype, int datalen, const void *data); +int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data); static inline int -nla_put_string (struct nl_msg *msg, int attrtype, const char *str) +nla_put_string(struct nl_msg *msg, int attrtype, const char *str) { - nm_assert (str); + nm_assert(str); - return nla_put (msg, attrtype, strlen (str) + 1, str); + return nla_put(msg, attrtype, strlen(str) + 1, str); } static inline int -nla_put_uint8 (struct nl_msg *msg, int attrtype, uint8_t val) +nla_put_uint8(struct nl_msg *msg, int attrtype, uint8_t val) { - return nla_put (msg, attrtype, sizeof (val), &val); + return nla_put(msg, attrtype, sizeof(val), &val); } static inline int -nla_put_uint16 (struct nl_msg *msg, int attrtype, uint16_t val) +nla_put_uint16(struct nl_msg *msg, int attrtype, uint16_t val) { - return nla_put (msg, attrtype, sizeof (val), &val); + return nla_put(msg, attrtype, sizeof(val), &val); } static inline int -nla_put_uint32 (struct nl_msg *msg, int attrtype, uint32_t val) +nla_put_uint32(struct nl_msg *msg, int attrtype, uint32_t val) { - return nla_put (msg, attrtype, sizeof (val), &val); + return nla_put(msg, attrtype, sizeof(val), &val); } -#define NLA_PUT(msg, attrtype, attrlen, data) \ - G_STMT_START { \ - if (nla_put (msg, attrtype, attrlen, data) < 0) \ - goto nla_put_failure; \ - } G_STMT_END +#define NLA_PUT(msg, attrtype, attrlen, data) \ + G_STMT_START \ + { \ + if (nla_put(msg, attrtype, attrlen, data) < 0) \ + goto nla_put_failure; \ + } \ + G_STMT_END -#define NLA_PUT_TYPE(msg, type, attrtype, value) \ - G_STMT_START { \ - type __nla_tmp = value; \ - NLA_PUT (msg, attrtype, sizeof (type), &__nla_tmp); \ - } G_STMT_END +#define NLA_PUT_TYPE(msg, type, attrtype, value) \ + G_STMT_START \ + { \ + type __nla_tmp = value; \ + NLA_PUT(msg, attrtype, sizeof(type), &__nla_tmp); \ + } \ + G_STMT_END -#define NLA_PUT_U8(msg, attrtype, value) \ - NLA_PUT_TYPE (msg, uint8_t, attrtype, value) +#define NLA_PUT_U8(msg, attrtype, value) NLA_PUT_TYPE(msg, uint8_t, attrtype, value) -#define NLA_PUT_S8(msg, attrtype, value) \ - NLA_PUT_TYPE (msg, int8_t, attrtype, value) +#define NLA_PUT_S8(msg, attrtype, value) NLA_PUT_TYPE(msg, int8_t, attrtype, value) -#define NLA_PUT_U16(msg, attrtype, value) \ - NLA_PUT_TYPE (msg, uint16_t, attrtype, value) +#define NLA_PUT_U16(msg, attrtype, value) NLA_PUT_TYPE(msg, uint16_t, attrtype, value) -#define NLA_PUT_U32(msg, attrtype, value) \ - NLA_PUT_TYPE (msg, uint32_t, attrtype, value) +#define NLA_PUT_U32(msg, attrtype, value) NLA_PUT_TYPE(msg, uint32_t, attrtype, value) -#define NLA_PUT_S32(msg, attrtype, value) \ - NLA_PUT_TYPE (msg, int32_t, attrtype, value) +#define NLA_PUT_S32(msg, attrtype, value) NLA_PUT_TYPE(msg, int32_t, attrtype, value) -#define NLA_PUT_U64(msg, attrtype, value) \ - NLA_PUT_TYPE (msg, uint64_t, attrtype, value) +#define NLA_PUT_U64(msg, attrtype, value) NLA_PUT_TYPE(msg, uint64_t, attrtype, value) -#define NLA_PUT_STRING(msg, attrtype, value) \ - NLA_PUT (msg, attrtype, (int) strlen (value) + 1, value) +#define NLA_PUT_STRING(msg, attrtype, value) NLA_PUT(msg, attrtype, (int) strlen(value) + 1, value) -#define NLA_PUT_FLAG(msg, attrtype) \ - NLA_PUT (msg, attrtype, 0, NULL) +#define NLA_PUT_FLAG(msg, attrtype) NLA_PUT(msg, attrtype, 0, NULL) -struct nlattr *nla_find (const struct nlattr *head, int len, int attrtype); +struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype); static inline int -nla_ok (const struct nlattr *nla, int remaining) +nla_ok(const struct nlattr *nla, int remaining) { - return remaining >= (int) sizeof (*nla) && - nla->nla_len >= sizeof (*nla) && - nla->nla_len <= remaining; + return remaining >= (int) sizeof(*nla) && nla->nla_len >= sizeof(*nla) + && nla->nla_len <= remaining; } static inline struct nlattr * -nla_next (const struct nlattr *nla, int *remaining) +nla_next(const struct nlattr *nla, int *remaining) { - int totlen = NLA_ALIGN (nla->nla_len); + int totlen = NLA_ALIGN(nla->nla_len); - *remaining -= totlen; - return (struct nlattr *) ((char *) nla + totlen); + *remaining -= totlen; + return (struct nlattr *) ((char *) nla + totlen); } #define nla_for_each_attr(pos, head, len, rem) \ - for (pos = head, rem = len; \ - nla_ok (pos, rem); \ - pos = nla_next (pos, &(rem))) - -#define nla_for_each_nested(pos, nla, rem) \ - for (pos = (struct nlattr *) nla_data (nla), rem = nla_len (nla); \ - nla_ok (pos, rem); \ - pos = nla_next (pos, &(rem))) - -void nla_nest_cancel (struct nl_msg *msg, const struct nlattr *attr); -struct nlattr *nla_nest_start (struct nl_msg *msg, int attrtype); -int nla_nest_end (struct nl_msg *msg, struct nlattr *start); - -int nla_parse (struct nlattr *tb[], - int maxtype, - struct nlattr *head, - int len, - const struct nla_policy *policy); - -#define nla_parse_arr(tb, head, len, policy) \ - ({ \ - _nl_static_assert_tb ((tb), (policy)); \ - \ - nla_parse ((tb), G_N_ELEMENTS (tb) - 1, (head), (len), (policy)); \ - }) + for (pos = head, rem = len; nla_ok(pos, rem); pos = nla_next(pos, &(rem))) + +#define nla_for_each_nested(pos, nla, rem) \ + for (pos = (struct nlattr *) nla_data(nla), rem = nla_len(nla); nla_ok(pos, rem); \ + pos = nla_next(pos, &(rem))) + +void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr); +struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype); +int nla_nest_end(struct nl_msg *msg, struct nlattr *start); + +int nla_parse(struct nlattr * tb[], + int maxtype, + struct nlattr * head, + int len, + const struct nla_policy *policy); + +#define nla_parse_arr(tb, head, len, policy) \ + ({ \ + _nl_static_assert_tb((tb), (policy)); \ + \ + nla_parse((tb), G_N_ELEMENTS(tb) - 1, (head), (len), (policy)); \ + }) static inline int -nla_parse_nested (struct nlattr *tb[], - int maxtype, - struct nlattr *nla, - const struct nla_policy *policy) +nla_parse_nested(struct nlattr * tb[], + int maxtype, + struct nlattr * nla, + const struct nla_policy *policy) { - return nla_parse (tb, maxtype, nla_data (nla), nla_len (nla), policy); + return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); } -#define nla_parse_nested_arr(tb, nla, policy) \ - ({ \ - _nl_static_assert_tb ((tb), (policy)); \ - \ - nla_parse_nested ((tb), G_N_ELEMENTS (tb) - 1, (nla), (policy)); \ - }) +#define nla_parse_nested_arr(tb, nla, policy) \ + ({ \ + _nl_static_assert_tb((tb), (policy)); \ + \ + nla_parse_nested((tb), G_N_ELEMENTS(tb) - 1, (nla), (policy)); \ + }) /*****************************************************************************/ -struct nl_msg *nlmsg_alloc (void); +struct nl_msg *nlmsg_alloc(void); -struct nl_msg *nlmsg_alloc_size (size_t max); +struct nl_msg *nlmsg_alloc_size(size_t max); -struct nl_msg *nlmsg_alloc_convert (struct nlmsghdr *hdr); +struct nl_msg *nlmsg_alloc_convert(struct nlmsghdr *hdr); -struct nl_msg *nlmsg_alloc_simple (int nlmsgtype, int flags); +struct nl_msg *nlmsg_alloc_simple(int nlmsgtype, int flags); -void *nlmsg_reserve (struct nl_msg *n, size_t len, int pad); +void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad); -int nlmsg_append (struct nl_msg *n, - const void *data, - size_t len, - int pad); +int nlmsg_append(struct nl_msg *n, const void *data, size_t len, int pad); -#define nlmsg_append_struct(n, data) \ - nlmsg_append (n, (data), sizeof (*(data)), NLMSG_ALIGNTO) +#define nlmsg_append_struct(n, data) nlmsg_append(n, (data), sizeof(*(data)), NLMSG_ALIGNTO) -void nlmsg_free (struct nl_msg *msg); +void nlmsg_free(struct nl_msg *msg); static inline int -nlmsg_size (int payload) +nlmsg_size(int payload) { - nm_assert (payload >= 0 && payload < G_MAXINT - NLMSG_HDRLEN - 4); - return NLMSG_HDRLEN + payload; + nm_assert(payload >= 0 && payload < G_MAXINT - NLMSG_HDRLEN - 4); + return NLMSG_HDRLEN + payload; } static inline int -nlmsg_total_size (int payload) +nlmsg_total_size(int payload) { - return NLMSG_ALIGN (nlmsg_size (payload)); + return NLMSG_ALIGN(nlmsg_size(payload)); } static inline int -nlmsg_ok (const struct nlmsghdr *nlh, int remaining) +nlmsg_ok(const struct nlmsghdr *nlh, int remaining) { - return (remaining >= (int) sizeof (struct nlmsghdr) && - nlh->nlmsg_len >= sizeof (struct nlmsghdr) && - nlh->nlmsg_len <= remaining); + return (remaining >= (int) sizeof(struct nlmsghdr) && nlh->nlmsg_len >= sizeof(struct nlmsghdr) + && nlh->nlmsg_len <= remaining); } static inline struct nlmsghdr * -nlmsg_next (struct nlmsghdr *nlh, int *remaining) +nlmsg_next(struct nlmsghdr *nlh, int *remaining) { - int totlen = NLMSG_ALIGN (nlh->nlmsg_len); + int totlen = NLMSG_ALIGN(nlh->nlmsg_len); - *remaining -= totlen; + *remaining -= totlen; - return (struct nlmsghdr *) ((unsigned char *) nlh + totlen); + return (struct nlmsghdr *) ((unsigned char *) nlh + totlen); } -int nlmsg_get_proto (struct nl_msg *msg); -void nlmsg_set_proto (struct nl_msg *msg, int protocol); +int nlmsg_get_proto(struct nl_msg *msg); +void nlmsg_set_proto(struct nl_msg *msg, int protocol); -void nlmsg_set_src (struct nl_msg *msg, struct sockaddr_nl *addr); +void nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr); -struct ucred *nlmsg_get_creds (struct nl_msg *msg); -void nlmsg_set_creds (struct nl_msg *msg, struct ucred *creds); +struct ucred *nlmsg_get_creds(struct nl_msg *msg); +void nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds); static inline void -_nm_auto_nl_msg_cleanup (struct nl_msg **ptr) +_nm_auto_nl_msg_cleanup(struct nl_msg **ptr) { - nlmsg_free (*ptr); + nlmsg_free(*ptr); } -#define nm_auto_nlmsg nm_auto (_nm_auto_nl_msg_cleanup) +#define nm_auto_nlmsg nm_auto(_nm_auto_nl_msg_cleanup) static inline void * -nlmsg_data (const struct nlmsghdr *nlh) +nlmsg_data(const struct nlmsghdr *nlh) { - return (unsigned char *) nlh + NLMSG_HDRLEN; + return (unsigned char *) nlh + NLMSG_HDRLEN; } static inline void * -nlmsg_tail (const struct nlmsghdr *nlh) +nlmsg_tail(const struct nlmsghdr *nlh) { - return (unsigned char *) nlh + NLMSG_ALIGN (nlh->nlmsg_len); + return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len); } -struct nlmsghdr *nlmsg_hdr (struct nl_msg *n); +struct nlmsghdr *nlmsg_hdr(struct nl_msg *n); static inline int -nlmsg_valid_hdr (const struct nlmsghdr *nlh, int hdrlen) +nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen) { - if (nlh->nlmsg_len < nlmsg_size (hdrlen)) - return 0; + if (nlh->nlmsg_len < nlmsg_size(hdrlen)) + return 0; - return 1; + return 1; } static inline int -nlmsg_datalen (const struct nlmsghdr *nlh) +nlmsg_datalen(const struct nlmsghdr *nlh) { - return nlh->nlmsg_len - NLMSG_HDRLEN; + return nlh->nlmsg_len - NLMSG_HDRLEN; } static inline int -nlmsg_attrlen (const struct nlmsghdr *nlh, int hdrlen) +nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen) { - return NM_MAX ((int) (nlmsg_datalen (nlh) - NLMSG_ALIGN (hdrlen)), 0); + return NM_MAX((int) (nlmsg_datalen(nlh) - NLMSG_ALIGN(hdrlen)), 0); } static inline struct nlattr * -nlmsg_attrdata (const struct nlmsghdr *nlh, int hdrlen) +nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen) { - unsigned char *data = nlmsg_data (nlh); - return (struct nlattr *) (data + NLMSG_ALIGN (hdrlen)); + unsigned char *data = nlmsg_data(nlh); + return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen)); } static inline struct nlattr * -nlmsg_find_attr (struct nlmsghdr *nlh, int hdrlen, int attrtype) +nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype) { - return nla_find (nlmsg_attrdata (nlh, hdrlen), - nlmsg_attrlen (nlh, hdrlen), - attrtype); + return nla_find(nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), attrtype); } -int nlmsg_parse (struct nlmsghdr *nlh, - int hdrlen, - struct nlattr *tb[], - int maxtype, - const struct nla_policy *policy); +int nlmsg_parse(struct nlmsghdr * nlh, + int hdrlen, + struct nlattr * tb[], + int maxtype, + const struct nla_policy *policy); -#define nlmsg_parse_arr(nlh, hdrlen, tb, policy) \ - ({ \ - _nl_static_assert_tb ((tb), (policy)); \ - G_STATIC_ASSERT_EXPR ((hdrlen) >= 0); \ - \ - nlmsg_parse ((nlh), (hdrlen), (tb), G_N_ELEMENTS (tb) - 1, (policy)); \ - }) +#define nlmsg_parse_arr(nlh, hdrlen, tb, policy) \ + ({ \ + _nl_static_assert_tb((tb), (policy)); \ + G_STATIC_ASSERT_EXPR((hdrlen) >= 0); \ + \ + nlmsg_parse((nlh), (hdrlen), (tb), G_N_ELEMENTS(tb) - 1, (policy)); \ + }) -struct nlmsghdr *nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq, - int type, int payload, int flags); +struct nlmsghdr * +nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags); /*****************************************************************************/ @@ -511,112 +500,116 @@ struct nlmsghdr *nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq, struct nl_sock; -struct nl_sock *nl_socket_alloc (void); +struct nl_sock *nl_socket_alloc(void); -void nl_socket_free (struct nl_sock *sk); +void nl_socket_free(struct nl_sock *sk); -int nl_socket_get_fd (const struct nl_sock *sk); +int nl_socket_get_fd(const struct nl_sock *sk); -struct sockaddr_nl *nlmsg_get_dst (struct nl_msg *msg); +struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *msg); -size_t nl_socket_get_msg_buf_size (struct nl_sock *sk); -int nl_socket_set_msg_buf_size (struct nl_sock *sk, size_t bufsize); +size_t nl_socket_get_msg_buf_size(struct nl_sock *sk); +int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize); -int nl_socket_set_buffer_size (struct nl_sock *sk, int rxbuf, int txbuf); +int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf); -int nl_socket_set_passcred (struct nl_sock *sk, int state); +int nl_socket_set_passcred(struct nl_sock *sk, int state); -int nl_socket_set_nonblocking (const struct nl_sock *sk); +int nl_socket_set_nonblocking(const struct nl_sock *sk); -void nl_socket_disable_msg_peek (struct nl_sock *sk); +void nl_socket_disable_msg_peek(struct nl_sock *sk); -uint32_t nl_socket_get_local_port (const struct nl_sock *sk); +uint32_t nl_socket_get_local_port(const struct nl_sock *sk); -int nl_socket_add_memberships (struct nl_sock *sk, int group, ...); +int nl_socket_add_memberships(struct nl_sock *sk, int group, ...); -int nl_connect (struct nl_sock *sk, int protocol); +int nl_connect(struct nl_sock *sk, int protocol); -int nl_recv (struct nl_sock *sk, - struct sockaddr_nl *nla, - unsigned char **buf, - struct ucred *out_creds, - gboolean *out_creds_has); +int nl_recv(struct nl_sock * sk, + struct sockaddr_nl *nla, + unsigned char ** buf, + struct ucred * out_creds, + gboolean * out_creds_has); -int nl_send (struct nl_sock *sk, struct nl_msg *msg); +int nl_send(struct nl_sock *sk, struct nl_msg *msg); -int nl_send_auto (struct nl_sock *sk, struct nl_msg *msg); +int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg); /*****************************************************************************/ enum nl_cb_action { - /* Proceed with wathever would come next */ - NL_OK, - /* Skip this message */ - NL_SKIP, - /* Stop parsing altogether and discard remaining messages */ - NL_STOP, + /* Proceed with wathever would come next */ + NL_OK, + /* Skip this message */ + NL_SKIP, + /* Stop parsing altogether and discard remaining messages */ + NL_STOP, }; -typedef int (*nl_recvmsg_msg_cb_t) (struct nl_msg *msg, void *arg); +typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg); -typedef int (*nl_recvmsg_err_cb_t) (struct sockaddr_nl *nla, - struct nlmsgerr *nlerr, void *arg); +typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg); struct nl_cb { - nl_recvmsg_msg_cb_t valid_cb; - void * valid_arg; + nl_recvmsg_msg_cb_t valid_cb; + void * valid_arg; - nl_recvmsg_msg_cb_t finish_cb; - void * finish_arg; + nl_recvmsg_msg_cb_t finish_cb; + void * finish_arg; - nl_recvmsg_msg_cb_t ack_cb; - void * ack_arg; + nl_recvmsg_msg_cb_t ack_cb; + void * ack_arg; - nl_recvmsg_err_cb_t err_cb; - void * err_arg; + nl_recvmsg_err_cb_t err_cb; + void * err_arg; }; -int nl_sendmsg (struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr); +int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr); -int nl_send_iovec (struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen); +int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen); -void nl_complete_msg (struct nl_sock *sk, struct nl_msg *msg); +void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg); -int nl_recvmsgs (struct nl_sock *sk, const struct nl_cb *cb); +int nl_recvmsgs(struct nl_sock *sk, const struct nl_cb *cb); -int nl_wait_for_ack (struct nl_sock *sk, - const struct nl_cb *cb); +int nl_wait_for_ack(struct nl_sock *sk, const struct nl_cb *cb); -int nl_socket_set_ext_ack (struct nl_sock *sk, gboolean enable); +int nl_socket_set_ext_ack(struct nl_sock *sk, gboolean enable); /*****************************************************************************/ -void *genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family, - int hdrlen, int flags, uint8_t cmd, uint8_t version); -void *genlmsg_data (const struct genlmsghdr *gnlh); -void *genlmsg_user_hdr (const struct genlmsghdr *gnlh); -struct genlmsghdr *genlmsg_hdr (struct nlmsghdr *nlh); -void *genlmsg_user_data (const struct genlmsghdr *gnlh, const int hdrlen); -struct nlattr *genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen); -int genlmsg_len (const struct genlmsghdr *gnlh); -int genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen); -int genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen); - -int genlmsg_parse (struct nlmsghdr *nlh, - int hdrlen, - struct nlattr *tb[], - int maxtype, - const struct nla_policy *policy); - -#define genlmsg_parse_arr(nlh, hdrlen, tb, policy) \ - ({ \ - _nl_static_assert_tb ((tb), (policy)); \ - G_STATIC_ASSERT_EXPR ((hdrlen) >= 0); \ - \ - genlmsg_parse ((nlh), (hdrlen), (tb), G_N_ELEMENTS (tb) - 1, (policy)); \ - }) - -int genl_ctrl_resolve (struct nl_sock *sk, const char *name); +void * genlmsg_put(struct nl_msg *msg, + uint32_t port, + uint32_t seq, + int family, + int hdrlen, + int flags, + uint8_t cmd, + uint8_t version); +void * genlmsg_data(const struct genlmsghdr *gnlh); +void * genlmsg_user_hdr(const struct genlmsghdr *gnlh); +struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh); +void * genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen); +struct nlattr * genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen); +int genlmsg_len(const struct genlmsghdr *gnlh); +int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen); +int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen); + +int genlmsg_parse(struct nlmsghdr * nlh, + int hdrlen, + struct nlattr * tb[], + int maxtype, + const struct nla_policy *policy); + +#define genlmsg_parse_arr(nlh, hdrlen, tb, policy) \ + ({ \ + _nl_static_assert_tb((tb), (policy)); \ + G_STATIC_ASSERT_EXPR((hdrlen) >= 0); \ + \ + genlmsg_parse((nlh), (hdrlen), (tb), G_N_ELEMENTS(tb) - 1, (policy)); \ + }) + +int genl_ctrl_resolve(struct nl_sock *sk, const char *name); /*****************************************************************************/ diff --git a/src/platform/nm-platform-private.h b/src/platform/nm-platform-private.h index a072af05..d99e330b 100644 --- a/src/platform/nm-platform-private.h +++ b/src/platform/nm-platform-private.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -9,19 +9,21 @@ #include "nm-platform.h" #include "nmp-object.h" -NMPCache *nm_platform_get_cache (NMPlatform *self); +NMPCache *nm_platform_get_cache(NMPlatform *self); -#define NMTST_ASSERT_PLATFORM_NETNS_CURRENT(platform) \ - G_STMT_START { \ - NMPlatform *_platform = (platform); \ - \ - nm_assert (NM_IS_PLATFORM (_platform)); \ - nm_assert (NM_IN_SET (nm_platform_netns_get (_platform), NULL, nmp_netns_get_current ())); \ - } G_STMT_END +#define NMTST_ASSERT_PLATFORM_NETNS_CURRENT(platform) \ + G_STMT_START \ + { \ + NMPlatform *_platform = (platform); \ + \ + nm_assert(NM_IS_PLATFORM(_platform)); \ + nm_assert(NM_IN_SET(nm_platform_netns_get(_platform), NULL, nmp_netns_get_current())); \ + } \ + G_STMT_END -void nm_platform_cache_update_emit_signal (NMPlatform *platform, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new); +void nm_platform_cache_update_emit_signal(NMPlatform * platform, + NMPCacheOpsType cache_op, + const NMPObject *obj_old, + const NMPObject *obj_new); #endif /* __NM_PLATFORM_PRIVATE_H__ */ diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 6c14bc5c..ea45050d 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 Red Hat, Inc. */ @@ -30,45 +30,44 @@ * utils *****************************************************************************/ -extern char *if_indextoname (unsigned __ifindex, char *__ifname); -unsigned if_nametoindex (const char *__ifname); +extern char *if_indextoname(unsigned __ifindex, char *__ifname); +unsigned if_nametoindex(const char *__ifname); const char * -nmp_utils_if_indextoname (int ifindex, char *out_ifname/*IFNAMSIZ*/) +nmp_utils_if_indextoname(int ifindex, char *out_ifname /*IFNAMSIZ*/) { - g_return_val_if_fail (ifindex > 0, NULL); - g_return_val_if_fail (out_ifname, NULL); + g_return_val_if_fail(ifindex > 0, NULL); + g_return_val_if_fail(out_ifname, NULL); - return if_indextoname (ifindex, out_ifname); + return if_indextoname(ifindex, out_ifname); } int -nmp_utils_if_nametoindex (const char *ifname) +nmp_utils_if_nametoindex(const char *ifname) { - g_return_val_if_fail (ifname, 0); + g_return_val_if_fail(ifname, 0); - return if_nametoindex (ifname); + return if_nametoindex(ifname); } /*****************************************************************************/ typedef struct { - int fd; - const int ifindex; - char ifname[IFNAMSIZ]; + int fd; + const int ifindex; + char ifname[IFNAMSIZ]; } SocketHandle; -#define SOCKET_HANDLE_INIT(_ifindex) \ - { \ - .fd = -1, \ - .ifindex = (_ifindex), \ - } +#define SOCKET_HANDLE_INIT(_ifindex) \ + { \ + .fd = -1, .ifindex = (_ifindex), \ + } static void -_nm_auto_socket_handle (SocketHandle *shandle) +_nm_auto_socket_handle(SocketHandle *shandle) { - if (shandle->fd >= 0) - nm_close (shandle->fd); + if (shandle->fd >= 0) + nm_close(shandle->fd); } #define nm_auto_socket_handle nm_auto(_nm_auto_socket_handle) @@ -76,421 +75,425 @@ _nm_auto_socket_handle (SocketHandle *shandle) /*****************************************************************************/ typedef enum { - IOCTL_CALL_DATA_TYPE_NONE, - IOCTL_CALL_DATA_TYPE_IFRDATA, - IOCTL_CALL_DATA_TYPE_IFRU, + IOCTL_CALL_DATA_TYPE_NONE, + IOCTL_CALL_DATA_TYPE_IFRDATA, + IOCTL_CALL_DATA_TYPE_IFRU, } IoctlCallDataType; static int -_ioctl_call (const char *log_ioctl_type, - const char *log_subtype, - unsigned long int ioctl_request, - int ifindex, - int *inout_fd, - char *inout_ifname, - IoctlCallDataType edata_type, - gpointer edata, - gsize edata_size, - struct ifreq *out_ifreq) +_ioctl_call(const char * log_ioctl_type, + const char * log_subtype, + unsigned long int ioctl_request, + int ifindex, + int * inout_fd, + char * inout_ifname, + IoctlCallDataType edata_type, + gpointer edata, + gsize edata_size, + struct ifreq * out_ifreq) { - nm_auto_close int fd_close = -1; - int fd; - int r; - gpointer edata_backup = NULL; - gs_free gpointer edata_backup_free = NULL; - guint try_count; - char known_ifnames[2][IFNAMSIZ]; - const char *failure_reason = NULL; - struct ifreq ifr; - - nm_assert (ifindex > 0); - nm_assert (NM_IN_SET (edata_type, IOCTL_CALL_DATA_TYPE_NONE, - IOCTL_CALL_DATA_TYPE_IFRDATA, - IOCTL_CALL_DATA_TYPE_IFRU)); - nm_assert (edata_type != IOCTL_CALL_DATA_TYPE_NONE || edata_size == 0); - nm_assert (edata_type != IOCTL_CALL_DATA_TYPE_IFRDATA || edata_size > 0); - nm_assert (edata_type != IOCTL_CALL_DATA_TYPE_IFRU || (edata_size > 0 && edata_size <= sizeof (ifr.ifr_ifru))); - nm_assert (edata_size == 0 || edata); - - /* open a file descriptor (or use the one provided). */ - if ( inout_fd - && *inout_fd >= 0) - fd = *inout_fd; - else { - fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (fd < 0) { - r = -NM_ERRNO_NATIVE (errno); - failure_reason = "failed creating socket or ioctl"; - goto out; - } - if (inout_fd) - *inout_fd = fd; - else - fd_close = fd; - } - - /* resolve the ifindex to name (or use the one provided). */ - if ( inout_ifname - && inout_ifname[0]) - nm_utils_ifname_cpy (known_ifnames[0], inout_ifname); - else { - if (!nmp_utils_if_indextoname (ifindex, known_ifnames[0])) { - failure_reason = "cannot resolve ifindex"; - r = -ENODEV; - goto out; - } - if (inout_ifname) - nm_utils_ifname_cpy (inout_ifname, known_ifnames[0]); - } - - /* we might need to retry the request. Backup edata so that we can - * restore it on retry. */ - if (edata_size > 0) - edata_backup = nm_memdup_maybe_a (500, edata, edata_size, &edata_backup_free); - - try_count = 0; + nm_auto_close int fd_close = -1; + int fd; + int r; + gpointer edata_backup = NULL; + gs_free gpointer edata_backup_free = NULL; + guint try_count; + char known_ifnames[2][IFNAMSIZ]; + const char * failure_reason = NULL; + struct ifreq ifr; + + nm_assert(ifindex > 0); + nm_assert(NM_IN_SET(edata_type, + IOCTL_CALL_DATA_TYPE_NONE, + IOCTL_CALL_DATA_TYPE_IFRDATA, + IOCTL_CALL_DATA_TYPE_IFRU)); + nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_NONE || edata_size == 0); + nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_IFRDATA || edata_size > 0); + nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_IFRU + || (edata_size > 0 && edata_size <= sizeof(ifr.ifr_ifru))); + nm_assert(edata_size == 0 || edata); + + /* open a file descriptor (or use the one provided). */ + if (inout_fd && *inout_fd >= 0) + fd = *inout_fd; + else { + fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + r = -NM_ERRNO_NATIVE(errno); + failure_reason = "failed creating socket or ioctl"; + goto out; + } + if (inout_fd) + *inout_fd = fd; + else + fd_close = fd; + } + + /* resolve the ifindex to name (or use the one provided). */ + if (inout_ifname && inout_ifname[0]) + nm_utils_ifname_cpy(known_ifnames[0], inout_ifname); + else { + if (!nmp_utils_if_indextoname(ifindex, known_ifnames[0])) { + failure_reason = "cannot resolve ifindex"; + r = -ENODEV; + goto out; + } + if (inout_ifname) + nm_utils_ifname_cpy(inout_ifname, known_ifnames[0]); + } + + /* we might need to retry the request. Backup edata so that we can + * restore it on retry. */ + if (edata_size > 0) + edata_backup = nm_memdup_maybe_a(500, edata, edata_size, &edata_backup_free); + + try_count = 0; again: - { - const char *ifname = known_ifnames[try_count % 2]; - - nm_assert (ifindex > 0); - nm_assert (ifname && nm_utils_ifname_valid_kernel (ifname, NULL)); - nm_assert (fd >= 0); - - memset (&ifr, 0, sizeof (ifr)); - nm_utils_ifname_cpy (ifr.ifr_name, ifname); - if (edata_type == IOCTL_CALL_DATA_TYPE_IFRDATA) - ifr.ifr_data = edata; - else if (edata_type == IOCTL_CALL_DATA_TYPE_IFRU) - memcpy (&ifr.ifr_ifru, edata, NM_MIN (edata_size, sizeof (ifr.ifr_ifru))); - - if (ioctl (fd, ioctl_request, &ifr) < 0) { - r = -NM_ERRNO_NATIVE (errno); - nm_log_trace (LOGD_PLATFORM, "%s[%d]: %s, %s: failed: %s", - log_ioctl_type, - ifindex, - log_subtype, - ifname, - nm_strerror_native (-r)); - } else { - r = 0; - nm_log_trace (LOGD_PLATFORM, "%s[%d]: %s, %s: success", - log_ioctl_type, - ifindex, - log_subtype, - ifname); - } - } - - try_count++; - - /* resolve the name again to see whether the ifindex still has the same name. */ - if (!nmp_utils_if_indextoname (ifindex, known_ifnames[try_count % 2])) { - /* we could not find the ifindex again. Probably the device just got - * removed. - * - * In both cases we return the error code we got from ioctl above. - * Either it failed because the device was gone already or it still - * managed to complete the call. In both cases, the error code is good. */ - failure_reason = "cannot resolve ifindex after ioctl call. Probably the device was just removed"; - goto out; - } - - /* check whether the ifname changed in the meantime. If yes, would render the result - * invalid. Note that this cannot detect every race regarding renames, for example: - * - * - if_indextoname(#10) gives eth0 - * - rename(#10) => eth0_tmp - * - rename(#11) => eth0 - * - ioctl(eth0) (wrongly fetching #11, formerly eth1) - * - rename(#11) => eth_something - * - rename(#10) => eth0 - * - if_indextoname(#10) gives eth0 - */ - if (!nm_streq (known_ifnames[0], known_ifnames[1])) { - gboolean retry; - - /* we detected a possible(!) rename. - * - * For getters it's straight forward to just retry the call. - * - * For setters we also always retry. If our previous call operated on the right device, - * calling it again should have no bad effect (just setting the same thing more than once). - * - * The only potential bad thing is if there was a race involving swapping names, and we just - * set the ioctl option on the wrong device. But then the bad thing already happend and - * we cannot detect it (nor do anything about it). At least, we can retry and set the - * option on the right interface. */ - retry = (try_count < 5); - - nm_log_trace (LOGD_PLATFORM, "%s[%d]: %s: rename detected from \"%s\" to \"%s\". %s", - log_ioctl_type, - ifindex, - log_subtype, - known_ifnames[(try_count - 1) % 2], - known_ifnames[ try_count % 2], - retry - ? "Retry" - : "No retry"); - if (inout_ifname) - nm_utils_ifname_cpy (inout_ifname, known_ifnames[try_count % 2]); - if (retry) { - if (edata_size > 0) - memcpy (edata, edata_backup, edata_size); - goto again; - } - } +{ + const char *ifname = known_ifnames[try_count % 2]; + + nm_assert(ifindex > 0); + nm_assert(ifname && nm_utils_ifname_valid_kernel(ifname, NULL)); + nm_assert(fd >= 0); + + memset(&ifr, 0, sizeof(ifr)); + nm_utils_ifname_cpy(ifr.ifr_name, ifname); + if (edata_type == IOCTL_CALL_DATA_TYPE_IFRDATA) + ifr.ifr_data = edata; + else if (edata_type == IOCTL_CALL_DATA_TYPE_IFRU) + memcpy(&ifr.ifr_ifru, edata, NM_MIN(edata_size, sizeof(ifr.ifr_ifru))); + + if (ioctl(fd, ioctl_request, &ifr) < 0) { + r = -NM_ERRNO_NATIVE(errno); + nm_log_trace(LOGD_PLATFORM, + "%s[%d]: %s, %s: failed: %s", + log_ioctl_type, + ifindex, + log_subtype, + ifname, + nm_strerror_native(-r)); + } else { + r = 0; + nm_log_trace(LOGD_PLATFORM, + "%s[%d]: %s, %s: success", + log_ioctl_type, + ifindex, + log_subtype, + ifname); + } +} + + try_count++; + + /* resolve the name again to see whether the ifindex still has the same name. */ + if (!nmp_utils_if_indextoname(ifindex, known_ifnames[try_count % 2])) { + /* we could not find the ifindex again. Probably the device just got + * removed. + * + * In both cases we return the error code we got from ioctl above. + * Either it failed because the device was gone already or it still + * managed to complete the call. In both cases, the error code is good. */ + failure_reason = + "cannot resolve ifindex after ioctl call. Probably the device was just removed"; + goto out; + } + + /* check whether the ifname changed in the meantime. If yes, would render the result + * invalid. Note that this cannot detect every race regarding renames, for example: + * + * - if_indextoname(#10) gives eth0 + * - rename(#10) => eth0_tmp + * - rename(#11) => eth0 + * - ioctl(eth0) (wrongly fetching #11, formerly eth1) + * - rename(#11) => eth_something + * - rename(#10) => eth0 + * - if_indextoname(#10) gives eth0 + */ + if (!nm_streq(known_ifnames[0], known_ifnames[1])) { + gboolean retry; + + /* we detected a possible(!) rename. + * + * For getters it's straight forward to just retry the call. + * + * For setters we also always retry. If our previous call operated on the right device, + * calling it again should have no bad effect (just setting the same thing more than once). + * + * The only potential bad thing is if there was a race involving swapping names, and we just + * set the ioctl option on the wrong device. But then the bad thing already happenned and + * we cannot detect it (nor do anything about it). At least, we can retry and set the + * option on the right interface. */ + retry = (try_count < 5); + + nm_log_trace(LOGD_PLATFORM, + "%s[%d]: %s: rename detected from \"%s\" to \"%s\". %s", + log_ioctl_type, + ifindex, + log_subtype, + known_ifnames[(try_count - 1) % 2], + known_ifnames[try_count % 2], + retry ? "Retry" : "No retry"); + if (inout_ifname) + nm_utils_ifname_cpy(inout_ifname, known_ifnames[try_count % 2]); + if (retry) { + if (edata_size > 0) + memcpy(edata, edata_backup, edata_size); + goto again; + } + } out: - if (failure_reason) { - nm_log_trace (LOGD_PLATFORM, "%s[%d]: %s: %s: %s", - log_ioctl_type, - ifindex, - log_subtype, - failure_reason, - r < 0 - ? nm_strerror_native (-r) - : "assume success"); - } - if (r >= 0) - NM_SET_OUT (out_ifreq, ifr); - return r; + if (failure_reason) { + nm_log_trace(LOGD_PLATFORM, + "%s[%d]: %s: %s: %s", + log_ioctl_type, + ifindex, + log_subtype, + failure_reason, + r < 0 ? nm_strerror_native(-r) : "assume success"); + } + if (r >= 0) + NM_SET_OUT(out_ifreq, ifr); + return r; } /****************************************************************************** * ethtool *****************************************************************************/ -static -NM_UTILS_ENUM2STR_DEFINE (_ethtool_cmd_to_string, guint32, - NM_UTILS_ENUM2STR (ETHTOOL_GCOALESCE, "ETHTOOL_GCOALESCE"), - NM_UTILS_ENUM2STR (ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"), - NM_UTILS_ENUM2STR (ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"), - NM_UTILS_ENUM2STR (ETHTOOL_GLINK, "ETHTOOL_GLINK"), - NM_UTILS_ENUM2STR (ETHTOOL_GPERMADDR, "ETHTOOL_GPERMADDR"), - NM_UTILS_ENUM2STR (ETHTOOL_GRINGPARAM, "ETHTOOL_GRINGPARAM"), - NM_UTILS_ENUM2STR (ETHTOOL_GSET, "ETHTOOL_GSET"), - NM_UTILS_ENUM2STR (ETHTOOL_GSSET_INFO, "ETHTOOL_GSSET_INFO"), - NM_UTILS_ENUM2STR (ETHTOOL_GSTATS, "ETHTOOL_GSTATS"), - NM_UTILS_ENUM2STR (ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS"), - NM_UTILS_ENUM2STR (ETHTOOL_GWOL, "ETHTOOL_GWOL"), - NM_UTILS_ENUM2STR (ETHTOOL_SCOALESCE, "ETHTOOL_SCOALESCE"), - NM_UTILS_ENUM2STR (ETHTOOL_SFEATURES, "ETHTOOL_SFEATURES"), - NM_UTILS_ENUM2STR (ETHTOOL_SRINGPARAM, "ETHTOOL_SRINGPARAM"), - NM_UTILS_ENUM2STR (ETHTOOL_SSET, "ETHTOOL_SSET"), - NM_UTILS_ENUM2STR (ETHTOOL_SWOL, "ETHTOOL_SWOL"), -); +static NM_UTILS_ENUM2STR_DEFINE(_ethtool_cmd_to_string, + guint32, + NM_UTILS_ENUM2STR(ETHTOOL_GCOALESCE, "ETHTOOL_GCOALESCE"), + NM_UTILS_ENUM2STR(ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"), + NM_UTILS_ENUM2STR(ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"), + NM_UTILS_ENUM2STR(ETHTOOL_GLINK, "ETHTOOL_GLINK"), + NM_UTILS_ENUM2STR(ETHTOOL_GPERMADDR, "ETHTOOL_GPERMADDR"), + NM_UTILS_ENUM2STR(ETHTOOL_GRINGPARAM, "ETHTOOL_GRINGPARAM"), + NM_UTILS_ENUM2STR(ETHTOOL_GSET, "ETHTOOL_GSET"), + NM_UTILS_ENUM2STR(ETHTOOL_GSSET_INFO, "ETHTOOL_GSSET_INFO"), + NM_UTILS_ENUM2STR(ETHTOOL_GSTATS, "ETHTOOL_GSTATS"), + NM_UTILS_ENUM2STR(ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS"), + NM_UTILS_ENUM2STR(ETHTOOL_GWOL, "ETHTOOL_GWOL"), + NM_UTILS_ENUM2STR(ETHTOOL_SCOALESCE, "ETHTOOL_SCOALESCE"), + NM_UTILS_ENUM2STR(ETHTOOL_SFEATURES, "ETHTOOL_SFEATURES"), + NM_UTILS_ENUM2STR(ETHTOOL_SRINGPARAM, "ETHTOOL_SRINGPARAM"), + NM_UTILS_ENUM2STR(ETHTOOL_SSET, "ETHTOOL_SSET"), + NM_UTILS_ENUM2STR(ETHTOOL_SWOL, "ETHTOOL_SWOL"), ); static const char * -_ethtool_edata_to_string (gpointer edata, gsize edata_size, char *sbuf, gsize sbuf_len) +_ethtool_edata_to_string(gpointer edata, gsize edata_size, char *sbuf, gsize sbuf_len) { - nm_assert (edata); - nm_assert (edata_size >= sizeof (guint32)); - nm_assert ((((intptr_t) edata) % _nm_alignof (guint32)) == 0); + nm_assert(edata); + nm_assert(edata_size >= sizeof(guint32)); + nm_assert((((intptr_t) edata) % _nm_alignof(guint32)) == 0); - return _ethtool_cmd_to_string (*((guint32 *) edata), sbuf, sbuf_len); + return _ethtool_cmd_to_string(*((guint32 *) edata), sbuf, sbuf_len); } /*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -#define ethtool_cmd_speed(pedata) ((pedata)->speed) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) + #define ethtool_cmd_speed(pedata) ((pedata)->speed) -#define ethtool_cmd_speed_set(pedata, speed) \ - G_STMT_START { (pedata)->speed = (guint16) (speed); } G_STMT_END + #define ethtool_cmd_speed_set(pedata, speed) \ + G_STMT_START \ + { \ + (pedata)->speed = (guint16)(speed); \ + } \ + G_STMT_END #endif static int -_ethtool_call_handle (SocketHandle *shandle, gpointer edata, gsize edata_size) +_ethtool_call_handle(SocketHandle *shandle, gpointer edata, gsize edata_size) { - char sbuf[50]; - - return _ioctl_call ("ethtool", - _ethtool_edata_to_string (edata, edata_size, sbuf, sizeof (sbuf)), - SIOCETHTOOL, - shandle->ifindex, - &shandle->fd, - shandle->ifname, - IOCTL_CALL_DATA_TYPE_IFRDATA, - edata, - edata_size, - NULL); + char sbuf[50]; + + return _ioctl_call("ethtool", + _ethtool_edata_to_string(edata, edata_size, sbuf, sizeof(sbuf)), + SIOCETHTOOL, + shandle->ifindex, + &shandle->fd, + shandle->ifname, + IOCTL_CALL_DATA_TYPE_IFRDATA, + edata, + edata_size, + NULL); } static int -_ethtool_call_once (int ifindex, gpointer edata, gsize edata_size) +_ethtool_call_once(int ifindex, gpointer edata, gsize edata_size) { - char sbuf[50]; - - return _ioctl_call ("ethtool", - _ethtool_edata_to_string (edata, edata_size, sbuf, sizeof (sbuf)), - SIOCETHTOOL, - ifindex, - NULL, - NULL, - IOCTL_CALL_DATA_TYPE_IFRDATA, - edata, - edata_size, - NULL); + char sbuf[50]; + + return _ioctl_call("ethtool", + _ethtool_edata_to_string(edata, edata_size, sbuf, sizeof(sbuf)), + SIOCETHTOOL, + ifindex, + NULL, + NULL, + IOCTL_CALL_DATA_TYPE_IFRDATA, + edata, + edata_size, + NULL); } /*****************************************************************************/ static struct ethtool_gstrings * -ethtool_get_stringset (SocketHandle *shandle, int stringset_id) +ethtool_get_stringset(SocketHandle *shandle, int stringset_id) { - struct { - struct ethtool_sset_info info; - guint32 sentinel; - } sset_info = { - .info.cmd = ETHTOOL_GSSET_INFO, - .info.reserved = 0, - .info.sset_mask = (1ULL << stringset_id), - }; - const guint32 *pdata; - gs_free struct ethtool_gstrings *gstrings = NULL; - gsize gstrings_len; - guint32 i, len; - - if (_ethtool_call_handle (shandle, &sset_info, sizeof (sset_info)) < 0) - return NULL; - if (!sset_info.info.sset_mask) - return NULL; - - pdata = (guint32 *) sset_info.info.data; - - len = *pdata; - - gstrings_len = sizeof (*gstrings) + (len * ETH_GSTRING_LEN); - gstrings = g_malloc0 (gstrings_len); - gstrings->cmd = ETHTOOL_GSTRINGS; - gstrings->string_set = stringset_id; - gstrings->len = len; - if (gstrings->len > 0) { - if (_ethtool_call_handle (shandle, gstrings, gstrings_len) < 0) - return NULL; - for (i = 0; i < gstrings->len; i++) { - /* ensure NUL terminated */ - gstrings->data[i * ETH_GSTRING_LEN + (ETH_GSTRING_LEN - 1)] = '\0'; - } - } - - return g_steal_pointer (&gstrings); + struct { + struct ethtool_sset_info info; + guint32 sentinel; + } sset_info = { + .info.cmd = ETHTOOL_GSSET_INFO, + .info.reserved = 0, + .info.sset_mask = (1ULL << stringset_id), + }; + const guint32 * pdata; + gs_free struct ethtool_gstrings *gstrings = NULL; + gsize gstrings_len; + guint32 i, len; + + if (_ethtool_call_handle(shandle, &sset_info, sizeof(sset_info)) < 0) + return NULL; + if (!sset_info.info.sset_mask) + return NULL; + + pdata = (guint32 *) sset_info.info.data; + + len = *pdata; + + gstrings_len = sizeof(*gstrings) + (len * ETH_GSTRING_LEN); + gstrings = g_malloc0(gstrings_len); + gstrings->cmd = ETHTOOL_GSTRINGS; + gstrings->string_set = stringset_id; + gstrings->len = len; + if (gstrings->len > 0) { + if (_ethtool_call_handle(shandle, gstrings, gstrings_len) < 0) + return NULL; + for (i = 0; i < gstrings->len; i++) { + /* ensure NUL terminated */ + gstrings->data[i * ETH_GSTRING_LEN + (ETH_GSTRING_LEN - 1)] = '\0'; + } + } + + return g_steal_pointer(&gstrings); } static int -ethtool_gstrings_find (const struct ethtool_gstrings *gstrings, const char *needle) +ethtool_gstrings_find(const struct ethtool_gstrings *gstrings, const char *needle) { - guint32 i; + guint32 i; - /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. - * that means, we cannot possibly request longer names. */ - nm_assert (needle && strlen (needle) < ETH_GSTRING_LEN); + /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. + * that means, we cannot possibly request longer names. */ + nm_assert(needle && strlen(needle) < ETH_GSTRING_LEN); - for (i = 0; i < gstrings->len; i++) { - if (nm_streq ((char *) &gstrings->data[i * ETH_GSTRING_LEN], needle)) - return i; - } - return -1; + for (i = 0; i < gstrings->len; i++) { + if (nm_streq((char *) &gstrings->data[i * ETH_GSTRING_LEN], needle)) + return i; + } + return -1; } static int -ethtool_get_stringset_index (SocketHandle *shandle, int stringset_id, const char *needle) +ethtool_get_stringset_index(SocketHandle *shandle, int stringset_id, const char *needle) { - gs_free struct ethtool_gstrings *gstrings = NULL; + gs_free struct ethtool_gstrings *gstrings = NULL; - /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. - * that means, we cannot possibly request longer names. */ - nm_assert (needle && strlen (needle) < ETH_GSTRING_LEN); + /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. + * that means, we cannot possibly request longer names. */ + nm_assert(needle && strlen(needle) < ETH_GSTRING_LEN); - gstrings = ethtool_get_stringset (shandle, stringset_id); - if (gstrings) - return ethtool_gstrings_find (gstrings, needle); - return -1; + gstrings = ethtool_get_stringset(shandle, stringset_id); + if (gstrings) + return ethtool_gstrings_find(gstrings, needle); + return -1; } /*****************************************************************************/ static const NMEthtoolFeatureInfo _ethtool_feature_infos[_NM_ETHTOOL_ID_FEATURE_NUM] = { -#define ETHT_FEAT(eid, ...) \ - { \ - .ethtool_id = eid, \ - .n_kernel_names = NM_NARG (__VA_ARGS__), \ - .kernel_names = ((const char *const[]) { __VA_ARGS__ }), \ - } - - /* the order does only matter for one thing: if it happens that more than one NMEthtoolID - * reference the same kernel-name, then the one that is mentioned *later* will win in - * case these NMEthtoolIDs are set. That mostly only makes sense for ethtool-ids which - * refer to multiple features ("feature-tso"), while also having more specific ids - * ("feature-tx-tcp-segmentation"). */ - - /* names from ethtool utility, which are aliases for multiple features. */ - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_SG, "tx-scatter-gather", - "tx-scatter-gather-fraglist"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TSO, "tx-tcp-segmentation", - "tx-tcp-ecn-segmentation", - "tx-tcp-mangleid-segmentation", - "tx-tcp6-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX, "tx-checksum-ipv4", - "tx-checksum-ip-generic", - "tx-checksum-ipv6", - "tx-checksum-fcoe-crc", - "tx-checksum-sctp"), - - /* names from ethtool utility, which are aliases for one feature. */ - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert"), - - /* names of features, as known by kernel. */ - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_HIGHDMA, "highdma"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, "hw-tc-offload"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, "tx-checksum-fcoe-crc"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, "tx-checksum-ipv4"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, "tx-checksum-ipv6"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, "tx-checksum-ip-generic"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, "tx-checksum-sctp"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, "tx-esp-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, "tx-ipxip6-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, "tx-nocache-copy"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, "tx-scatter-gather"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, "tx-scatter-gather-fraglist"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, "tx-sctp-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, "tx-tcp6-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), - ETHT_FEAT (NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), +#define ETHT_FEAT(eid, ...) \ + { \ + .ethtool_id = eid, .n_kernel_names = NM_NARG(__VA_ARGS__), \ + .kernel_names = ((const char *const[]){__VA_ARGS__}), \ + } + + /* the order does only matter for one thing: if it happens that more than one NMEthtoolID + * reference the same kernel-name, then the one that is mentioned *later* will win in + * case these NMEthtoolIDs are set. That mostly only makes sense for ethtool-ids which + * refer to multiple features ("feature-tso"), while also having more specific ids + * ("feature-tx-tcp-segmentation"). */ + + /* names from ethtool utility, which are aliases for multiple features. */ + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_SG, "tx-scatter-gather", "tx-scatter-gather-fraglist"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TSO, + "tx-tcp-segmentation", + "tx-tcp-ecn-segmentation", + "tx-tcp-mangleid-segmentation", + "tx-tcp6-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX, + "tx-checksum-ipv4", + "tx-checksum-ip-generic", + "tx-checksum-ipv6", + "tx-checksum-fcoe-crc", + "tx-checksum-sctp"), + + /* names from ethtool utility, which are aliases for one feature. */ + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert"), + + /* names of features, as known by kernel. */ + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_HIGHDMA, "highdma"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, "hw-tc-offload"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, "tx-checksum-fcoe-crc"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, "tx-checksum-ipv4"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, "tx-checksum-ipv6"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, "tx-checksum-ip-generic"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, "tx-checksum-sctp"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, "tx-esp-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, "tx-ipxip6-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, "tx-nocache-copy"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, "tx-scatter-gather"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, "tx-scatter-gather-fraglist"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, "tx-sctp-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, "tx-tcp6-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), + ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), }; /* the number of kernel features that we handle. It essentially is the sum of all @@ -500,886 +503,953 @@ static const NMEthtoolFeatureInfo _ethtool_feature_infos[_NM_ETHTOOL_ID_FEATURE_ #define N_ETHTOOL_KERNEL_FEATURES (((guint) _NM_ETHTOOL_ID_FEATURE_NUM) + 8u) static void -_ASSERT_ethtool_feature_infos (void) +_ASSERT_ethtool_feature_infos(void) { #if NM_MORE_ASSERTS > 10 - guint i, k, n; - bool found[_NM_ETHTOOL_ID_FEATURE_NUM] = { }; + guint i, k, n; + bool found[_NM_ETHTOOL_ID_FEATURE_NUM] = {}; - G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (_ethtool_feature_infos) == _NM_ETHTOOL_ID_FEATURE_NUM); + G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(_ethtool_feature_infos) == _NM_ETHTOOL_ID_FEATURE_NUM); - n = 0; - for (i = 0; i < G_N_ELEMENTS (_ethtool_feature_infos); i++) { - NMEthtoolFeatureState kstate; - const NMEthtoolFeatureInfo *inf = &_ethtool_feature_infos[i]; + n = 0; + for (i = 0; i < G_N_ELEMENTS(_ethtool_feature_infos); i++) { + NMEthtoolFeatureState kstate; + const NMEthtoolFeatureInfo *inf = &_ethtool_feature_infos[i]; - g_assert (inf->ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST); - g_assert (inf->ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST); - g_assert (inf->n_kernel_names > 0); + g_assert(inf->ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST); + g_assert(inf->ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST); + g_assert(inf->n_kernel_names > 0); - for (k = 0; k < i; k++) - g_assert (inf->ethtool_id != _ethtool_feature_infos[k].ethtool_id); + for (k = 0; k < i; k++) + g_assert(inf->ethtool_id != _ethtool_feature_infos[k].ethtool_id); - g_assert (!found[_NM_ETHTOOL_ID_FEATURE_AS_IDX (inf->ethtool_id)]); - found[_NM_ETHTOOL_ID_FEATURE_AS_IDX (inf->ethtool_id)] = TRUE; + g_assert(!found[_NM_ETHTOOL_ID_FEATURE_AS_IDX(inf->ethtool_id)]); + found[_NM_ETHTOOL_ID_FEATURE_AS_IDX(inf->ethtool_id)] = TRUE; - kstate.idx_kernel_name = inf->n_kernel_names - 1; - g_assert ((guint) kstate.idx_kernel_name == (guint) (inf->n_kernel_names - 1)); + kstate.idx_kernel_name = inf->n_kernel_names - 1; + g_assert((guint) kstate.idx_kernel_name == (guint)(inf->n_kernel_names - 1)); - n += inf->n_kernel_names; - for (k = 0; k < inf->n_kernel_names; k++) { - g_assert (nm_utils_strv_find_first ((char **) inf->kernel_names, - k, - inf->kernel_names[k]) < 0); - } - } + n += inf->n_kernel_names; + for (k = 0; k < inf->n_kernel_names; k++) { + g_assert(nm_utils_strv_find_first((char **) inf->kernel_names, k, inf->kernel_names[k]) + < 0); + } + } - for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) - g_assert (found[i]); + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) + g_assert(found[i]); - g_assert (n == N_ETHTOOL_KERNEL_FEATURES); + g_assert(n == N_ETHTOOL_KERNEL_FEATURES); #endif } static NMEthtoolFeatureStates * -ethtool_get_features (SocketHandle *shandle) +ethtool_get_features(SocketHandle *shandle) { - gs_free NMEthtoolFeatureStates *states = NULL; - gs_free struct ethtool_gstrings *ss_features = NULL; - - _ASSERT_ethtool_feature_infos (); - - ss_features = ethtool_get_stringset (shandle, ETH_SS_FEATURES); - if (!ss_features) - return NULL; - - if (ss_features->len > 0) { - gs_free struct ethtool_gfeatures *gfeatures_free = NULL; - struct ethtool_gfeatures *gfeatures; - gsize gfeatures_len; - guint idx; - const NMEthtoolFeatureState *states_list0 = NULL; - const NMEthtoolFeatureState *const*states_plist0 = NULL; - guint states_plist_n = 0; - - gfeatures_len = sizeof (struct ethtool_gfeatures) - + (NM_DIV_ROUND_UP (ss_features->len, 32u) * sizeof(gfeatures->features[0])); - gfeatures = nm_malloc0_maybe_a (300, gfeatures_len, &gfeatures_free); - gfeatures->cmd = ETHTOOL_GFEATURES; - gfeatures->size = NM_DIV_ROUND_UP (ss_features->len, 32u); - if (_ethtool_call_handle (shandle, gfeatures, gfeatures_len) < 0) - return NULL; - - for (idx = 0; idx < G_N_ELEMENTS (_ethtool_feature_infos); idx++) { - const NMEthtoolFeatureInfo *info = &_ethtool_feature_infos[idx]; - guint idx_kernel_name; - - for (idx_kernel_name = 0; idx_kernel_name < info->n_kernel_names; idx_kernel_name++) { - NMEthtoolFeatureState *kstate; - const char *kernel_name = info->kernel_names[idx_kernel_name]; - int i_feature; - guint i_block; - guint32 i_flag; - - i_feature = ethtool_gstrings_find (ss_features, kernel_name); - if (i_feature < 0) - continue; - - i_block = ((guint) i_feature) / 32u; - i_flag = (guint32) (1u << (((guint) i_feature) % 32u)); - - if (!states) { - states = g_malloc0 (sizeof (NMEthtoolFeatureStates) - + (N_ETHTOOL_KERNEL_FEATURES * sizeof (NMEthtoolFeatureState)) - + ((N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS (_ethtool_feature_infos)) * sizeof (NMEthtoolFeatureState *))); - states_list0 = &states->states_list[0]; - states_plist0 = (gpointer) &states_list0[N_ETHTOOL_KERNEL_FEATURES]; - states->n_ss_features = ss_features->len; - } - - nm_assert (states->n_states < N_ETHTOOL_KERNEL_FEATURES); - kstate = (NMEthtoolFeatureState *) &states_list0[states->n_states]; - states->n_states++; - - kstate->info = info; - kstate->idx_ss_features = i_feature; - kstate->idx_kernel_name = idx_kernel_name; - kstate->available = !!(gfeatures->features[i_block].available & i_flag); - kstate->requested = !!(gfeatures->features[i_block].requested & i_flag); - kstate->active = !!(gfeatures->features[i_block].active & i_flag); - kstate->never_changed = !!(gfeatures->features[i_block].never_changed & i_flag); - - nm_assert (states_plist_n < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS (_ethtool_feature_infos)); - - if (!states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX (info->ethtool_id)]) - states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX (info->ethtool_id)] = &states_plist0[states_plist_n]; - ((const NMEthtoolFeatureState **) states_plist0)[states_plist_n] = kstate; - states_plist_n++; - } - - if (states && states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX (info->ethtool_id)]) { - nm_assert (states_plist_n < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS (_ethtool_feature_infos)); - nm_assert (!states_plist0[states_plist_n]); - states_plist_n++; - } - } - } - - return g_steal_pointer (&states); + gs_free NMEthtoolFeatureStates * states = NULL; + gs_free struct ethtool_gstrings *ss_features = NULL; + + _ASSERT_ethtool_feature_infos(); + + ss_features = ethtool_get_stringset(shandle, ETH_SS_FEATURES); + if (!ss_features) + return NULL; + + if (ss_features->len > 0) { + gs_free struct ethtool_gfeatures * gfeatures_free = NULL; + struct ethtool_gfeatures * gfeatures; + gsize gfeatures_len; + guint idx; + const NMEthtoolFeatureState * states_list0 = NULL; + const NMEthtoolFeatureState *const *states_plist0 = NULL; + guint states_plist_n = 0; + + gfeatures_len = sizeof(struct ethtool_gfeatures) + + (NM_DIV_ROUND_UP(ss_features->len, 32u) * sizeof(gfeatures->features[0])); + gfeatures = nm_malloc0_maybe_a(300, gfeatures_len, &gfeatures_free); + gfeatures->cmd = ETHTOOL_GFEATURES; + gfeatures->size = NM_DIV_ROUND_UP(ss_features->len, 32u); + if (_ethtool_call_handle(shandle, gfeatures, gfeatures_len) < 0) + return NULL; + + for (idx = 0; idx < G_N_ELEMENTS(_ethtool_feature_infos); idx++) { + const NMEthtoolFeatureInfo *info = &_ethtool_feature_infos[idx]; + guint idx_kernel_name; + + for (idx_kernel_name = 0; idx_kernel_name < info->n_kernel_names; idx_kernel_name++) { + NMEthtoolFeatureState *kstate; + const char * kernel_name = info->kernel_names[idx_kernel_name]; + int i_feature; + guint i_block; + guint32 i_flag; + + i_feature = ethtool_gstrings_find(ss_features, kernel_name); + if (i_feature < 0) + continue; + + i_block = ((guint) i_feature) / 32u; + i_flag = (guint32)(1u << (((guint) i_feature) % 32u)); + + if (!states) { + states = g_malloc0( + sizeof(NMEthtoolFeatureStates) + + (N_ETHTOOL_KERNEL_FEATURES * sizeof(NMEthtoolFeatureState)) + + ((N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos)) + * sizeof(NMEthtoolFeatureState *))); + states_list0 = &states->states_list[0]; + states_plist0 = (gpointer) &states_list0[N_ETHTOOL_KERNEL_FEATURES]; + states->n_ss_features = ss_features->len; + } + + nm_assert(states->n_states < N_ETHTOOL_KERNEL_FEATURES); + kstate = (NMEthtoolFeatureState *) &states_list0[states->n_states]; + states->n_states++; + + kstate->info = info; + kstate->idx_ss_features = i_feature; + kstate->idx_kernel_name = idx_kernel_name; + kstate->available = !!(gfeatures->features[i_block].available & i_flag); + kstate->requested = !!(gfeatures->features[i_block].requested & i_flag); + kstate->active = !!(gfeatures->features[i_block].active & i_flag); + kstate->never_changed = !!(gfeatures->features[i_block].never_changed & i_flag); + + nm_assert(states_plist_n + < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos)); + + if (!states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)]) + states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)] = + &states_plist0[states_plist_n]; + ((const NMEthtoolFeatureState **) states_plist0)[states_plist_n] = kstate; + states_plist_n++; + } + + if (states && states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)]) { + nm_assert(states_plist_n + < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos)); + nm_assert(!states_plist0[states_plist_n]); + states_plist_n++; + } + } + } + + return g_steal_pointer(&states); } NMEthtoolFeatureStates * -nmp_utils_ethtool_get_features (int ifindex) +nmp_utils_ethtool_get_features(int ifindex) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - NMEthtoolFeatureStates *features; - - g_return_val_if_fail (ifindex > 0, 0); - - features = ethtool_get_features (&shandle); - - if (!features) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure getting features", - ifindex, - "get-features"); - return NULL; - } - - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: retrieved kernel features", - ifindex, - "get-features"); - return features; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + NMEthtoolFeatureStates * features; + + g_return_val_if_fail(ifindex > 0, 0); + + features = ethtool_get_features(&shandle); + + if (!features) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting features", + ifindex, + "get-features"); + return NULL; + } + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: retrieved kernel features", + ifindex, + "get-features"); + return features; } static const char * -_ethtool_feature_state_to_string (char *buf, gsize buf_size, const NMEthtoolFeatureState *s, const char *prefix) +_ethtool_feature_state_to_string(char * buf, + gsize buf_size, + const NMEthtoolFeatureState *s, + const char * prefix) { - int l; - - l = g_snprintf (buf, buf_size, - "%s %s%s", - prefix ?: "", - ONOFF (s->active), - (!s->available || s->never_changed) - ? ", [fixed]" - : ((s->requested != s->active) - ? (s->requested ? ", [requested on]" : ", [requested off]") - : "")); - nm_assert (l < buf_size); - return buf; + int l; + + l = g_snprintf(buf, + buf_size, + "%s %s%s", + prefix ?: "", + ONOFF(s->active), + (!s->available || s->never_changed) + ? ", [fixed]" + : ((s->requested != s->active) + ? (s->requested ? ", [requested on]" : ", [requested off]") + : "")); + nm_assert(l < buf_size); + return buf; } gboolean -nmp_utils_ethtool_set_features (int ifindex, - const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */) +nmp_utils_ethtool_set_features( + int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - gs_free struct ethtool_sfeatures *sfeatures_free = NULL; - struct ethtool_sfeatures *sfeatures; - gsize sfeatures_len; - int r; - guint i, j; - struct { - const NMEthtoolFeatureState *f_state; - NMTernary requested; - } set_states[N_ETHTOOL_KERNEL_FEATURES]; - guint set_states_n = 0; - gboolean success = TRUE; - - g_return_val_if_fail (ifindex > 0, 0); - g_return_val_if_fail (features, 0); - g_return_val_if_fail (requested, 0); - - nm_assert (features->n_states <= N_ETHTOOL_KERNEL_FEATURES); - - for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) { - const NMEthtoolFeatureState *const*states_indexed; - - if (requested[i] == NM_TERNARY_DEFAULT) - continue; - - if (!(states_indexed = features->states_indexed[i])) { - if (do_set) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set feature %s: skip (not found)", - ifindex, - "set-features", - nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname); - success = FALSE; - } - continue; - } - - for (j = 0; states_indexed[j]; j++) { - const NMEthtoolFeatureState *s = states_indexed[j]; - char sbuf[255]; - - if (set_states_n >= G_N_ELEMENTS (set_states)) - g_return_val_if_reached (FALSE); - - if (s->never_changed) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s feature %s (%s): %s, %s (skip feature marked as never changed)", - ifindex, - "set-features", - do_set ? "set" : "reset", - nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, - s->info->kernel_names[s->idx_kernel_name], - ONOFF (do_set ? requested[i] == NM_TERNARY_TRUE : s->active), - _ethtool_feature_state_to_string (sbuf, sizeof (sbuf), s, do_set ? " currently:" : " before:")); - continue; - } - - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s feature %s (%s): %s, %s", - ifindex, - "set-features", - do_set ? "set" : "reset", - nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, - s->info->kernel_names[s->idx_kernel_name], - ONOFF (do_set ? requested[i] == NM_TERNARY_TRUE : s->active), - _ethtool_feature_state_to_string (sbuf, sizeof (sbuf), s, do_set ? " currently:" : " before:")); - - if ( do_set - && (!s->available || s->never_changed) - && (s->active != (requested[i] == NM_TERNARY_TRUE))) { - /* we request to change a flag which kernel reported as fixed. - * While the ethtool operation will silently succeed, mark the request - * as failure. */ - success = FALSE; - } - - set_states[set_states_n].f_state = s; - set_states[set_states_n].requested = requested[i]; - set_states_n++; - } - } - - if (set_states_n == 0) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: no feature requested", - ifindex, - "set-features"); - return TRUE; - } - - sfeatures_len = sizeof (struct ethtool_sfeatures) - + (NM_DIV_ROUND_UP (features->n_ss_features, 32U) * sizeof(sfeatures->features[0])); - sfeatures = nm_malloc0_maybe_a (300, sfeatures_len, &sfeatures_free); - sfeatures->cmd = ETHTOOL_SFEATURES; - sfeatures->size = NM_DIV_ROUND_UP (features->n_ss_features, 32U); - - for (i = 0; i < set_states_n; i++) { - const NMEthtoolFeatureState *s = set_states[i].f_state; - guint i_block; - guint32 i_flag; - gboolean is_requested; - - i_block = s->idx_ss_features / 32u; - i_flag = (guint32) (1u << (s->idx_ss_features % 32u)); - - sfeatures->features[i_block].valid |= i_flag; - - if (do_set) - is_requested = (set_states[i].requested == NM_TERNARY_TRUE); - else - is_requested = s->active; - - if (is_requested) - sfeatures->features[i_block].requested |= i_flag; - else - sfeatures->features[i_block].requested &= ~i_flag; - } - - r = _ethtool_call_handle (&shandle, sfeatures, sfeatures_len); - if (r < 0) { - success = FALSE; - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting features (%s)", - ifindex, - "set-features", - nm_strerror_native (-r)); - return FALSE; - } - - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s", - ifindex, - "set-features", - success - ? "successfully setting features" - : "at least some of the features were not successfully set"); - return success; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + gs_free struct ethtool_sfeatures * sfeatures_free = NULL; + struct ethtool_sfeatures * sfeatures; + gsize sfeatures_len; + int r; + guint i, j; + struct { + const NMEthtoolFeatureState *f_state; + NMTernary requested; + } set_states[N_ETHTOOL_KERNEL_FEATURES]; + guint set_states_n = 0; + gboolean success = TRUE; + + g_return_val_if_fail(ifindex > 0, 0); + g_return_val_if_fail(features, 0); + g_return_val_if_fail(requested, 0); + + nm_assert(features->n_states <= N_ETHTOOL_KERNEL_FEATURES); + + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) { + const NMEthtoolFeatureState *const *states_indexed; + + if (requested[i] == NM_TERNARY_DEFAULT) + continue; + + if (!(states_indexed = features->states_indexed[i])) { + if (do_set) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: set feature %s: skip (not found)", + ifindex, + "set-features", + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname); + success = FALSE; + } + continue; + } + + for (j = 0; states_indexed[j]; j++) { + const NMEthtoolFeatureState *s = states_indexed[j]; + char sbuf[255]; + + if (set_states_n >= G_N_ELEMENTS(set_states)) + g_return_val_if_reached(FALSE); + + if (s->never_changed) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: %s feature %s (%s): %s, %s (skip feature marked as " + "never changed)", + ifindex, + "set-features", + do_set ? "set" : "reset", + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, + s->info->kernel_names[s->idx_kernel_name], + ONOFF(do_set ? requested[i] == NM_TERNARY_TRUE : s->active), + _ethtool_feature_state_to_string(sbuf, + sizeof(sbuf), + s, + do_set ? " currently:" : " before:")); + continue; + } + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: %s feature %s (%s): %s, %s", + ifindex, + "set-features", + do_set ? "set" : "reset", + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, + s->info->kernel_names[s->idx_kernel_name], + ONOFF(do_set ? requested[i] == NM_TERNARY_TRUE : s->active), + _ethtool_feature_state_to_string(sbuf, + sizeof(sbuf), + s, + do_set ? " currently:" : " before:")); + + if (do_set && (!s->available || s->never_changed) + && (s->active != (requested[i] == NM_TERNARY_TRUE))) { + /* we request to change a flag which kernel reported as fixed. + * While the ethtool operation will silently succeed, mark the request + * as failure. */ + success = FALSE; + } + + set_states[set_states_n].f_state = s; + set_states[set_states_n].requested = requested[i]; + set_states_n++; + } + } + + if (set_states_n == 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: no feature requested", + ifindex, + "set-features"); + return TRUE; + } + + sfeatures_len = + sizeof(struct ethtool_sfeatures) + + (NM_DIV_ROUND_UP(features->n_ss_features, 32U) * sizeof(sfeatures->features[0])); + sfeatures = nm_malloc0_maybe_a(300, sfeatures_len, &sfeatures_free); + sfeatures->cmd = ETHTOOL_SFEATURES; + sfeatures->size = NM_DIV_ROUND_UP(features->n_ss_features, 32U); + + for (i = 0; i < set_states_n; i++) { + const NMEthtoolFeatureState *s = set_states[i].f_state; + guint i_block; + guint32 i_flag; + gboolean is_requested; + + i_block = s->idx_ss_features / 32u; + i_flag = (guint32)(1u << (s->idx_ss_features % 32u)); + + sfeatures->features[i_block].valid |= i_flag; + + if (do_set) + is_requested = (set_states[i].requested == NM_TERNARY_TRUE); + else + is_requested = s->active; + + if (is_requested) + sfeatures->features[i_block].requested |= i_flag; + else + sfeatures->features[i_block].requested &= ~i_flag; + } + + r = _ethtool_call_handle(&shandle, sfeatures, sfeatures_len); + if (r < 0) { + success = FALSE; + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure setting features (%s)", + ifindex, + "set-features", + nm_strerror_native(-r)); + return FALSE; + } + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: %s", + ifindex, + "set-features", + success ? "successfully setting features" + : "at least some of the features were not successfully set"); + return success; } static gboolean -ethtool_get_coalesce (SocketHandle *shandle, - NMEthtoolCoalesceState *coalesce) +ethtool_get_coalesce(SocketHandle *shandle, NMEthtoolCoalesceState *coalesce) { - struct ethtool_coalesce eth_data; - - eth_data.cmd = ETHTOOL_GCOALESCE; - - if (_ethtool_call_handle (shandle, - ð_data, - sizeof (struct ethtool_coalesce)) != 0) - return FALSE; - - *coalesce = (NMEthtoolCoalesceState) { - .s = { - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS)] = eth_data.rx_coalesce_usecs, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES)] = eth_data.rx_max_coalesced_frames, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)] = eth_data.rx_coalesce_usecs_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)] = eth_data.rx_max_coalesced_frames_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS)] = eth_data.tx_coalesce_usecs, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES)] = eth_data.tx_max_coalesced_frames, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)] = eth_data.tx_coalesce_usecs_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)] = eth_data.tx_max_coalesced_frames_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)] = eth_data.stats_block_coalesce_usecs, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)] = eth_data.use_adaptive_rx_coalesce, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)] = eth_data.use_adaptive_tx_coalesce, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)] = eth_data.pkt_rate_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)] = eth_data.rx_coalesce_usecs_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)] = eth_data.rx_max_coalesced_frames_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)] = eth_data.tx_coalesce_usecs_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)] = eth_data.tx_max_coalesced_frames_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)] = eth_data.pkt_rate_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)] = eth_data.rx_coalesce_usecs_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)] = eth_data.rx_max_coalesced_frames_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)] = eth_data.tx_coalesce_usecs_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)] = eth_data.tx_max_coalesced_frames_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)] = eth_data.rate_sample_interval, - } - }; - return TRUE; + struct ethtool_coalesce eth_data; + + eth_data.cmd = ETHTOOL_GCOALESCE; + + if (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_coalesce)) != 0) + return FALSE; + + *coalesce = (NMEthtoolCoalesceState){ + .s = { + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS)] = + eth_data.rx_coalesce_usecs, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES)] = + eth_data.rx_max_coalesced_frames, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)] = + eth_data.rx_coalesce_usecs_irq, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)] = + eth_data.rx_max_coalesced_frames_irq, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS)] = + eth_data.tx_coalesce_usecs, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES)] = + eth_data.tx_max_coalesced_frames, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)] = + eth_data.tx_coalesce_usecs_irq, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)] = + eth_data.tx_max_coalesced_frames_irq, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)] = + eth_data.stats_block_coalesce_usecs, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)] = + eth_data.use_adaptive_rx_coalesce, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)] = + eth_data.use_adaptive_tx_coalesce, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)] = + eth_data.pkt_rate_low, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)] = + eth_data.rx_coalesce_usecs_low, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)] = + eth_data.rx_max_coalesced_frames_low, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)] = + eth_data.tx_coalesce_usecs_low, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)] = + eth_data.tx_max_coalesced_frames_low, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)] = + eth_data.pkt_rate_high, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)] = + eth_data.rx_coalesce_usecs_high, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)] = + eth_data.rx_max_coalesced_frames_high, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)] = + eth_data.tx_coalesce_usecs_high, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)] = + eth_data.tx_max_coalesced_frames_high, + [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)] = + eth_data.rate_sample_interval, + }}; + return TRUE; } - gboolean -nmp_utils_ethtool_get_coalesce (int ifindex, - NMEthtoolCoalesceState *coalesce) +nmp_utils_ethtool_get_coalesce(int ifindex, NMEthtoolCoalesceState *coalesce) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (coalesce, FALSE); - - if (!ethtool_get_coalesce (&shandle, coalesce)) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure getting coalesce settings", - ifindex, - "get-coalesce"); - return FALSE; - } - - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: retrieved kernel coalesce settings", - ifindex, - "get-coalesce"); - return TRUE; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(coalesce, FALSE); + + if (!ethtool_get_coalesce(&shandle, coalesce)) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting coalesce settings", + ifindex, + "get-coalesce"); + return FALSE; + } + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: retrieved kernel coalesce settings", + ifindex, + "get-coalesce"); + return TRUE; } static gboolean -ethtool_set_coalesce (SocketHandle *shandle, - const NMEthtoolCoalesceState *coalesce) +ethtool_set_coalesce(SocketHandle *shandle, const NMEthtoolCoalesceState *coalesce) { - struct ethtool_coalesce eth_data; - gboolean success; - - nm_assert (shandle); - nm_assert (coalesce); - - eth_data = (struct ethtool_coalesce) { - .cmd = ETHTOOL_SCOALESCE, - .rx_coalesce_usecs = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS)], - .rx_max_coalesced_frames = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES)], - .rx_coalesce_usecs_irq = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)], - .rx_max_coalesced_frames_irq = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)], - .tx_coalesce_usecs = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS)], - .tx_max_coalesced_frames = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES)], - .tx_coalesce_usecs_irq = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)], - .tx_max_coalesced_frames_irq = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)], - .stats_block_coalesce_usecs = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)], - .use_adaptive_rx_coalesce = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)], - .use_adaptive_tx_coalesce = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)], - .pkt_rate_low = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)], - .rx_coalesce_usecs_low = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)], - .rx_max_coalesced_frames_low = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)], - .tx_coalesce_usecs_low = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)], - .tx_max_coalesced_frames_low = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)], - .pkt_rate_high = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)], - .rx_coalesce_usecs_high = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)], - .rx_max_coalesced_frames_high = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)], - .tx_coalesce_usecs_high = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)], - .tx_max_coalesced_frames_high = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)], - .rate_sample_interval = coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX (NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)], - }; - - success = (_ethtool_call_handle (shandle, - ð_data, - sizeof (struct ethtool_coalesce)) == 0); - return success; + struct ethtool_coalesce eth_data; + gboolean success; + + nm_assert(shandle); + nm_assert(coalesce); + + eth_data = (struct ethtool_coalesce){ + .cmd = ETHTOOL_SCOALESCE, + .rx_coalesce_usecs = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS)], + .rx_max_coalesced_frames = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES)], + .rx_coalesce_usecs_irq = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)], + .rx_max_coalesced_frames_irq = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)], + .tx_coalesce_usecs = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS)], + .tx_max_coalesced_frames = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES)], + .tx_coalesce_usecs_irq = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)], + .tx_max_coalesced_frames_irq = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)], + .stats_block_coalesce_usecs = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)], + .use_adaptive_rx_coalesce = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)], + .use_adaptive_tx_coalesce = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)], + .pkt_rate_low = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)], + .rx_coalesce_usecs_low = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)], + .rx_max_coalesced_frames_low = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)], + .tx_coalesce_usecs_low = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)], + .tx_max_coalesced_frames_low = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)], + .pkt_rate_high = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)], + .rx_coalesce_usecs_high = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)], + .rx_max_coalesced_frames_high = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)], + .tx_coalesce_usecs_high = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)], + .tx_max_coalesced_frames_high = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)], + .rate_sample_interval = + coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)], + }; + + success = (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_coalesce)) == 0); + return success; } gboolean -nmp_utils_ethtool_set_coalesce (int ifindex, - const NMEthtoolCoalesceState *coalesce) +nmp_utils_ethtool_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (coalesce, FALSE); - - if (!ethtool_set_coalesce (&shandle, coalesce)) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting coalesce settings", - ifindex, - "set-coalesce"); - return FALSE; - } - - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set kernel coalesce settings", - ifindex, - "set-coalesce"); - return TRUE; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(coalesce, FALSE); + + if (!ethtool_set_coalesce(&shandle, coalesce)) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure setting coalesce settings", + ifindex, + "set-coalesce"); + return FALSE; + } + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: set kernel coalesce settings", + ifindex, + "set-coalesce"); + return TRUE; } static gboolean -ethtool_get_ring (SocketHandle *shandle, - NMEthtoolRingState *ring) +ethtool_get_ring(SocketHandle *shandle, NMEthtoolRingState *ring) { - struct ethtool_ringparam eth_data; + struct ethtool_ringparam eth_data; - eth_data.cmd = ETHTOOL_GRINGPARAM; + eth_data.cmd = ETHTOOL_GRINGPARAM; - if (_ethtool_call_handle (shandle, - ð_data, - sizeof (struct ethtool_ringparam)) != 0) - return FALSE; + if (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_ringparam)) != 0) + return FALSE; - ring->rx_pending = eth_data.rx_pending; - ring->rx_jumbo_pending = eth_data.rx_jumbo_pending; - ring->rx_mini_pending = eth_data.rx_mini_pending; - ring->tx_pending = eth_data.tx_pending; + ring->rx_pending = eth_data.rx_pending; + ring->rx_jumbo_pending = eth_data.rx_jumbo_pending; + ring->rx_mini_pending = eth_data.rx_mini_pending; + ring->tx_pending = eth_data.tx_pending; - return TRUE; + return TRUE; } gboolean -nmp_utils_ethtool_get_ring (int ifindex, - NMEthtoolRingState *ring) +nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (ring, FALSE); - - if (!ethtool_get_ring (&shandle, ring)) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure getting ring settings", - ifindex, - "get-ring"); - return FALSE; - } - - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: retrieved kernel ring settings", - ifindex, - "get-ring"); - return TRUE; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(ring, FALSE); + + if (!ethtool_get_ring(&shandle, ring)) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting ring settings", + ifindex, + "get-ring"); + return FALSE; + } + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: retrieved kernel ring settings", + ifindex, + "get-ring"); + return TRUE; } static gboolean -ethtool_set_ring (SocketHandle *shandle, - const NMEthtoolRingState *ring) +ethtool_set_ring(SocketHandle *shandle, const NMEthtoolRingState *ring) { - gboolean success; - struct ethtool_ringparam eth_data; - - g_return_val_if_fail (shandle, FALSE); - g_return_val_if_fail (ring, FALSE); - - eth_data = (struct ethtool_ringparam) { - .cmd = ETHTOOL_SRINGPARAM, - .rx_pending = ring->rx_pending, - .rx_jumbo_pending = ring->rx_jumbo_pending, - .rx_mini_pending = ring->rx_mini_pending, - .tx_pending = ring->tx_pending, - }; - - success = (_ethtool_call_handle (shandle, - ð_data, - sizeof (struct ethtool_ringparam)) == 0); - return success; + gboolean success; + struct ethtool_ringparam eth_data; + + g_return_val_if_fail(shandle, FALSE); + g_return_val_if_fail(ring, FALSE); + + eth_data = (struct ethtool_ringparam){ + .cmd = ETHTOOL_SRINGPARAM, + .rx_pending = ring->rx_pending, + .rx_jumbo_pending = ring->rx_jumbo_pending, + .rx_mini_pending = ring->rx_mini_pending, + .tx_pending = ring->tx_pending, + }; + + success = (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_ringparam)) == 0); + return success; } gboolean -nmp_utils_ethtool_set_ring (int ifindex, - const NMEthtoolRingState *ring) +nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (ring, FALSE); - - if (!ethtool_set_ring (&shandle, ring)) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting ring settings", - ifindex, - "set-ring"); - return FALSE; - } - - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set kernel ring settings", - ifindex, - "set-ring"); - return TRUE; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(ring, FALSE); + + if (!ethtool_set_ring(&shandle, ring)) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure setting ring settings", + ifindex, + "set-ring"); + return FALSE; + } + + nm_log_trace(LOGD_PLATFORM, "ethtool[%d]: %s: set kernel ring settings", ifindex, "set-ring"); + return TRUE; } /*****************************************************************************/ gboolean -nmp_utils_ethtool_get_driver_info (int ifindex, - NMPUtilsEthtoolDriverInfo *data) +nmp_utils_ethtool_get_driver_info(int ifindex, NMPUtilsEthtoolDriverInfo *data) { - struct ethtool_drvinfo *drvinfo; - - G_STATIC_ASSERT_EXPR (sizeof (*data) == sizeof (*drvinfo)); - G_STATIC_ASSERT_EXPR (offsetof (NMPUtilsEthtoolDriverInfo, driver) == offsetof (struct ethtool_drvinfo, driver)); - G_STATIC_ASSERT_EXPR (offsetof (NMPUtilsEthtoolDriverInfo, version) == offsetof (struct ethtool_drvinfo, version)); - G_STATIC_ASSERT_EXPR (offsetof (NMPUtilsEthtoolDriverInfo, fw_version) == offsetof (struct ethtool_drvinfo, fw_version)); - G_STATIC_ASSERT_EXPR (sizeof (data->driver) == sizeof (drvinfo->driver)); - G_STATIC_ASSERT_EXPR (sizeof (data->version) == sizeof (drvinfo->version)); - G_STATIC_ASSERT_EXPR (sizeof (data->fw_version) == sizeof (drvinfo->fw_version)); - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (data, FALSE); - - drvinfo = (struct ethtool_drvinfo *) data; - *drvinfo = (struct ethtool_drvinfo) { - .cmd = ETHTOOL_GDRVINFO, - }; - return _ethtool_call_once (ifindex, drvinfo, sizeof (*drvinfo)) >= 0; + struct ethtool_drvinfo *drvinfo; + + G_STATIC_ASSERT_EXPR(sizeof(*data) == sizeof(*drvinfo)); + G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, driver) + == offsetof(struct ethtool_drvinfo, driver)); + G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, version) + == offsetof(struct ethtool_drvinfo, version)); + G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, fw_version) + == offsetof(struct ethtool_drvinfo, fw_version)); + G_STATIC_ASSERT_EXPR(sizeof(data->driver) == sizeof(drvinfo->driver)); + G_STATIC_ASSERT_EXPR(sizeof(data->version) == sizeof(drvinfo->version)); + G_STATIC_ASSERT_EXPR(sizeof(data->fw_version) == sizeof(drvinfo->fw_version)); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(data, FALSE); + + drvinfo = (struct ethtool_drvinfo *) data; + *drvinfo = (struct ethtool_drvinfo){ + .cmd = ETHTOOL_GDRVINFO, + }; + return _ethtool_call_once(ifindex, drvinfo, sizeof(*drvinfo)) >= 0; } gboolean -nmp_utils_ethtool_get_permanent_address (int ifindex, - guint8 *buf, - size_t *length) +nmp_utils_ethtool_get_permanent_address(int ifindex, guint8 *buf, size_t *length) { - struct { - struct ethtool_perm_addr e; - guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1]; - } edata = { - .e.cmd = ETHTOOL_GPERMADDR, - .e.size = NM_UTILS_HWADDR_LEN_MAX, - }; - const guint8 *pdata; - - guint i; - - g_return_val_if_fail (ifindex > 0, FALSE); - - if (_ethtool_call_once (ifindex, &edata, sizeof (edata)) < 0) - return FALSE; - - if (edata.e.size > NM_UTILS_HWADDR_LEN_MAX) - return FALSE; - if (edata.e.size < 1) - return FALSE; - - pdata = (const guint8 *) edata.e.data; - - if (NM_IN_SET (pdata[0], 0, 0xFF)) { - /* Some drivers might return a permanent address of all zeros. - * Reject that (rh#1264024) - * - * Some drivers return a permanent address of all ones. Reject that too */ - for (i = 1; i < edata.e.size; i++) { - if (pdata[0] != pdata[i]) - goto not_all_0or1; - } - return FALSE; - } + struct { + struct ethtool_perm_addr e; + guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1]; + } edata = { + .e.cmd = ETHTOOL_GPERMADDR, + .e.size = NM_UTILS_HWADDR_LEN_MAX, + }; + const guint8 *pdata; + + guint i; + + g_return_val_if_fail(ifindex > 0, FALSE); + + if (_ethtool_call_once(ifindex, &edata, sizeof(edata)) < 0) + return FALSE; + + if (edata.e.size > NM_UTILS_HWADDR_LEN_MAX) + return FALSE; + if (edata.e.size < 1) + return FALSE; + + pdata = (const guint8 *) edata.e.data; + + if (NM_IN_SET(pdata[0], 0, 0xFF)) { + /* Some drivers might return a permanent address of all zeros. + * Reject that (rh#1264024) + * + * Some drivers return a permanent address of all ones. Reject that too */ + for (i = 1; i < edata.e.size; i++) { + if (pdata[0] != pdata[i]) + goto not_all_0or1; + } + return FALSE; + } not_all_0or1: - memcpy (buf, pdata, edata.e.size); - *length = edata.e.size; - return TRUE; + memcpy(buf, pdata, edata.e.size); + *length = edata.e.size; + return TRUE; } gboolean -nmp_utils_ethtool_supports_carrier_detect (int ifindex) +nmp_utils_ethtool_supports_carrier_detect(int ifindex) { - struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK }; + struct ethtool_cmd edata = {.cmd = ETHTOOL_GLINK}; - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - /* We ignore the result. If the ETHTOOL_GLINK call succeeded, then we - * assume the device supports carrier-detect, otherwise we assume it - * doesn't. - */ - return _ethtool_call_once (ifindex, &edata, sizeof (edata)) >= 0; + /* We ignore the result. If the ETHTOOL_GLINK call succeeded, then we + * assume the device supports carrier-detect, otherwise we assume it + * doesn't. + */ + return _ethtool_call_once(ifindex, &edata, sizeof(edata)) >= 0; } gboolean -nmp_utils_ethtool_supports_vlans (int ifindex) +nmp_utils_ethtool_supports_vlans(int ifindex) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - gs_free struct ethtool_gfeatures *features_free = NULL; - struct ethtool_gfeatures *features; - gsize features_len; - int idx, block, bit, size; - - g_return_val_if_fail (ifindex > 0, FALSE); - - idx = ethtool_get_stringset_index (&shandle, ETH_SS_FEATURES, "vlan-challenged"); - if (idx < 0) { - nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: vlan-challenged ethtool feature does not exist?", ifindex); - return FALSE; - } - - block = idx / 32; - bit = idx % 32; - size = block + 1; - - features_len = sizeof (*features) - + (size * sizeof (struct ethtool_get_features_block)); - features = nm_malloc0_maybe_a (300, features_len, &features_free); - features->cmd = ETHTOOL_GFEATURES; - features->size = size; - - if (_ethtool_call_handle (&shandle, features, features_len) < 0) - return FALSE; - - return !(features->features[block].active & (1 << bit)); + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + gs_free struct ethtool_gfeatures * features_free = NULL; + struct ethtool_gfeatures * features; + gsize features_len; + int idx, block, bit, size; + + g_return_val_if_fail(ifindex > 0, FALSE); + + idx = ethtool_get_stringset_index(&shandle, ETH_SS_FEATURES, "vlan-challenged"); + if (idx < 0) { + nm_log_dbg(LOGD_PLATFORM, + "ethtool[%d]: vlan-challenged ethtool feature does not exist?", + ifindex); + return FALSE; + } + + block = idx / 32; + bit = idx % 32; + size = block + 1; + + features_len = sizeof(*features) + (size * sizeof(struct ethtool_get_features_block)); + features = nm_malloc0_maybe_a(300, features_len, &features_free); + features->cmd = ETHTOOL_GFEATURES; + features->size = size; + + if (_ethtool_call_handle(&shandle, features, features_len) < 0) + return FALSE; + + return !(features->features[block].active & (1 << bit)); } int -nmp_utils_ethtool_get_peer_ifindex (int ifindex) +nmp_utils_ethtool_get_peer_ifindex(int ifindex) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - gsize stats_len; - gs_free struct ethtool_stats *stats_free = NULL; - struct ethtool_stats *stats; - int peer_ifindex_stat; - - g_return_val_if_fail (ifindex > 0, 0); - - peer_ifindex_stat = ethtool_get_stringset_index (&shandle, ETH_SS_STATS, "peer_ifindex"); - if (peer_ifindex_stat < 0) { - nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: peer_ifindex stat does not exist?", ifindex); - return FALSE; - } - - stats_len = sizeof (*stats) + (peer_ifindex_stat + 1) * sizeof (guint64); - stats = nm_malloc0_maybe_a (300, stats_len, &stats_free); - stats->cmd = ETHTOOL_GSTATS; - stats->n_stats = peer_ifindex_stat + 1; - if (_ethtool_call_handle (&shandle, stats, stats_len) < 0) - return 0; - - return stats->data[peer_ifindex_stat]; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + gsize stats_len; + gs_free struct ethtool_stats * stats_free = NULL; + struct ethtool_stats * stats; + int peer_ifindex_stat; + + g_return_val_if_fail(ifindex > 0, 0); + + peer_ifindex_stat = ethtool_get_stringset_index(&shandle, ETH_SS_STATS, "peer_ifindex"); + if (peer_ifindex_stat < 0) { + nm_log_dbg(LOGD_PLATFORM, "ethtool[%d]: peer_ifindex stat does not exist?", ifindex); + return FALSE; + } + + stats_len = sizeof(*stats) + (peer_ifindex_stat + 1) * sizeof(guint64); + stats = nm_malloc0_maybe_a(300, stats_len, &stats_free); + stats->cmd = ETHTOOL_GSTATS; + stats->n_stats = peer_ifindex_stat + 1; + if (_ethtool_call_handle(&shandle, stats, stats_len) < 0) + return 0; + + return stats->data[peer_ifindex_stat]; } gboolean -nmp_utils_ethtool_get_wake_on_lan (int ifindex) +nmp_utils_ethtool_get_wake_on_lan(int ifindex) { - struct ethtool_wolinfo wol = { - .cmd = ETHTOOL_GWOL, - }; + struct ethtool_wolinfo wol = { + .cmd = ETHTOOL_GWOL, + }; - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - if (_ethtool_call_once (ifindex, &wol, sizeof (wol)) < 0) - return FALSE; + if (_ethtool_call_once(ifindex, &wol, sizeof(wol)) < 0) + return FALSE; - return wol.wolopts != 0; + return wol.wolopts != 0; } gboolean -nmp_utils_ethtool_get_link_settings (int ifindex, - gboolean *out_autoneg, - guint32 *out_speed, - NMPlatformLinkDuplexType *out_duplex) +nmp_utils_ethtool_get_link_settings(int ifindex, + gboolean * out_autoneg, + guint32 * out_speed, + NMPlatformLinkDuplexType *out_duplex) { - struct ethtool_cmd edata = { - .cmd = ETHTOOL_GSET, - }; - - g_return_val_if_fail (ifindex > 0, FALSE); - - if (_ethtool_call_once (ifindex, &edata, sizeof (edata)) < 0) - return FALSE; - - NM_SET_OUT (out_autoneg, (edata.autoneg == AUTONEG_ENABLE)); - - if (out_speed) { - guint32 speed; - - speed = ethtool_cmd_speed (&edata); - if (speed == G_MAXUINT16 || speed == G_MAXUINT32) - speed = 0; - - *out_speed = speed; - } - - if (out_duplex) { - switch (edata.duplex) { - case DUPLEX_HALF: - *out_duplex = NM_PLATFORM_LINK_DUPLEX_HALF; - break; - case DUPLEX_FULL: - *out_duplex = NM_PLATFORM_LINK_DUPLEX_FULL; - break; - default: /* DUPLEX_UNKNOWN */ - *out_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; - break; - } - } - - return TRUE; + struct ethtool_cmd edata = { + .cmd = ETHTOOL_GSET, + }; + + g_return_val_if_fail(ifindex > 0, FALSE); + + if (_ethtool_call_once(ifindex, &edata, sizeof(edata)) < 0) + return FALSE; + + NM_SET_OUT(out_autoneg, (edata.autoneg == AUTONEG_ENABLE)); + + if (out_speed) { + guint32 speed; + + speed = ethtool_cmd_speed(&edata); + if (speed == G_MAXUINT16 || speed == G_MAXUINT32) + speed = 0; + + *out_speed = speed; + } + + if (out_duplex) { + switch (edata.duplex) { + case DUPLEX_HALF: + *out_duplex = NM_PLATFORM_LINK_DUPLEX_HALF; + break; + case DUPLEX_FULL: + *out_duplex = NM_PLATFORM_LINK_DUPLEX_FULL; + break; + default: /* DUPLEX_UNKNOWN */ + *out_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; + break; + } + } + + return TRUE; } - #define ADVERTISED_INVALID 0 -#define BASET_ALL_MODES ( ADVERTISED_10baseT_Half \ - | ADVERTISED_10baseT_Full \ - | ADVERTISED_100baseT_Half \ - | ADVERTISED_100baseT_Full \ - | ADVERTISED_1000baseT_Half \ - | ADVERTISED_1000baseT_Full \ - | ADVERTISED_10000baseT_Full ) +#define BASET_ALL_MODES \ + (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half \ + | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full \ + | ADVERTISED_10000baseT_Full) static guint32 -get_baset_mode (guint32 speed, NMPlatformLinkDuplexType duplex) +get_baset_mode(guint32 speed, NMPlatformLinkDuplexType duplex) { - if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN) - return ADVERTISED_INVALID; - - if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) { - switch (speed) { - case 10: return ADVERTISED_10baseT_Half; - case 100: return ADVERTISED_100baseT_Half; - case 1000: return ADVERTISED_1000baseT_Half; - default: return ADVERTISED_INVALID; - } - } else { - switch (speed) { - case 10: return ADVERTISED_10baseT_Full; - case 100: return ADVERTISED_100baseT_Full; - case 1000: return ADVERTISED_1000baseT_Full; - case 10000: return ADVERTISED_10000baseT_Full; - default: return ADVERTISED_INVALID; - } - } + if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN) + return ADVERTISED_INVALID; + + if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) { + switch (speed) { + case 10: + return ADVERTISED_10baseT_Half; + case 100: + return ADVERTISED_100baseT_Half; + case 1000: + return ADVERTISED_1000baseT_Half; + default: + return ADVERTISED_INVALID; + } + } else { + switch (speed) { + case 10: + return ADVERTISED_10baseT_Full; + case 100: + return ADVERTISED_100baseT_Full; + case 1000: + return ADVERTISED_1000baseT_Full; + case 10000: + return ADVERTISED_10000baseT_Full; + default: + return ADVERTISED_INVALID; + } + } } gboolean -nmp_utils_ethtool_set_link_settings (int ifindex, - gboolean autoneg, - guint32 speed, - NMPlatformLinkDuplexType duplex) +nmp_utils_ethtool_set_link_settings(int ifindex, + gboolean autoneg, + guint32 speed, + NMPlatformLinkDuplexType duplex) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - struct ethtool_cmd edata = { - .cmd = ETHTOOL_GSET, - }; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail ( (speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN) - || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), FALSE); - - /* retrieve first current settings */ - if (_ethtool_call_handle (&shandle, &edata, sizeof (edata)) < 0) - return FALSE; - - /* FIXME: try first new ETHTOOL_GLINKSETTINGS/SLINKSETTINGS API - * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f1ac7a700d039c61d8d8b99f28d605d489a60cf - */ - - /* then change the needed ones */ - edata.cmd = ETHTOOL_SSET; - if (autoneg) { - edata.autoneg = AUTONEG_ENABLE; - if (!speed) - edata.advertising = edata.supported; - else { - guint32 mode; - - mode = get_baset_mode (speed, duplex); - - if (!mode) { - nm_log_trace (LOGD_PLATFORM, - "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised", - ifindex, - speed, - nm_platform_link_duplex_type_to_string (duplex)); - return FALSE; - } - if (!(edata.supported & mode)) { - nm_log_trace (LOGD_PLATFORM, - "ethtool[%d]: device does not support %uBASE-T %s duplex mode", - ifindex, - speed, - nm_platform_link_duplex_type_to_string (duplex)); - return FALSE; - } - edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode; - } - } else { - edata.autoneg = AUTONEG_DISABLE; - - if (speed) - ethtool_cmd_speed_set (&edata, speed); - - switch (duplex) { - case NM_PLATFORM_LINK_DUPLEX_HALF: - edata.duplex = DUPLEX_HALF; - break; - case NM_PLATFORM_LINK_DUPLEX_FULL: - edata.duplex = DUPLEX_FULL; - break; - case NM_PLATFORM_LINK_DUPLEX_UNKNOWN: - break; - default: - g_return_val_if_reached (FALSE); - } - } - - return _ethtool_call_handle (&shandle, &edata, sizeof (edata)) >= 0; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + struct ethtool_cmd edata = { + .cmd = ETHTOOL_GSET, + }; + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail((speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN) + || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), + FALSE); + + /* retrieve first current settings */ + if (_ethtool_call_handle(&shandle, &edata, sizeof(edata)) < 0) + return FALSE; + + /* FIXME: try first new ETHTOOL_GLINKSETTINGS/SLINKSETTINGS API + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f1ac7a700d039c61d8d8b99f28d605d489a60cf + */ + + /* then change the needed ones */ + edata.cmd = ETHTOOL_SSET; + if (autoneg) { + edata.autoneg = AUTONEG_ENABLE; + if (!speed) + edata.advertising = edata.supported; + else { + guint32 mode; + + mode = get_baset_mode(speed, duplex); + + if (!mode) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised", + ifindex, + speed, + nm_platform_link_duplex_type_to_string(duplex)); + return FALSE; + } + if (!(edata.supported & mode)) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: device does not support %uBASE-T %s duplex mode", + ifindex, + speed, + nm_platform_link_duplex_type_to_string(duplex)); + return FALSE; + } + edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode; + } + } else { + edata.autoneg = AUTONEG_DISABLE; + + if (speed) + ethtool_cmd_speed_set(&edata, speed); + + switch (duplex) { + case NM_PLATFORM_LINK_DUPLEX_HALF: + edata.duplex = DUPLEX_HALF; + break; + case NM_PLATFORM_LINK_DUPLEX_FULL: + edata.duplex = DUPLEX_FULL; + break; + case NM_PLATFORM_LINK_DUPLEX_UNKNOWN: + break; + default: + g_return_val_if_reached(FALSE); + } + } + + return _ethtool_call_handle(&shandle, &edata, sizeof(edata)) >= 0; } gboolean -nmp_utils_ethtool_set_wake_on_lan (int ifindex, - NMSettingWiredWakeOnLan wol, - const char *wol_password) +nmp_utils_ethtool_set_wake_on_lan(int ifindex, + NMSettingWiredWakeOnLan wol, + const char * wol_password) { - struct ethtool_wolinfo wol_info = { - .cmd = ETHTOOL_SWOL, - .wolopts = 0, - }; - - g_return_val_if_fail (ifindex > 0, FALSE); - - if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE) - return TRUE; - - nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: setting Wake-on-LAN options 0x%x, password '%s'", - ifindex, (unsigned) wol, wol_password); - - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) - wol_info.wolopts |= WAKE_PHY; - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) - wol_info.wolopts |= WAKE_UCAST; - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) - wol_info.wolopts |= WAKE_MCAST; - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) - wol_info.wolopts |= WAKE_BCAST; - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) - wol_info.wolopts |= WAKE_ARP; - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) - wol_info.wolopts |= WAKE_MAGIC; - - if (wol_password) { - if (!nm_utils_hwaddr_aton (wol_password, wol_info.sopass, ETH_ALEN)) { - nm_log_dbg (LOGD_PLATFORM, "ethtool[%d]: couldn't parse Wake-on-LAN password '%s'", ifindex, wol_password); - return FALSE; - } - wol_info.wolopts |= WAKE_MAGICSECURE; - } - - return _ethtool_call_once (ifindex, &wol_info, sizeof (wol_info)) >= 0; + struct ethtool_wolinfo wol_info = { + .cmd = ETHTOOL_SWOL, + .wolopts = 0, + }; + + g_return_val_if_fail(ifindex > 0, FALSE); + + if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE) + return TRUE; + + nm_log_dbg(LOGD_PLATFORM, + "ethtool[%d]: setting Wake-on-LAN options 0x%x, password '%s'", + ifindex, + (unsigned) wol, + wol_password); + + if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) + wol_info.wolopts |= WAKE_PHY; + if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) + wol_info.wolopts |= WAKE_UCAST; + if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) + wol_info.wolopts |= WAKE_MCAST; + if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) + wol_info.wolopts |= WAKE_BCAST; + if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) + wol_info.wolopts |= WAKE_ARP; + if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + wol_info.wolopts |= WAKE_MAGIC; + + if (wol_password) { + if (!nm_utils_hwaddr_aton(wol_password, wol_info.sopass, ETH_ALEN)) { + nm_log_dbg(LOGD_PLATFORM, + "ethtool[%d]: couldn't parse Wake-on-LAN password '%s'", + ifindex, + wol_password); + return FALSE; + } + wol_info.wolopts |= WAKE_MAGICSECURE; + } + + return _ethtool_call_once(ifindex, &wol_info, sizeof(wol_info)) >= 0; } /****************************************************************************** @@ -1387,48 +1457,52 @@ nmp_utils_ethtool_set_wake_on_lan (int ifindex, *****************************************************************************/ gboolean -nmp_utils_mii_supports_carrier_detect (int ifindex) +nmp_utils_mii_supports_carrier_detect(int ifindex) { - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); - int r; - struct ifreq ifr; - struct mii_ioctl_data *mii; - - g_return_val_if_fail (ifindex > 0, FALSE); - - r = _ioctl_call ("mii", - "SIOCGMIIPHY", - SIOCGMIIPHY, - shandle.ifindex, - &shandle.fd, - shandle.ifname, - IOCTL_CALL_DATA_TYPE_NONE, - NULL, - 0, - &ifr); - if (r < 0) - return FALSE; - - /* If we can read the BMSR register, we assume that the card supports MII link detection */ - mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; - mii->reg_num = MII_BMSR; - - r = _ioctl_call ("mii", - "SIOCGMIIREG", - SIOCGMIIREG, - shandle.ifindex, - &shandle.fd, - shandle.ifname, - IOCTL_CALL_DATA_TYPE_IFRU, - mii, - sizeof (*mii), - &ifr); - if (r < 0) - return FALSE; - - mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; - nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect yes: SIOCGMIIREG result 0x%X", ifindex, shandle.ifname, mii->val_out); - return TRUE; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + int r; + struct ifreq ifr; + struct mii_ioctl_data * mii; + + g_return_val_if_fail(ifindex > 0, FALSE); + + r = _ioctl_call("mii", + "SIOCGMIIPHY", + SIOCGMIIPHY, + shandle.ifindex, + &shandle.fd, + shandle.ifname, + IOCTL_CALL_DATA_TYPE_NONE, + NULL, + 0, + &ifr); + if (r < 0) + return FALSE; + + /* If we can read the BMSR register, we assume that the card supports MII link detection */ + mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; + mii->reg_num = MII_BMSR; + + r = _ioctl_call("mii", + "SIOCGMIIREG", + SIOCGMIIREG, + shandle.ifindex, + &shandle.fd, + shandle.ifname, + IOCTL_CALL_DATA_TYPE_IFRU, + mii, + sizeof(*mii), + &ifr); + if (r < 0) + return FALSE; + + mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; + nm_log_trace(LOGD_PLATFORM, + "mii[%d,%s]: carrier-detect yes: SIOCGMIIREG result 0x%X", + ifindex, + shandle.ifname, + mii->val_out); + return TRUE; } /****************************************************************************** @@ -1436,38 +1510,37 @@ nmp_utils_mii_supports_carrier_detect (int ifindex) *****************************************************************************/ const char * -nmp_utils_udev_get_driver (struct udev_device *udevice) +nmp_utils_udev_get_driver(struct udev_device *udevice) { - struct udev_device *parent = NULL, *grandparent = NULL; - const char *driver, *subsys; - - driver = udev_device_get_driver (udevice); - if (driver) - goto out; - - /* Try the parent */ - parent = udev_device_get_parent (udevice); - if (parent) { - driver = udev_device_get_driver (parent); - if (!driver) { - /* Try the grandparent if it's an ibmebus device or if the - * subsys is NULL which usually indicates some sort of - * platform device like a 'gadget' net interface. - */ - subsys = udev_device_get_subsystem (parent); - if ( (g_strcmp0 (subsys, "ibmebus") == 0) - || (subsys == NULL)) { - grandparent = udev_device_get_parent (parent); - if (grandparent) - driver = udev_device_get_driver (grandparent); - } - } - } + struct udev_device *parent = NULL, *grandparent = NULL; + const char * driver, *subsys; + + driver = udev_device_get_driver(udevice); + if (driver) + goto out; + + /* Try the parent */ + parent = udev_device_get_parent(udevice); + if (parent) { + driver = udev_device_get_driver(parent); + if (!driver) { + /* Try the grandparent if it's an ibmebus device or if the + * subsys is NULL which usually indicates some sort of + * platform device like a 'gadget' net interface. + */ + subsys = udev_device_get_subsystem(parent); + if ((g_strcmp0(subsys, "ibmebus") == 0) || (subsys == NULL)) { + grandparent = udev_device_get_parent(parent); + if (grandparent) + driver = udev_device_get_driver(grandparent); + } + } + } out: - /* Intern the string so we don't have to worry about memory - * management in NMPlatformLink. */ - return g_intern_string (driver); + /* Intern the string so we don't have to worry about memory + * management in NMPlatformLink. */ + return g_intern_string(driver); } /****************************************************************************** @@ -1475,127 +1548,164 @@ out: *****************************************************************************/ NMIPConfigSource -nmp_utils_ip_config_source_from_rtprot (guint8 rtprot) +nmp_utils_ip_config_source_from_rtprot(guint8 rtprot) { - return ((int) rtprot) + 1; + return ((int) rtprot) + 1; } NMIPConfigSource -nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source) +nmp_utils_ip_config_source_round_trip_rtprot(NMIPConfigSource source) { - /* when adding a route to kernel for a give @source, the resulting route - * will be put into the cache with a source of NM_IP_CONFIG_SOURCE_RTPROT_*. - * This function returns that. */ - return nmp_utils_ip_config_source_from_rtprot (nmp_utils_ip_config_source_coerce_to_rtprot (source)); + /* when adding a route to kernel for a give @source, the resulting route + * will be put into the cache with a source of NM_IP_CONFIG_SOURCE_RTPROT_*. + * This function returns that. */ + return nmp_utils_ip_config_source_from_rtprot( + nmp_utils_ip_config_source_coerce_to_rtprot(source)); } guint8 -nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source) +nmp_utils_ip_config_source_coerce_to_rtprot(NMIPConfigSource source) { - /* when adding a route to kernel, we coerce the @source field - * to rtm_protocol. This is not lossless as we map different - * source values to the same RTPROT uint8 value. */ - if (source <= NM_IP_CONFIG_SOURCE_UNKNOWN) - return RTPROT_UNSPEC; - - if (source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST) - return source - 1; - - switch (source) { - case NM_IP_CONFIG_SOURCE_KERNEL: - return RTPROT_KERNEL; - case NM_IP_CONFIG_SOURCE_IP6LL: - return RTPROT_KERNEL; - case NM_IP_CONFIG_SOURCE_DHCP: - return RTPROT_DHCP; - case NM_IP_CONFIG_SOURCE_NDISC: - return RTPROT_RA; - - default: - return RTPROT_STATIC; - } + /* when adding a route to kernel, we coerce the @source field + * to rtm_protocol. This is not lossless as we map different + * source values to the same RTPROT uint8 value. */ + if (source <= NM_IP_CONFIG_SOURCE_UNKNOWN) + return RTPROT_UNSPEC; + + if (source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST) + return source - 1; + + switch (source) { + case NM_IP_CONFIG_SOURCE_KERNEL: + return RTPROT_KERNEL; + case NM_IP_CONFIG_SOURCE_IP6LL: + return RTPROT_KERNEL; + case NM_IP_CONFIG_SOURCE_DHCP: + return RTPROT_DHCP; + case NM_IP_CONFIG_SOURCE_NDISC: + return RTPROT_RA; + + default: + return RTPROT_STATIC; + } } NMIPConfigSource -nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource source) +nmp_utils_ip_config_source_coerce_from_rtprot(NMIPConfigSource source) { - /* When we receive a route from kernel and put it into the platform cache, - * we preserve the protocol field by converting it to a NMIPConfigSource - * via nmp_utils_ip_config_source_from_rtprot(). - * - * However, that is not the inverse of nmp_utils_ip_config_source_coerce_to_rtprot(). - * Instead, to go back to the original value, you need another step: - * nmp_utils_ip_config_source_coerce_from_rtprot (nmp_utils_ip_config_source_from_rtprot (rtprot)). - * - * This might partly restore the original source value, but of course that - * is not really possible because nmp_utils_ip_config_source_coerce_to_rtprot() - * is not injective. - * */ - switch (source) { - case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: - return NM_IP_CONFIG_SOURCE_UNKNOWN; - - case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: - case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: - return NM_IP_CONFIG_SOURCE_KERNEL; - - case NM_IP_CONFIG_SOURCE_RTPROT_RA: - return NM_IP_CONFIG_SOURCE_NDISC; - - case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: - return NM_IP_CONFIG_SOURCE_DHCP; - - default: - return NM_IP_CONFIG_SOURCE_USER; - } + /* When we receive a route from kernel and put it into the platform cache, + * we preserve the protocol field by converting it to a NMIPConfigSource + * via nmp_utils_ip_config_source_from_rtprot(). + * + * However, that is not the inverse of nmp_utils_ip_config_source_coerce_to_rtprot(). + * Instead, to go back to the original value, you need another step: + * nmp_utils_ip_config_source_coerce_from_rtprot (nmp_utils_ip_config_source_from_rtprot (rtprot)). + * + * This might partly restore the original source value, but of course that + * is not really possible because nmp_utils_ip_config_source_coerce_to_rtprot() + * is not injective. + * */ + switch (source) { + case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: + return NM_IP_CONFIG_SOURCE_UNKNOWN; + + case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: + case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: + return NM_IP_CONFIG_SOURCE_KERNEL; + + case NM_IP_CONFIG_SOURCE_RTPROT_RA: + return NM_IP_CONFIG_SOURCE_NDISC; + + case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: + return NM_IP_CONFIG_SOURCE_DHCP; + + default: + return NM_IP_CONFIG_SOURCE_USER; + } } const char * -nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len) +nmp_utils_ip_config_source_to_string(NMIPConfigSource source, char *buf, gsize len) { - const char *s = NULL; - nm_utils_to_string_buffer_init (&buf, &len); \ - - if (!len) - return buf; - - switch (source) { - case NM_IP_CONFIG_SOURCE_UNKNOWN: s = "unknown"; break; - - case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: s = "rt-unspec"; break; - case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: s = "rt-redirect"; break; - case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: s = "rt-kernel"; break; - case NM_IP_CONFIG_SOURCE_RTPROT_BOOT: s = "rt-boot"; break; - case NM_IP_CONFIG_SOURCE_RTPROT_STATIC: s = "rt-static"; break; - case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: s = "rt-dhcp"; break; - case NM_IP_CONFIG_SOURCE_RTPROT_RA: s = "rt-ra"; break; - - case NM_IP_CONFIG_SOURCE_KERNEL: s = "kernel"; break; - case NM_IP_CONFIG_SOURCE_SHARED: s = "shared"; break; - case NM_IP_CONFIG_SOURCE_IP4LL: s = "ipv4ll"; break; - case NM_IP_CONFIG_SOURCE_IP6LL: s = "ipv6ll"; break; - case NM_IP_CONFIG_SOURCE_PPP: s = "ppp"; break; - case NM_IP_CONFIG_SOURCE_WWAN: s = "wwan"; break; - case NM_IP_CONFIG_SOURCE_VPN: s = "vpn"; break; - case NM_IP_CONFIG_SOURCE_DHCP: s = "dhcp"; break; - case NM_IP_CONFIG_SOURCE_NDISC: s = "ndisc"; break; - case NM_IP_CONFIG_SOURCE_USER: s = "user"; break; - default: - break; - } - - if (source >= 1 && source <= 0x100) { - if (s) - g_snprintf (buf, len, "%s", s); - else - g_snprintf (buf, len, "rt-%d", ((int) source) - 1); - } else { - if (s) - g_strlcpy (buf, s, len); - else - g_snprintf (buf, len, "(%d)", source); - } - return buf; + const char *s = NULL; + nm_utils_to_string_buffer_init(&buf, &len); + + if (!len) + return buf; + + switch (source) { + case NM_IP_CONFIG_SOURCE_UNKNOWN: + s = "unknown"; + break; + + case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: + s = "rt-unspec"; + break; + case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: + s = "rt-redirect"; + break; + case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: + s = "rt-kernel"; + break; + case NM_IP_CONFIG_SOURCE_RTPROT_BOOT: + s = "rt-boot"; + break; + case NM_IP_CONFIG_SOURCE_RTPROT_STATIC: + s = "rt-static"; + break; + case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: + s = "rt-dhcp"; + break; + case NM_IP_CONFIG_SOURCE_RTPROT_RA: + s = "rt-ra"; + break; + + case NM_IP_CONFIG_SOURCE_KERNEL: + s = "kernel"; + break; + case NM_IP_CONFIG_SOURCE_SHARED: + s = "shared"; + break; + case NM_IP_CONFIG_SOURCE_IP4LL: + s = "ipv4ll"; + break; + case NM_IP_CONFIG_SOURCE_IP6LL: + s = "ipv6ll"; + break; + case NM_IP_CONFIG_SOURCE_PPP: + s = "ppp"; + break; + case NM_IP_CONFIG_SOURCE_WWAN: + s = "wwan"; + break; + case NM_IP_CONFIG_SOURCE_VPN: + s = "vpn"; + break; + case NM_IP_CONFIG_SOURCE_DHCP: + s = "dhcp"; + break; + case NM_IP_CONFIG_SOURCE_NDISC: + s = "ndisc"; + break; + case NM_IP_CONFIG_SOURCE_USER: + s = "user"; + break; + default: + break; + } + + if (source >= 1 && source <= 0x100) { + if (s) + g_snprintf(buf, len, "%s", s); + else + g_snprintf(buf, len, "rt-%d", ((int) source) - 1); + } else { + if (s) + g_strlcpy(buf, s, len); + else + g_snprintf(buf, len, "(%d)", source); + } + return buf; } /** @@ -1612,66 +1722,64 @@ nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize * to the "/sys/class/net/%s" directory for @ifindex. */ int -nmp_utils_sysctl_open_netdir (int ifindex, - const char *ifname_guess, - char *out_ifname) +nmp_utils_sysctl_open_netdir(int ifindex, const char *ifname_guess, char *out_ifname) { - #define SYS_CLASS_NET "/sys/class/net/" - const char *ifname = ifname_guess; - char ifname_buf_last_try[IFNAMSIZ]; - char ifname_buf[IFNAMSIZ]; - guint try_count = 0; - char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET; - char fd_buf[256]; - ssize_t nn; +#define SYS_CLASS_NET "/sys/class/net/" + const char *ifname = ifname_guess; + char ifname_buf_last_try[IFNAMSIZ]; + char ifname_buf[IFNAMSIZ]; + guint try_count = 0; + char sysdir[NM_STRLEN(SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET; + char fd_buf[256]; + ssize_t nn; - g_return_val_if_fail (ifindex >= 0, -1); + g_return_val_if_fail(ifindex >= 0, -1); - ifname_buf_last_try[0] = '\0'; + ifname_buf_last_try[0] = '\0'; - for (try_count = 0; try_count < 10; try_count++, ifname = NULL) { - nm_auto_close int fd_dir = -1; - nm_auto_close int fd_ifindex = -1; + for (try_count = 0; try_count < 10; try_count++, ifname = NULL) { + nm_auto_close int fd_dir = -1; + nm_auto_close int fd_ifindex = -1; - if (!ifname) { - ifname = nmp_utils_if_indextoname (ifindex, ifname_buf); - if (!ifname) - return -1; - } + if (!ifname) { + ifname = nmp_utils_if_indextoname(ifindex, ifname_buf); + if (!ifname) + return -1; + } - nm_assert (nm_utils_ifname_valid_kernel (ifname, NULL)); + nm_assert(nm_utils_ifname_valid_kernel(ifname, NULL)); - if (g_strlcpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], ifname, IFNAMSIZ) >= IFNAMSIZ) - g_return_val_if_reached (-1); + if (g_strlcpy(&sysdir[NM_STRLEN(SYS_CLASS_NET)], ifname, IFNAMSIZ) >= IFNAMSIZ) + g_return_val_if_reached(-1); - /* we only retry, if the name changed since previous attempt. - * Hence, it is extremely unlikely that this loop runes until the - * end of the @try_count. */ - if (nm_streq (ifname, ifname_buf_last_try)) - return -1; - strcpy (ifname_buf_last_try, ifname); + /* we only retry, if the name changed since previous attempt. + * Hence, it is extremely unlikely that this loop runes until the + * end of the @try_count. */ + if (nm_streq(ifname, ifname_buf_last_try)) + return -1; + strcpy(ifname_buf_last_try, ifname); - fd_dir = open (sysdir, O_DIRECTORY | O_CLOEXEC); - if (fd_dir < 0) - continue; + fd_dir = open(sysdir, O_DIRECTORY | O_CLOEXEC); + if (fd_dir < 0) + continue; - fd_ifindex = openat (fd_dir, "ifindex", O_CLOEXEC); - if (fd_ifindex < 0) - continue; + fd_ifindex = openat(fd_dir, "ifindex", O_CLOEXEC); + if (fd_ifindex < 0) + continue; - nn = nm_utils_fd_read_loop (fd_ifindex, fd_buf, sizeof (fd_buf) - 2, FALSE); - if (nn <= 0) - continue; - fd_buf[nn] = '\0'; + nn = nm_utils_fd_read_loop(fd_ifindex, fd_buf, sizeof(fd_buf) - 2, FALSE); + if (nn <= 0) + continue; + fd_buf[nn] = '\0'; - if (ifindex != (int) _nm_utils_ascii_str_to_int64 (fd_buf, 10, 1, G_MAXINT, -1)) - continue; + if (ifindex != (int) _nm_utils_ascii_str_to_int64(fd_buf, 10, 1, G_MAXINT, -1)) + continue; - if (out_ifname) - strcpy (out_ifname, ifname); + if (out_ifname) + strcpy(out_ifname, ifname); - return nm_steal_fd (&fd_dir); - } + return nm_steal_fd(&fd_dir); + } - return -1; + return -1; } diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 062c8597..076a2c7d 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 Red Hat, Inc. */ @@ -12,128 +12,129 @@ /*****************************************************************************/ -const char *nmp_utils_ethtool_get_driver (int ifindex); -gboolean nmp_utils_ethtool_supports_carrier_detect (int ifindex); -gboolean nmp_utils_ethtool_supports_vlans (int ifindex); -int nmp_utils_ethtool_get_peer_ifindex (int ifindex); -gboolean nmp_utils_ethtool_get_wake_on_lan (int ifindex); -gboolean nmp_utils_ethtool_set_wake_on_lan (int ifindex, NMSettingWiredWakeOnLan wol, - const char *wol_password); - -gboolean nmp_utils_ethtool_get_link_settings (int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex); -gboolean nmp_utils_ethtool_set_link_settings (int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex); - -gboolean nmp_utils_ethtool_get_permanent_address (int ifindex, - guint8 *buf, - size_t *length); +const char *nmp_utils_ethtool_get_driver(int ifindex); +gboolean nmp_utils_ethtool_supports_carrier_detect(int ifindex); +gboolean nmp_utils_ethtool_supports_vlans(int ifindex); +int nmp_utils_ethtool_get_peer_ifindex(int ifindex); +gboolean nmp_utils_ethtool_get_wake_on_lan(int ifindex); +gboolean nmp_utils_ethtool_set_wake_on_lan(int ifindex, + NMSettingWiredWakeOnLan wol, + const char * wol_password); + +gboolean nmp_utils_ethtool_get_link_settings(int ifindex, + gboolean * out_autoneg, + guint32 * out_speed, + NMPlatformLinkDuplexType *out_duplex); +gboolean nmp_utils_ethtool_set_link_settings(int ifindex, + gboolean autoneg, + guint32 speed, + NMPlatformLinkDuplexType duplex); + +gboolean nmp_utils_ethtool_get_permanent_address(int ifindex, guint8 *buf, size_t *length); typedef struct { - /* We don't want to include <linux/ethtool.h> in header files, - * thus create a ABI compatible version of struct ethtool_drvinfo.*/ - guint32 _private_cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char _private_bus_info[32]; - char _private_erom_version[32]; - char _private_reserved2[12]; - guint32 _private_n_priv_flags; - guint32 _private_n_stats; - guint32 _private_testinfo_len; - guint32 _private_eedump_len; - guint32 _private_regdump_len; + /* We don't want to include <linux/ethtool.h> in header files, + * thus create a ABI compatible version of struct ethtool_drvinfo.*/ + guint32 _private_cmd; + char driver[32]; + char version[32]; + char fw_version[32]; + char _private_bus_info[32]; + char _private_erom_version[32]; + char _private_reserved2[12]; + guint32 _private_n_priv_flags; + guint32 _private_n_stats; + guint32 _private_testinfo_len; + guint32 _private_eedump_len; + guint32 _private_regdump_len; } NMPUtilsEthtoolDriverInfo; -gboolean nmp_utils_ethtool_get_driver_info (int ifindex, - NMPUtilsEthtoolDriverInfo *data); +gboolean nmp_utils_ethtool_get_driver_info(int ifindex, NMPUtilsEthtoolDriverInfo *data); typedef struct { - NMEthtoolID ethtool_id; + NMEthtoolID ethtool_id; - guint8 n_kernel_names; + guint8 n_kernel_names; - /* one NMEthtoolID refers to one or more kernel_names. The reason for supporting this complexity - * (where one NMSettingEthtool option refers to multiple kernel features) is to follow what - * ethtool does, where "tx" is an alias for multiple features. */ - const char *const*kernel_names; + /* one NMEthtoolID refers to one or more kernel_names. The reason for supporting this complexity + * (where one NMSettingEthtool option refers to multiple kernel features) is to follow what + * ethtool does, where "tx" is an alias for multiple features. */ + const char *const *kernel_names; } NMEthtoolFeatureInfo; typedef struct { - const NMEthtoolFeatureInfo *info; + const NMEthtoolFeatureInfo *info; - guint idx_ss_features; + guint idx_ss_features; - /* one NMEthtoolFeatureInfo references one or more kernel_names. This is the index - * of the matching info->kernel_names */ - guint8 idx_kernel_name; + /* one NMEthtoolFeatureInfo references one or more kernel_names. This is the index + * of the matching info->kernel_names */ + guint8 idx_kernel_name; - bool available:1; - bool requested:1; - bool active:1; - bool never_changed:1; + bool available : 1; + bool requested : 1; + bool active : 1; + bool never_changed : 1; } NMEthtoolFeatureState; struct _NMEthtoolFeatureStates { - guint n_states; + guint n_states; - guint n_ss_features; + guint n_ss_features; - /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */ - const NMEthtoolFeatureState *const*states_indexed[_NM_ETHTOOL_ID_FEATURE_NUM]; + /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */ + const NMEthtoolFeatureState *const *states_indexed[_NM_ETHTOOL_ID_FEATURE_NUM]; - /* the same content, here as a list of n_states entries. */ - const NMEthtoolFeatureState states_list[]; + /* the same content, here as a list of n_states entries. */ + const NMEthtoolFeatureState states_list[]; }; -NMEthtoolFeatureStates *nmp_utils_ethtool_get_features (int ifindex); +NMEthtoolFeatureStates *nmp_utils_ethtool_get_features(int ifindex); -gboolean nmp_utils_ethtool_set_features (int ifindex, - const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */); +gboolean nmp_utils_ethtool_set_features( + int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */); struct _NMEthtoolCoalesceState { - guint32 s[_NM_ETHTOOL_ID_COALESCE_NUM /* indexed by (NMEthtoolID - _NM_ETHTOOL_ID_COALESCE_FIRST) */]; + guint32 + s[_NM_ETHTOOL_ID_COALESCE_NUM /* indexed by (NMEthtoolID - _NM_ETHTOOL_ID_COALESCE_FIRST) */ + ]; }; -gboolean nmp_utils_ethtool_get_coalesce (int ifindex, - NMEthtoolCoalesceState *coalesce); +gboolean nmp_utils_ethtool_get_coalesce(int ifindex, NMEthtoolCoalesceState *coalesce); -gboolean nmp_utils_ethtool_set_coalesce (int ifindex, - const NMEthtoolCoalesceState *coalesce); +gboolean nmp_utils_ethtool_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce); struct _NMEthtoolRingState { - guint32 rx_pending; - guint32 rx_mini_pending; - guint32 rx_jumbo_pending; - guint32 tx_pending; + guint32 rx_pending; + guint32 rx_mini_pending; + guint32 rx_jumbo_pending; + guint32 tx_pending; }; -gboolean nmp_utils_ethtool_get_ring (int ifindex, - NMEthtoolRingState *ring); +gboolean nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring); -gboolean nmp_utils_ethtool_set_ring (int ifindex, - const NMEthtoolRingState *ring); +gboolean nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring); /*****************************************************************************/ -gboolean nmp_utils_mii_supports_carrier_detect (int ifindex); +gboolean nmp_utils_mii_supports_carrier_detect(int ifindex); struct udev_device; -const char *nmp_utils_udev_get_driver (struct udev_device *udevice); +const char *nmp_utils_udev_get_driver(struct udev_device *udevice); -NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint8 rtprot) _nm_const; -guint8 nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source) _nm_const; -NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource source) _nm_const; -NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source) _nm_const; -const char * nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len); +NMIPConfigSource nmp_utils_ip_config_source_from_rtprot(guint8 rtprot) _nm_const; +guint8 nmp_utils_ip_config_source_coerce_to_rtprot(NMIPConfigSource source) _nm_const; +NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot(NMIPConfigSource source) _nm_const; +NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot(NMIPConfigSource source) _nm_const; +const char *nmp_utils_ip_config_source_to_string(NMIPConfigSource source, char *buf, gsize len); -const char *nmp_utils_if_indextoname (int ifindex, char *out_ifname/*IFNAMSIZ*/); -int nmp_utils_if_nametoindex (const char *ifname); +const char *nmp_utils_if_indextoname(int ifindex, char *out_ifname /*IFNAMSIZ*/); +int nmp_utils_if_nametoindex(const char *ifname); -int nmp_utils_sysctl_open_netdir (int ifindex, - const char *ifname_guess, - char *out_ifname); +int nmp_utils_sysctl_open_netdir(int ifindex, const char *ifname_guess, char *out_ifname); #endif /* __NM_PLATFORM_UTILS_H__ */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 4702ba97..d1ff6fbc 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ @@ -36,220 +36,226 @@ /*****************************************************************************/ -G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Address, address)); -G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Address, address)); -G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Route, network)); -G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Route, network)); +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr) + == G_STRUCT_OFFSET(NMPlatformIP4Address, address)); +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr) + == G_STRUCT_OFFSET(NMPlatformIP6Address, address)); +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr) + == G_STRUCT_OFFSET(NMPlatformIP4Route, network)); +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr) + == G_STRUCT_OFFSET(NMPlatformIP6Route, network)); -G_STATIC_ASSERT (_nm_alignof (NMPlatformIPRoute) == _nm_alignof (NMPlatformIP4Route)); -G_STATIC_ASSERT (_nm_alignof (NMPlatformIPRoute) == _nm_alignof (NMPlatformIP6Route)); -G_STATIC_ASSERT (_nm_alignof (NMPlatformIPRoute) == _nm_alignof (NMPlatformIPXRoute)); +G_STATIC_ASSERT(_nm_alignof(NMPlatformIPRoute) == _nm_alignof(NMPlatformIP4Route)); +G_STATIC_ASSERT(_nm_alignof(NMPlatformIPRoute) == _nm_alignof(NMPlatformIP6Route)); +G_STATIC_ASSERT(_nm_alignof(NMPlatformIPRoute) == _nm_alignof(NMPlatformIPXRoute)); -G_STATIC_ASSERT (_nm_alignof (NMPlatformIPAddress) == _nm_alignof (NMPlatformIP4Address)); -G_STATIC_ASSERT (_nm_alignof (NMPlatformIPAddress) == _nm_alignof (NMPlatformIP6Address)); -G_STATIC_ASSERT (_nm_alignof (NMPlatformIPAddress) == _nm_alignof (NMPlatformIPXAddress)); +G_STATIC_ASSERT(_nm_alignof(NMPlatformIPAddress) == _nm_alignof(NMPlatformIP4Address)); +G_STATIC_ASSERT(_nm_alignof(NMPlatformIPAddress) == _nm_alignof(NMPlatformIP6Address)); +G_STATIC_ASSERT(_nm_alignof(NMPlatformIPAddress) == _nm_alignof(NMPlatformIPXAddress)); /*****************************************************************************/ -G_STATIC_ASSERT (sizeof ( ((NMPLinkAddress *) NULL)->data ) == NM_UTILS_HWADDR_LEN_MAX); -G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->l_address.data ) == NM_UTILS_HWADDR_LEN_MAX); -G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->l_broadcast.data ) == NM_UTILS_HWADDR_LEN_MAX); +G_STATIC_ASSERT(sizeof(((NMPLinkAddress *) NULL)->data) == NM_UTILS_HWADDR_LEN_MAX); +G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_address.data) == NM_UTILS_HWADDR_LEN_MAX); +G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_broadcast.data) == NM_UTILS_HWADDR_LEN_MAX); static const char * -_nmp_link_address_to_string (const NMPLinkAddress *addr, - char buf[static (NM_UTILS_HWADDR_LEN_MAX * 3)]) +_nmp_link_address_to_string(const NMPLinkAddress *addr, + char buf[static(NM_UTILS_HWADDR_LEN_MAX * 3)]) { - nm_assert (addr); + nm_assert(addr); - if (addr->len > 0) { - if (!nm_utils_hwaddr_ntoa_buf (addr->data, - addr->len, - TRUE, - buf, - NM_UTILS_HWADDR_LEN_MAX * 3)) { - buf[0] = '\0'; - g_return_val_if_reached (buf); - } - } else - buf[0] = '\0'; + if (addr->len > 0) { + if (!_nm_utils_hwaddr_ntoa(addr->data, addr->len, TRUE, buf, NM_UTILS_HWADDR_LEN_MAX * 3)) { + buf[0] = '\0'; + g_return_val_if_reached(buf); + } + } else + buf[0] = '\0'; - return buf; + return buf; } gconstpointer -nmp_link_address_get (const NMPLinkAddress *addr, size_t *length) +nmp_link_address_get(const NMPLinkAddress *addr, size_t *length) { - if ( !addr - || addr->len <= 0) { - NM_SET_OUT (length, 0); - return NULL; - } + if (!addr || addr->len <= 0) { + NM_SET_OUT(length, 0); + return NULL; + } - if (addr->len > NM_UTILS_HWADDR_LEN_MAX) { - NM_SET_OUT (length, 0); - g_return_val_if_reached (NULL); - } + if (addr->len > NM_UTILS_HWADDR_LEN_MAX) { + NM_SET_OUT(length, 0); + g_return_val_if_reached(NULL); + } - NM_SET_OUT (length, addr->len); - return addr->data; + NM_SET_OUT(length, addr->len); + return addr->data; } GBytes * -nmp_link_address_get_as_bytes (const NMPLinkAddress *addr) +nmp_link_address_get_as_bytes(const NMPLinkAddress *addr) { - gconstpointer data; - size_t length; + gconstpointer data; + size_t length; - data = nmp_link_address_get (addr, &length); + data = nmp_link_address_get(addr, &length); - return length > 0 - ? g_bytes_new (data, length) - : NULL; + return length > 0 ? g_bytes_new(data, length) : NULL; } /*****************************************************************************/ -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG_PREFIX_NAME "platform" - - -#define NMLOG_COMMON(level, name, ...) \ - char __prefix[32]; \ - const char *__p_prefix = _NMLOG_PREFIX_NAME; \ - const NMPlatform *const __self = (self); \ - const char *__name = name; \ - \ - if (__self && NM_PLATFORM_GET_PRIVATE (__self)->log_with_ptr) { \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ - __p_prefix = __prefix; \ - } \ - _nm_log (__level, _NMLOG_DOMAIN, 0, __name, NULL, \ - "%s: %s%s%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - __p_prefix, \ - NM_PRINT_FMT_QUOTED (__name, "(", __name, ") ", "") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); - -#define _NMLOG(level, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ - NMLOG_COMMON(level, NULL, __VA_ARGS__); \ - } \ - } G_STMT_END - -#define _NMLOG2(level, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ - NMLOG_COMMON(level, name, __VA_ARGS__); \ - } \ - } G_STMT_END - -#define _NMLOG3(level, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ - NMLOG_COMMON(level, ifindex > 0 ? nm_platform_link_get_name (self, ifindex) : NULL, __VA_ARGS__); \ - } \ - } G_STMT_END +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG_PREFIX_NAME "platform" + +#define NMLOG_COMMON(level, name, ...) \ + char __prefix[32]; \ + const char * __p_prefix = _NMLOG_PREFIX_NAME; \ + const NMPlatform *const __self = (self); \ + const char * __name = name; \ + \ + if (__self && NM_PLATFORM_GET_PRIVATE(__self)->log_with_ptr) { \ + g_snprintf(__prefix, sizeof(__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ + __p_prefix = __prefix; \ + } \ + _nm_log(__level, \ + _NMLOG_DOMAIN, \ + 0, \ + __name, \ + NULL, \ + "%s: %s%s%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + __p_prefix, \ + NM_PRINT_FMT_QUOTED(__name, "(", __name, ") ", "") _NM_UTILS_MACRO_REST(__VA_ARGS__)); + +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ + NMLOG_COMMON(level, NULL, __VA_ARGS__); \ + } \ + } \ + G_STMT_END + +#define _NMLOG2(level, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ + NMLOG_COMMON(level, name, __VA_ARGS__); \ + } \ + } \ + G_STMT_END + +#define _NMLOG3(level, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ + NMLOG_COMMON(level, \ + ifindex > 0 ? nm_platform_link_get_name(self, ifindex) : NULL, \ + __VA_ARGS__); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ -static guint signals[_NM_PLATFORM_SIGNAL_ID_LAST] = { 0 }; +static guint signals[_NM_PLATFORM_SIGNAL_ID_LAST] = {0}; enum { - PROP_0, - PROP_NETNS_SUPPORT, - PROP_USE_UDEV, - PROP_LOG_WITH_PTR, - LAST_PROP, + PROP_0, + PROP_NETNS_SUPPORT, + PROP_USE_UDEV, + PROP_LOG_WITH_PTR, + LAST_PROP, }; typedef struct _NMPlatformPrivate { - bool use_udev:1; - bool log_with_ptr:1; - - guint ip4_dev_route_blacklist_check_id; - guint ip4_dev_route_blacklist_gc_timeout_id; - GHashTable *ip4_dev_route_blacklist_hash; - NMDedupMultiIndex *multi_idx; - NMPCache *cache; + bool use_udev : 1; + bool log_with_ptr : 1; + + guint ip4_dev_route_blacklist_check_id; + guint ip4_dev_route_blacklist_gc_timeout_id; + GHashTable * ip4_dev_route_blacklist_hash; + NMDedupMultiIndex *multi_idx; + NMPCache * cache; } NMPlatformPrivate; -G_DEFINE_TYPE (NMPlatform, nm_platform, G_TYPE_OBJECT) +G_DEFINE_TYPE(NMPlatform, nm_platform, G_TYPE_OBJECT) -#define NM_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMPlatform, NM_IS_PLATFORM) +#define NM_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMPlatform, NM_IS_PLATFORM) /*****************************************************************************/ -static void _ip4_dev_route_blacklist_schedule (NMPlatform *self); +static void _ip4_dev_route_blacklist_schedule(NMPlatform *self); /*****************************************************************************/ gboolean -nm_platform_get_use_udev (NMPlatform *self) +nm_platform_get_use_udev(NMPlatform *self) { - return NM_PLATFORM_GET_PRIVATE (self)->use_udev; + return NM_PLATFORM_GET_PRIVATE(self)->use_udev; } gboolean -nm_platform_get_log_with_ptr (NMPlatform *self) +nm_platform_get_log_with_ptr(NMPlatform *self) { - return NM_PLATFORM_GET_PRIVATE (self)->log_with_ptr; + return NM_PLATFORM_GET_PRIVATE(self)->log_with_ptr; } /*****************************************************************************/ guint -_nm_platform_signal_id_get (NMPlatformSignalIdType signal_type) +_nm_platform_signal_id_get(NMPlatformSignalIdType signal_type) { - nm_assert ( signal_type > 0 - && signal_type != NM_PLATFORM_SIGNAL_ID_NONE - && signal_type < _NM_PLATFORM_SIGNAL_ID_LAST); + nm_assert(signal_type > 0 && signal_type != NM_PLATFORM_SIGNAL_ID_NONE + && signal_type < _NM_PLATFORM_SIGNAL_ID_LAST); - return signals[signal_type]; + return signals[signal_type]; } /*****************************************************************************/ /* Singleton NMPlatform subclass instance and cached class object */ -NM_DEFINE_SINGLETON_INSTANCE (NMPlatform); +NM_DEFINE_SINGLETON_INSTANCE(NMPlatform); -NM_DEFINE_SINGLETON_REGISTER (NMPlatform); +NM_DEFINE_SINGLETON_REGISTER(NMPlatform); /* Just always initialize a @klass instance. NM_PLATFORM_GET_CLASS() * is only a plain read on the self instance, which the compiler * like can optimize out. */ -#define _CHECK_SELF_VOID(self, klass) \ - NMPlatformClass *klass; \ - do { \ - g_return_if_fail (NM_IS_PLATFORM (self)); \ - klass = NM_PLATFORM_GET_CLASS (self); \ - (void) klass; \ - } while (0) - -#define _CHECK_SELF(self, klass, err_val) \ - NMPlatformClass *klass; \ - do { \ - g_return_val_if_fail (NM_IS_PLATFORM (self), err_val); \ - klass = NM_PLATFORM_GET_CLASS (self); \ - (void) klass; \ - } while (0) - -#define _CHECK_SELF_NETNS(self, klass, netns, err_val) \ - nm_auto_pop_netns NMPNetns *netns = NULL; \ - NMPlatformClass *klass; \ - do { \ - g_return_val_if_fail (NM_IS_PLATFORM (self), err_val); \ - klass = NM_PLATFORM_GET_CLASS (self); \ - (void) klass; \ - if (!nm_platform_netns_push (self, &netns)) \ - return (err_val); \ - } while (0) +#define _CHECK_SELF_VOID(self, klass) \ + NMPlatformClass *klass; \ + do { \ + g_return_if_fail(NM_IS_PLATFORM(self)); \ + klass = NM_PLATFORM_GET_CLASS(self); \ + (void) klass; \ + } while (0) + +#define _CHECK_SELF(self, klass, err_val) \ + NMPlatformClass *klass; \ + do { \ + g_return_val_if_fail(NM_IS_PLATFORM(self), err_val); \ + klass = NM_PLATFORM_GET_CLASS(self); \ + (void) klass; \ + } while (0) + +#define _CHECK_SELF_NETNS(self, klass, netns, err_val) \ + nm_auto_pop_netns NMPNetns *netns = NULL; \ + NMPlatformClass * klass; \ + do { \ + g_return_val_if_fail(NM_IS_PLATFORM(self), err_val); \ + klass = NM_PLATFORM_GET_CLASS(self); \ + (void) klass; \ + if (!nm_platform_netns_push(self, &netns)) \ + return (err_val); \ + } while (0) /** * nm_platform_setup: @@ -264,17 +270,19 @@ NM_DEFINE_SINGLETON_REGISTER (NMPlatform); * though. */ void -nm_platform_setup (NMPlatform *instance) +nm_platform_setup(NMPlatform *instance) { - g_return_if_fail (NM_IS_PLATFORM (instance)); - g_return_if_fail (!singleton_instance); + g_return_if_fail(NM_IS_PLATFORM(instance)); + g_return_if_fail(!singleton_instance); - singleton_instance = instance; + singleton_instance = instance; - nm_singleton_instance_register (); + nm_singleton_instance_register(); - nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")", - "NMPlatform", NM_HASH_OBFUSCATE_PTR (instance)); + nm_log_dbg(LOGD_CORE, + "setup %s singleton (" NM_HASH_OBFUSCATE_PTR_FMT ")", + "NMPlatform", + NM_HASH_OBFUSCATE_PTR(instance)); } /** @@ -287,138 +295,152 @@ nm_platform_setup (NMPlatform *instance) * Returns: (transfer none): The #NMPlatform singleton reference. */ NMPlatform * -nm_platform_get () +nm_platform_get() { - g_assert (singleton_instance); + g_assert(singleton_instance); - return singleton_instance; + return singleton_instance; } /*****************************************************************************/ NMDedupMultiIndex * -nm_platform_get_multi_idx (NMPlatform *self) +nm_platform_get_multi_idx(NMPlatform *self) { - g_return_val_if_fail (NM_IS_PLATFORM (self), NULL); + g_return_val_if_fail(NM_IS_PLATFORM(self), NULL); - return NM_PLATFORM_GET_PRIVATE (self)->multi_idx; + return NM_PLATFORM_GET_PRIVATE(self)->multi_idx; } /*****************************************************************************/ -static -NM_UTILS_LOOKUP_STR_DEFINE (_nmp_nlm_flag_to_string_lookup, NMPNlmFlags, - NM_UTILS_LOOKUP_DEFAULT (NULL), - NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_ADD, "add"), - NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_CHANGE, "change"), - NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_REPLACE, "replace"), - NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_PREPEND, "prepend"), - NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_APPEND, "append"), - NM_UTILS_LOOKUP_ITEM (NMP_NLM_FLAG_TEST, "test"), - NM_UTILS_LOOKUP_ITEM_IGNORE (NMP_NLM_FLAG_F_APPEND), - NM_UTILS_LOOKUP_ITEM_IGNORE (NMP_NLM_FLAG_FMASK), - NM_UTILS_LOOKUP_ITEM_IGNORE (NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE), - NM_UTILS_LOOKUP_ITEM_IGNORE (NMP_NLM_FLAG_F_ECHO), -); - -#define _nmp_nlm_flag_to_string(flags) \ - ({ \ - NMPNlmFlags _flags = (flags); \ - \ - _nmp_nlm_flag_to_string_lookup (flags) ?: nm_sprintf_bufa (100, "new[0x%x]", (unsigned) _flags); \ - }) +static NM_UTILS_LOOKUP_STR_DEFINE( + _nmp_nlm_flag_to_string_lookup, + NMPNlmFlags, + NM_UTILS_LOOKUP_DEFAULT(NULL), + NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_ADD, "add"), + NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_CHANGE, "change"), + NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_REPLACE, "replace"), + NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_PREPEND, "prepend"), + NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_APPEND, "append"), + NM_UTILS_LOOKUP_ITEM(NMP_NLM_FLAG_TEST, "test"), + NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_F_APPEND), + NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_FMASK), + NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE), + NM_UTILS_LOOKUP_ITEM_IGNORE(NMP_NLM_FLAG_F_ECHO), ); + +#define _nmp_nlm_flag_to_string(flags) \ + ({ \ + NMPNlmFlags _flags = (flags); \ + \ + _nmp_nlm_flag_to_string_lookup(flags) \ + ?: nm_sprintf_bufa(100, "new[0x%x]", (unsigned) _flags); \ + }) /*****************************************************************************/ -volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM] = { }; +volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM] = {}; static const struct { - bool compile_time_default; - const char *name; - const char *desc; + bool compile_time_default; + const char *name; + const char *desc; } _nm_platform_kernel_support_info[_NM_PLATFORM_KERNEL_SUPPORT_NUM] = { - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS] = { - .compile_time_default = TRUE, - .name = "EXTENDED_IFA_FLAGS", - .desc = "IPv6 temporary addresses support", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL] = { - .compile_time_default = TRUE, - .name = "USER_IPV6LL", - .desc = "IFLA_INET6_ADDR_GEN_MODE support", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF] = { - .compile_time_default = (RTA_MAX >= 20 /* RTA_PREF */), - .name = "RTA_PREF", - .desc = "ability to set router preference for IPv6 routes", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV] = { - .compile_time_default = (FRA_MAX >= 19 /* FRA_L3MDEV */), - .name = "FRA_L3MDEV", - .desc = "FRA_L3MDEV attribute for policy routing rules", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE] = { - .compile_time_default = (FRA_MAX >= 20 /* FRA_UID_RANGE */), - .name = "FRA_UID_RANGE", - .desc = "FRA_UID_RANGE attribute for policy routing rules", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL] = { - .compile_time_default = (FRA_MAX >= 21 /* FRA_PROTOCOL */), - .name = "FRA_PROTOCOL", - .desc = "FRA_PROTOCOL attribute for policy routing rules", - }, - [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO] = { - .compile_time_default = (FRA_MAX >= 22 /* FRA_IP_PROTO */), - .name = "FRA_IP_PROTO", - .desc = "FRA_IP_PROTO, FRA_SPORT_RANGE, FRA_DPORT_RANGE attributes for policy routing rules", - }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS] = + { + .compile_time_default = TRUE, + .name = "EXTENDED_IFA_FLAGS", + .desc = "IPv6 temporary addresses support", + }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL] = + { + .compile_time_default = TRUE, + .name = "USER_IPV6LL", + .desc = "IFLA_INET6_ADDR_GEN_MODE support", + }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF] = + { + .compile_time_default = (RTA_MAX >= 20 /* RTA_PREF */), + .name = "RTA_PREF", + .desc = "ability to set router preference for IPv6 routes", + }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV] = + { + .compile_time_default = (FRA_MAX >= 19 /* FRA_L3MDEV */), + .name = "FRA_L3MDEV", + .desc = "FRA_L3MDEV attribute for policy routing rules", + }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE] = + { + .compile_time_default = (FRA_MAX >= 20 /* FRA_UID_RANGE */), + .name = "FRA_UID_RANGE", + .desc = "FRA_UID_RANGE attribute for policy routing rules", + }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL] = + { + .compile_time_default = (FRA_MAX >= 21 /* FRA_PROTOCOL */), + .name = "FRA_PROTOCOL", + .desc = "FRA_PROTOCOL attribute for policy routing rules", + }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO] = + { + .compile_time_default = (FRA_MAX >= 22 /* FRA_IP_PROTO */), + .name = "FRA_IP_PROTO", + .desc = "FRA_IP_PROTO, FRA_SPORT_RANGE, FRA_DPORT_RANGE attributes for policy routing " + "rules", + }, + [NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED] = + { + .compile_time_default = (IFLA_BR_MAX >= 41 /* IFLA_BR_VLAN_STATS_ENABLED */), + .name = "IFLA_BR_VLAN_STATS_ENABLE", + .desc = "IFLA_BR_VLAN_STATS_ENABLE bridge link attribute", + }, }; int -_nm_platform_kernel_support_init (NMPlatformKernelSupportType type, - int value) +_nm_platform_kernel_support_init(NMPlatformKernelSupportType type, int value) { - volatile int *p_state; - gboolean set_default = FALSE; + volatile int *p_state; + gboolean set_default = FALSE; - nm_assert (_NM_INT_NOT_NEGATIVE (type) && type < G_N_ELEMENTS (_nm_platform_kernel_support_state)); + nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(_nm_platform_kernel_support_state)); - p_state = &_nm_platform_kernel_support_state[type]; + p_state = &_nm_platform_kernel_support_state[type]; - if (value == 0) { - set_default = TRUE; - value = _nm_platform_kernel_support_info[type].compile_time_default - ? 1 - : -1; - } + if (value == 0) { + set_default = TRUE; + value = _nm_platform_kernel_support_info[type].compile_time_default ? 1 : -1; + } - nm_assert (NM_IN_SET (value, -1, 1)); + nm_assert(NM_IN_SET(value, -1, 1)); - if (!g_atomic_int_compare_and_exchange (p_state, 0, value)) { - value = g_atomic_int_get (p_state); - nm_assert (NM_IN_SET (value, -1, 1)); - return value; - } + if (!g_atomic_int_compare_and_exchange(p_state, 0, value)) { + value = g_atomic_int_get(p_state); + nm_assert(NM_IN_SET(value, -1, 1)); + return value; + } #undef NM_THREAD_SAFE_ON_MAIN_THREAD #define NM_THREAD_SAFE_ON_MAIN_THREAD 0 - if (set_default) { - nm_log_dbg (LOGD_PLATFORM, "platform: kernel-support for %s (%s) not detected: assume %ssupported", - _nm_platform_kernel_support_info[type].name, - _nm_platform_kernel_support_info[type].desc, - value >= 0 ? "" : "not "); - } else { - nm_log_dbg (LOGD_PLATFORM, "platform: kernel-support for %s (%s) detected: %ssupported", - _nm_platform_kernel_support_info[type].name, - _nm_platform_kernel_support_info[type].desc, - value >= 0 ? "" : "not "); - } + if (set_default) { + nm_log_dbg(LOGD_PLATFORM, + "platform: kernel-support for %s (%s) not detected: assume %ssupported", + _nm_platform_kernel_support_info[type].name, + _nm_platform_kernel_support_info[type].desc, + value >= 0 ? "" : "not "); + } else { + nm_log_dbg(LOGD_PLATFORM, + "platform: kernel-support for %s (%s) detected: %ssupported", + _nm_platform_kernel_support_info[type].name, + _nm_platform_kernel_support_info[type].desc, + value >= 0 ? "" : "not "); + } #undef NM_THREAD_SAFE_ON_MAIN_THREAD #define NM_THREAD_SAFE_ON_MAIN_THREAD 1 - return value; + return value; } /*****************************************************************************/ @@ -432,51 +454,51 @@ _nm_platform_kernel_support_init (NMPlatformKernelSupportType type, * new netlink messages. Possibly it will raise change signals. */ void -nm_platform_process_events (NMPlatform *self) +nm_platform_process_events(NMPlatform *self) { - _CHECK_SELF_VOID (self, klass); + _CHECK_SELF_VOID(self, klass); - if (klass->process_events) - klass->process_events (self); + if (klass->process_events) + klass->process_events(self); } const NMPlatformLink * -nm_platform_process_events_ensure_link (NMPlatform *self, - int ifindex, - const char *ifname) -{ - const NMPObject *obj; - gboolean refreshed = FALSE; - - g_return_val_if_fail (NM_IS_PLATFORM (self), NULL); - - if (ifindex <= 0 && !ifname) - return NULL; - - /* we look into the cache, whether a link for given ifindex/ifname - * exits. If not, we poll the netlink socket, maybe the event - * with the link is waiting. - * - * Then we try again to find the object. - * - * If the link is already cached the first time, we avoid polling - * the netlink socket. */ +nm_platform_process_events_ensure_link(NMPlatform *self, int ifindex, const char *ifname) +{ + const NMPObject *obj; + gboolean refreshed = FALSE; + + g_return_val_if_fail(NM_IS_PLATFORM(self), NULL); + + if (ifindex <= 0 && !ifname) + return NULL; + + /* we look into the cache, whether a link for given ifindex/ifname + * exits. If not, we poll the netlink socket, maybe the event + * with the link is waiting. + * + * Then we try again to find the object. + * + * If the link is already cached the first time, we avoid polling + * the netlink socket. */ again: - obj = nmp_cache_lookup_link_full (nm_platform_get_cache (self), - ifindex, - ifname, - FALSE, /* also invisible. We don't care here whether udev is ready */ - NM_LINK_TYPE_NONE, - NULL, NULL); - if (obj) - return NMP_OBJECT_CAST_LINK (obj); - if (!refreshed) { - refreshed = TRUE; - nm_platform_process_events (self); - goto again; - } - - return NULL; + obj = nmp_cache_lookup_link_full( + nm_platform_get_cache(self), + ifindex, + ifname, + FALSE, /* also invisible. We don't care here whether udev is ready */ + NM_LINK_TYPE_NONE, + NULL, + NULL); + if (obj) + return NMP_OBJECT_CAST_LINK(obj); + if (!refreshed) { + refreshed = TRUE; + nm_platform_process_events(self); + goto again; + } + + return NULL; } /*****************************************************************************/ @@ -494,19 +516,19 @@ again: * directory. */ int -nm_platform_sysctl_open_netdir (NMPlatform *self, int ifindex, char *out_ifname) +nm_platform_sysctl_open_netdir(NMPlatform *self, int ifindex, char *out_ifname) { - const char*ifname_guess; - _CHECK_SELF_NETNS (self, klass, netns, -1); + const char *ifname_guess; + _CHECK_SELF_NETNS(self, klass, netns, -1); - g_return_val_if_fail (ifindex > 0, -1); + g_return_val_if_fail(ifindex > 0, -1); - /* we don't have an @ifname_guess argument to make the API nicer. - * But still do a cache-lookup first. Chances are good that we have - * the right ifname cached and save if_indextoname() */ - ifname_guess = nm_platform_link_get_name (self, ifindex); + /* we don't have an @ifname_guess argument to make the API nicer. + * But still do a cache-lookup first. Chances are good that we have + * the right ifname cached and save if_indextoname() */ + ifname_guess = nm_platform_link_get_name(self, ifindex); - return nmp_utils_sysctl_open_netdir (ifindex, ifname_guess, out_ifname); + return nmp_utils_sysctl_open_netdir(ifindex, ifname_guess, out_ifname); } /** @@ -525,14 +547,18 @@ nm_platform_sysctl_open_netdir (NMPlatform *self, int ifindex, char *out_ifname) * Returns: %TRUE on success. */ gboolean -nm_platform_sysctl_set (NMPlatform *self, const char *pathid, int dirfd, const char *path, const char *value) +nm_platform_sysctl_set(NMPlatform *self, + const char *pathid, + int dirfd, + const char *path, + const char *value) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (path, FALSE); - g_return_val_if_fail (value, FALSE); + g_return_val_if_fail(path, FALSE); + g_return_val_if_fail(value, FALSE); - return klass->sysctl_set (self, pathid, dirfd, path, value); + return klass->sysctl_set(self, pathid, dirfd, path, value); } /** @@ -554,104 +580,107 @@ nm_platform_sysctl_set (NMPlatform *self, const char *pathid, int dirfd, const c * that the function can be used safely on all /proc and /sys files, * independently of how /proc/sys/kernel/sysctl_writes_strict is configured. */ -void nm_platform_sysctl_set_async (NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - const char *const *values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable *cancellable) +void +nm_platform_sysctl_set_async(NMPlatform * self, + const char * pathid, + int dirfd, + const char * path, + const char *const * values, + NMPlatformAsyncCallback callback, + gpointer data, + GCancellable * cancellable) { - _CHECK_SELF_VOID (self, klass); + _CHECK_SELF_VOID(self, klass); - klass->sysctl_set_async (self, pathid, dirfd, path, values, callback, data, cancellable); + klass->sysctl_set_async(self, pathid, dirfd, path, values, callback, data, cancellable); } - gboolean -nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self, - const char *iface, - int value) +nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(NMPlatform *self, const char *iface, int value) { - const char *path; - gint64 cur; - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + const char *path; + gint64 cur; + char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - /* the hop-limit provided via RA is uint8. */ - if (value > 0xFF) - return FALSE; + /* the hop-limit provided via RA is uint8. */ + if (value > 0xFF) + return FALSE; - /* don't allow unreasonable small values */ - if (value < 10) - return FALSE; + /* don't allow unreasonable small values */ + if (value < 10) + return FALSE; - path = nm_utils_sysctl_ip_conf_path (AF_INET6, buf, iface, "hop_limit"); - cur = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), 10, 1, G_MAXINT32, -1); + path = nm_utils_sysctl_ip_conf_path(AF_INET6, buf, iface, "hop_limit"); + cur = nm_platform_sysctl_get_int_checked(self, + NMP_SYSCTL_PATHID_ABSOLUTE(path), + 10, + 1, + G_MAXINT32, + -1); - /* only allow increasing the hop-limit to avoid DOS by an attacker - * setting a low hop-limit (CVE-2015-2924, rh#1209902) */ + /* only allow increasing the hop-limit to avoid DOS by an attacker + * setting a low hop-limit (CVE-2015-2924, rh#1209902) */ - if (value < cur) - return FALSE; - if (value != cur) { - char svalue[20]; + if (value < cur) + return FALSE; + if (value != cur) { + char svalue[20]; - sprintf (svalue, "%d", value); - nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), svalue); - } + sprintf(svalue, "%d", value); + nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), svalue); + } - return TRUE; + return TRUE; } gboolean -nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NMPlatform *self, - const char *iface, - guint value_ms) +nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(NMPlatform *self, + const char *iface, + guint value_ms) { - char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - char str[128]; - guint clamped; + char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + char str[128]; + guint clamped; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - if (!value_ms) - return TRUE; + if (!value_ms) + return TRUE; - /* RFC 4861 says the value can't be greater than one hour. - * Also use a reasonable lower threshold. */ - clamped = NM_CLAMP (value_ms, 100, 3600000); - nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", iface); - nm_sprintf_buf (str, "%u", clamped); - if (!nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str)) - return FALSE; + /* RFC 4861 says the value can't be greater than one hour. + * Also use a reasonable lower threshold. */ + clamped = NM_CLAMP(value_ms, 100, 3600000); + nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", iface); + nm_sprintf_buf(str, "%u", clamped); + if (!nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str)) + return FALSE; - /* Set stale time in the same way as kernel */ - nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/gc_stale_time", iface); - nm_sprintf_buf (str, "%u", clamped * 3 / 1000); + /* Set stale time in the same way as kernel */ + nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/gc_stale_time", iface); + nm_sprintf_buf(str, "%u", clamped * 3 / 1000); - return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str); + return nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str); } gboolean -nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NMPlatform *self, - const char *iface, - guint value_ms) +nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(NMPlatform *self, + const char *iface, + guint value_ms) { - char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - char str[128]; + char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + char str[128]; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - if (!value_ms) - return TRUE; + if (!value_ms) + return TRUE; - nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms", iface); - nm_sprintf_buf (str, "%u", NM_CLAMP (value_ms, 10, 3600000)); + nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms", iface); + nm_sprintf_buf(str, "%u", NM_CLAMP(value_ms, 10, 3600000)); - return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str); + return nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str); } /** @@ -667,13 +696,13 @@ nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NMPlatform *self, * If the path does not exist, %NULL is returned and %errno set to %ENOENT. */ char * -nm_platform_sysctl_get (NMPlatform *self, const char *pathid, int dirfd, const char *path) +nm_platform_sysctl_get(NMPlatform *self, const char *pathid, int dirfd, const char *path) { - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - g_return_val_if_fail (path, NULL); + g_return_val_if_fail(path, NULL); - return klass->sysctl_get (self, pathid, dirfd, path); + return klass->sysctl_get(self, pathid, dirfd, path); } /** @@ -691,9 +720,20 @@ nm_platform_sysctl_get (NMPlatform *self, const char *pathid, int dirfd, const c * value, on success %errno will be set to zero. */ gint32 -nm_platform_sysctl_get_int32 (NMPlatform *self, const char *pathid, int dirfd, const char *path, gint32 fallback) -{ - return nm_platform_sysctl_get_int_checked (self, pathid, dirfd, path, 10, G_MININT32, G_MAXINT32, fallback); +nm_platform_sysctl_get_int32(NMPlatform *self, + const char *pathid, + int dirfd, + const char *path, + gint32 fallback) +{ + return nm_platform_sysctl_get_int_checked(self, + pathid, + dirfd, + path, + 10, + G_MININT32, + G_MAXINT32, + fallback); } /** @@ -718,186 +758,184 @@ nm_platform_sysctl_get_int32 (NMPlatform *self, const char *pathid, int dirfd, c * is set to ENOENT. */ gint64 -nm_platform_sysctl_get_int_checked (NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - guint base, - gint64 min, - gint64 max, - gint64 fallback) -{ - char *value = NULL; - gint32 ret; - int errsv; - - _CHECK_SELF (self, klass, fallback); - - g_return_val_if_fail (path, fallback); - - if (!path) { - errno = EINVAL; - return fallback; - } - - value = nm_platform_sysctl_get (self, pathid, dirfd, path); - if (!value) { - /* nm_platform_sysctl_get() set errno to ENOENT if the file does not exist. - * Propagate/preserve that. */ - if (errno != ENOENT) - errno = EINVAL; - return fallback; - } - - ret = _nm_utils_ascii_str_to_int64 (value, base, min, max, fallback); - errsv = errno; - g_free (value); - errno = errsv; - return ret; +nm_platform_sysctl_get_int_checked(NMPlatform *self, + const char *pathid, + int dirfd, + const char *path, + guint base, + gint64 min, + gint64 max, + gint64 fallback) +{ + char * value = NULL; + gint32 ret; + int errsv; + + _CHECK_SELF(self, klass, fallback); + + g_return_val_if_fail(path, fallback); + + if (!path) { + errno = EINVAL; + return fallback; + } + + value = nm_platform_sysctl_get(self, pathid, dirfd, path); + if (!value) { + /* nm_platform_sysctl_get() set errno to ENOENT if the file does not exist. + * Propagate/preserve that. */ + if (errno != ENOENT) + errno = EINVAL; + return fallback; + } + + ret = _nm_utils_ascii_str_to_int64(value, base, min, max, fallback); + errsv = errno; + g_free(value); + errno = errsv; + return ret; } /*****************************************************************************/ char * -nm_platform_sysctl_ip_conf_get (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property) +nm_platform_sysctl_ip_conf_get(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property) { - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - return nm_platform_sysctl_get (self, - NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family, - buf, - ifname, - property))); + return nm_platform_sysctl_get( + self, + NMP_SYSCTL_PATHID_ABSOLUTE( + nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property))); } gint64 -nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - guint base, - gint64 min, - gint64 max, - gint64 fallback) -{ - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - - return nm_platform_sysctl_get_int_checked (self, - NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family, - buf, - ifname, - property)), - base, - min, - max, - fallback); +nm_platform_sysctl_ip_conf_get_int_checked(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property, + guint base, + gint64 min, + gint64 max, + gint64 fallback) +{ + char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + + return nm_platform_sysctl_get_int_checked( + self, + NMP_SYSCTL_PATHID_ABSOLUTE( + nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property)), + base, + min, + max, + fallback); } gboolean -nm_platform_sysctl_ip_conf_set (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - const char *value) +nm_platform_sysctl_ip_conf_set(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property, + const char *value) { - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - return nm_platform_sysctl_set (self, - NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family, - buf, - ifname, - property)), - value); + return nm_platform_sysctl_set( + self, + NMP_SYSCTL_PATHID_ABSOLUTE( + nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property)), + value); } gboolean -nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - gint64 value) +nm_platform_sysctl_ip_conf_set_int64(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property, + gint64 value) { - char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; - char s[64]; + char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + char s[64]; - return nm_platform_sysctl_set (self, - NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (addr_family, - buf, - ifname, - property)), - nm_sprintf_buf (s, "%"G_GINT64_FORMAT, value)); + return nm_platform_sysctl_set( + self, + NMP_SYSCTL_PATHID_ABSOLUTE( + nm_utils_sysctl_ip_conf_path(addr_family, buf, ifname, property)), + nm_sprintf_buf(s, "%" G_GINT64_FORMAT, value)); } int -nm_platform_sysctl_ip_conf_get_rp_filter_ipv4 (NMPlatform *self, - const char *ifname, - gboolean consider_all, - gboolean *out_due_to_all) -{ - int val, val_all; - - NM_SET_OUT (out_due_to_all, FALSE); - - if (!ifname) - return -1; - - val = nm_platform_sysctl_ip_conf_get_int_checked (self, - AF_INET, - ifname, - "rp_filter", - 10, 0, 2, -1); - if (val == -1) - return -1; - - /* the effectively used value is the rp_filter sysctl value of MAX(all,ifname). - * Note that this is the numerical MAX(), despite rp_filter "1" being more strict - * than "2". */ - if ( val < 2 - && consider_all - && !nm_streq (ifname, "all")) { - val_all = nm_platform_sysctl_ip_conf_get_int_checked (self, - AF_INET, - "all", - "rp_filter", - 10, 0, 2, val); - if (val_all > val) { - val = val_all; - NM_SET_OUT (out_due_to_all, TRUE); - } - } - - return val; +nm_platform_sysctl_ip_conf_get_rp_filter_ipv4(NMPlatform *self, + const char *ifname, + gboolean consider_all, + gboolean * out_due_to_all) +{ + int val, val_all; + + NM_SET_OUT(out_due_to_all, FALSE); + + if (!ifname) + return -1; + + val = nm_platform_sysctl_ip_conf_get_int_checked(self, + AF_INET, + ifname, + "rp_filter", + 10, + 0, + 2, + -1); + if (val == -1) + return -1; + + /* the effectively used value is the rp_filter sysctl value of MAX(all,ifname). + * Note that this is the numerical MAX(), despite rp_filter "1" being more strict + * than "2". */ + if (val < 2 && consider_all && !nm_streq(ifname, "all")) { + val_all = nm_platform_sysctl_ip_conf_get_int_checked(self, + AF_INET, + "all", + "rp_filter", + 10, + 0, + 2, + val); + if (val_all > val) { + val = val_all; + NM_SET_OUT(out_due_to_all, TRUE); + } + } + + return val; } /*****************************************************************************/ static int -_link_get_all_presort (gconstpointer p_a, - gconstpointer p_b, - gpointer sort_by_name) +_link_get_all_presort(gconstpointer p_a, gconstpointer p_b, gpointer sort_by_name) { - const NMPlatformLink *a = NMP_OBJECT_CAST_LINK (*((const NMPObject **) p_a)); - const NMPlatformLink *b = NMP_OBJECT_CAST_LINK (*((const NMPObject **) p_b)); + const NMPlatformLink *a = NMP_OBJECT_CAST_LINK(*((const NMPObject **) p_a)); + const NMPlatformLink *b = NMP_OBJECT_CAST_LINK(*((const NMPObject **) p_b)); - /* Loopback always first */ - if (a->ifindex == 1) - return -1; - if (b->ifindex == 1) - return 1; + /* Loopback always first */ + if (a->ifindex == 1) + return -1; + if (b->ifindex == 1) + return 1; - if (GPOINTER_TO_INT (sort_by_name)) { - /* Initialized links first */ - if (a->initialized > b->initialized) - return -1; - if (a->initialized < b->initialized) - return 1; + if (GPOINTER_TO_INT(sort_by_name)) { + /* Initialized links first */ + if (a->initialized > b->initialized) + return -1; + if (a->initialized < b->initialized) + return 1; - return strcmp (a->name, b->name); - } else - return a->ifindex - b->ifindex; + return strcmp(a->name, b->name); + } else + return a->ifindex - b->ifindex; } /** @@ -909,136 +947,131 @@ _link_get_all_presort (gconstpointer p_a, * owned by the caller and should be freed with g_ptr_array_unref(). */ GPtrArray * -nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name) -{ - gs_unref_ptrarray GPtrArray *links = NULL; - GPtrArray *result; - guint i, nresult; - gs_unref_hashtable GHashTable *unseen = NULL; - const NMPlatformLink *item; - NMPLookup lookup; - - _CHECK_SELF (self, klass, NULL); - - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK); - links = nm_dedup_multi_objs_to_ptr_array_head (nm_platform_lookup (self, &lookup), - NULL, NULL); - if (!links) - return NULL; - - for (i = 0; i < links->len; ) { - if (!nmp_object_is_visible (links->pdata[i])) - g_ptr_array_remove_index_fast (links, i); - else - i++; - } - - if (links->len == 0) - return NULL; - - /* first sort the links by their ifindex or name. Below we will sort - * further by moving children/slaves to the end. */ - g_ptr_array_sort_with_data (links, _link_get_all_presort, GINT_TO_POINTER (sort_by_name)); - - unseen = g_hash_table_new (nm_direct_hash, NULL); - for (i = 0; i < links->len; i++) { - item = NMP_OBJECT_CAST_LINK (links->pdata[i]); - nm_assert (item->ifindex > 0); - if (!g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL)) - nm_assert_not_reached (); - } +nm_platform_link_get_all(NMPlatform *self, gboolean sort_by_name) +{ + gs_unref_ptrarray GPtrArray *links = NULL; + GPtrArray * result; + guint i, nresult; + gs_unref_hashtable GHashTable *unseen = NULL; + const NMPlatformLink * item; + NMPLookup lookup; + + _CHECK_SELF(self, klass, NULL); + + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); + links = nm_dedup_multi_objs_to_ptr_array_head(nm_platform_lookup(self, &lookup), NULL, NULL); + if (!links) + return NULL; + + for (i = 0; i < links->len;) { + if (!nmp_object_is_visible(links->pdata[i])) + g_ptr_array_remove_index_fast(links, i); + else + i++; + } + + if (links->len == 0) + return NULL; + + /* first sort the links by their ifindex or name. Below we will sort + * further by moving children/slaves to the end. */ + g_ptr_array_sort_with_data(links, _link_get_all_presort, GINT_TO_POINTER(sort_by_name)); + + unseen = g_hash_table_new(nm_direct_hash, NULL); + for (i = 0; i < links->len; i++) { + item = NMP_OBJECT_CAST_LINK(links->pdata[i]); + nm_assert(item->ifindex > 0); + if (!g_hash_table_insert(unseen, GINT_TO_POINTER(item->ifindex), NULL)) + nm_assert_not_reached(); + } #if NM_MORE_ASSERTS - /* Ensure that link_get_all returns a consistent and valid result. */ - for (i = 0; i < links->len; i++) { - item = NMP_OBJECT_CAST_LINK (links->pdata[i]); - - if (!item->ifindex) - continue; - if (item->master != 0) { - g_warn_if_fail (item->master > 0); - g_warn_if_fail (item->master != item->ifindex); - g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->master))); - } - if (item->parent != 0) { - if (item->parent != NM_PLATFORM_LINK_OTHER_NETNS) { - g_warn_if_fail (item->parent > 0); - g_warn_if_fail (item->parent != item->ifindex); - g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))); - } - } - } + /* Ensure that link_get_all returns a consistent and valid result. */ + for (i = 0; i < links->len; i++) { + item = NMP_OBJECT_CAST_LINK(links->pdata[i]); + + if (!item->ifindex) + continue; + if (item->master != 0) { + g_warn_if_fail(item->master > 0); + g_warn_if_fail(item->master != item->ifindex); + g_warn_if_fail(g_hash_table_contains(unseen, GINT_TO_POINTER(item->master))); + } + if (item->parent != 0) { + if (item->parent != NM_PLATFORM_LINK_OTHER_NETNS) { + g_warn_if_fail(item->parent > 0); + g_warn_if_fail(item->parent != item->ifindex); + g_warn_if_fail(g_hash_table_contains(unseen, GINT_TO_POINTER(item->parent))); + } + } + } #endif - /* Re-order the links list such that children/slaves come after all ancestors */ - nm_assert (g_hash_table_size (unseen) == links->len); - nresult = links->len; - result = g_ptr_array_new_full (nresult, (GDestroyNotify) nmp_object_unref); + /* Re-order the links list such that children/slaves come after all ancestors */ + nm_assert(g_hash_table_size(unseen) == links->len); + nresult = links->len; + result = g_ptr_array_new_full(nresult, (GDestroyNotify) nmp_object_unref); - while (TRUE) { - gboolean found_something = FALSE; - guint first_idx = G_MAXUINT; + while (TRUE) { + gboolean found_something = FALSE; + guint first_idx = G_MAXUINT; - for (i = 0; i < links->len; i++) { - item = NMP_OBJECT_CAST_LINK (links->pdata[i]); + for (i = 0; i < links->len; i++) { + item = NMP_OBJECT_CAST_LINK(links->pdata[i]); - if (!item) - continue; + if (!item) + continue; - g_assert (g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex))); + g_assert(g_hash_table_contains(unseen, GINT_TO_POINTER(item->ifindex))); - if (item->master > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->master))) - goto skip; - if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))) - goto skip; + if (item->master > 0 && g_hash_table_contains(unseen, GINT_TO_POINTER(item->master))) + goto skip; + if (item->parent > 0 && g_hash_table_contains(unseen, GINT_TO_POINTER(item->parent))) + goto skip; - g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); - g_ptr_array_add (result, links->pdata[i]); - links->pdata[i] = NULL; - found_something = TRUE; - continue; + g_hash_table_remove(unseen, GINT_TO_POINTER(item->ifindex)); + g_ptr_array_add(result, links->pdata[i]); + links->pdata[i] = NULL; + found_something = TRUE; + continue; skip: - if (first_idx == G_MAXUINT) - first_idx = i; - } - - if (found_something) { - if (first_idx == G_MAXUINT) - break; - } else { - nm_assert (first_idx != G_MAXUINT); - /* There is a loop, pop the first (remaining) element from the list. - * This can happen for veth pairs where each peer is parent of the other end. */ - item = NMP_OBJECT_CAST_LINK (links->pdata[first_idx]); - nm_assert (item); - g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); - g_ptr_array_add (result, links->pdata[first_idx]); - links->pdata[first_idx] = NULL; - } - nm_assert (result->len < nresult); - } - nm_assert (result->len == nresult); - - return result; + if (first_idx == G_MAXUINT) + first_idx = i; + } + + if (found_something) { + if (first_idx == G_MAXUINT) + break; + } else { + nm_assert(first_idx != G_MAXUINT); + /* There is a loop, pop the first (remaining) element from the list. + * This can happen for veth pairs where each peer is parent of the other end. */ + item = NMP_OBJECT_CAST_LINK(links->pdata[first_idx]); + nm_assert(item); + g_hash_table_remove(unseen, GINT_TO_POINTER(item->ifindex)); + g_ptr_array_add(result, links->pdata[first_idx]); + links->pdata[first_idx] = NULL; + } + nm_assert(result->len < nresult); + } + nm_assert(result->len == nresult); + + return result; } /*****************************************************************************/ const NMPObject * -nm_platform_link_get_obj (NMPlatform *self, - int ifindex, - gboolean visible_only) +nm_platform_link_get_obj(NMPlatform *self, int ifindex, gboolean visible_only) { - const NMPObject *obj_cache; + const NMPObject *obj_cache; - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - obj_cache = nmp_cache_lookup_link (nm_platform_get_cache (self), ifindex); - if ( !obj_cache - || ( visible_only - && !nmp_object_is_visible (obj_cache))) - return NULL; - return obj_cache; + obj_cache = nmp_cache_lookup_link(nm_platform_get_cache(self), ifindex); + if (!obj_cache || (visible_only && !nmp_object_is_visible(obj_cache))) + return NULL; + return obj_cache; } /*****************************************************************************/ @@ -1056,9 +1089,9 @@ nm_platform_link_get_obj (NMPlatform *self, * invalidate/modify the returned instance. **/ const NMPlatformLink * -nm_platform_link_get (NMPlatform *self, int ifindex) +nm_platform_link_get(NMPlatform *self, int ifindex) { - return NMP_OBJECT_CAST_LINK (nm_platform_link_get_obj (self, ifindex, TRUE)); + return NMP_OBJECT_CAST_LINK(nm_platform_link_get_obj(self, ifindex, TRUE)); } /** @@ -1069,30 +1102,35 @@ nm_platform_link_get (NMPlatform *self, int ifindex) * Returns: the first #NMPlatformLink instance with the given name. **/ const NMPlatformLink * -nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname) +nm_platform_link_get_by_ifname(NMPlatform *self, const char *ifname) { - const NMPObject *obj; + const NMPObject *obj; - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - if (!ifname || !*ifname) - return NULL; + if (!ifname || !*ifname) + return NULL; - obj = nmp_cache_lookup_link_full (nm_platform_get_cache (self), - 0, ifname, TRUE, NM_LINK_TYPE_NONE, NULL, NULL); - return NMP_OBJECT_CAST_LINK (obj); + obj = nmp_cache_lookup_link_full(nm_platform_get_cache(self), + 0, + ifname, + TRUE, + NM_LINK_TYPE_NONE, + NULL, + NULL); + return NMP_OBJECT_CAST_LINK(obj); } struct _nm_platform_link_get_by_address_data { - gconstpointer data; - guint8 len; + gconstpointer data; + guint8 len; }; static gboolean -_nm_platform_link_get_by_address_match_link (const NMPObject *obj, struct _nm_platform_link_get_by_address_data *d) +_nm_platform_link_get_by_address_match_link(const NMPObject * obj, + struct _nm_platform_link_get_by_address_data *d) { - return obj->link.l_address.len == d->len - && !memcmp (obj->link.l_address.data, d->data, d->len); + return obj->link.l_address.len == d->len && !memcmp(obj->link.l_address.data, d->data, d->len); } /** @@ -1105,56 +1143,63 @@ _nm_platform_link_get_by_address_match_link (const NMPObject *obj, struct _nm_pl * address. **/ const NMPlatformLink * -nm_platform_link_get_by_address (NMPlatform *self, - NMLinkType link_type, - gconstpointer address, - size_t length) +nm_platform_link_get_by_address(NMPlatform * self, + NMLinkType link_type, + gconstpointer address, + size_t length) { - const NMPObject *obj; - struct _nm_platform_link_get_by_address_data d = { - .data = address, - .len = length, - }; + const NMPObject * obj; + struct _nm_platform_link_get_by_address_data d = { + .data = address, + .len = length, + }; - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - if (length == 0) - return NULL; + if (length == 0) + return NULL; - if (length > NM_UTILS_HWADDR_LEN_MAX) - g_return_val_if_reached (NULL); - if (!address) - g_return_val_if_reached (NULL); + if (length > NM_UTILS_HWADDR_LEN_MAX) + g_return_val_if_reached(NULL); + if (!address) + g_return_val_if_reached(NULL); - obj = nmp_cache_lookup_link_full (nm_platform_get_cache (self), - 0, NULL, TRUE, link_type, - (NMPObjectMatchFn) _nm_platform_link_get_by_address_match_link, &d); - return NMP_OBJECT_CAST_LINK (obj); + obj = nmp_cache_lookup_link_full(nm_platform_get_cache(self), + 0, + NULL, + TRUE, + link_type, + (NMPObjectMatchFn) _nm_platform_link_get_by_address_match_link, + &d); + return NMP_OBJECT_CAST_LINK(obj); } static int -_link_add_check_existing (NMPlatform *self, const char *name, NMLinkType type, const NMPlatformLink **out_link) -{ - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get_by_ifname (self, name); - if (pllink) { - gboolean wrong_type; - - wrong_type = type != NM_LINK_TYPE_NONE && pllink->type != type; - _LOG2D ("link: skip adding link due to existing interface of type %s%s%s", - nm_link_type_to_string (pllink->type), - wrong_type ? ", expected " : "", - wrong_type ? nm_link_type_to_string (type) : ""); - if (out_link) - *out_link = pllink; - if (wrong_type) - return -NME_PL_WRONG_TYPE; - return -NME_PL_EXISTS; - } - if (out_link) - *out_link = NULL; - return 0; +_link_add_check_existing(NMPlatform * self, + const char * name, + NMLinkType type, + const NMPlatformLink **out_link) +{ + const NMPlatformLink *pllink; + + pllink = nm_platform_link_get_by_ifname(self, name); + if (pllink) { + gboolean wrong_type; + + wrong_type = type != NM_LINK_TYPE_NONE && pllink->type != type; + _LOG2D("link: skip adding link due to existing interface of type %s%s%s", + nm_link_type_to_string(pllink->type), + wrong_type ? ", expected " : "", + wrong_type ? nm_link_type_to_string(type) : ""); + if (out_link) + *out_link = pllink; + if (wrong_type) + return -NME_PL_WRONG_TYPE; + return -NME_PL_EXISTS; + } + if (out_link) + *out_link = NULL; + return 0; } /** @@ -1179,103 +1224,128 @@ _link_add_check_existing (NMPlatform *self, const char *name, NMLinkType type, c * Returns: the negative nm-error on failure. */ int -nm_platform_link_add (NMPlatform *self, - NMLinkType type, - const char *name, - int parent, - const void *address, - size_t address_len, - gconstpointer extra_data, - const NMPlatformLink **out_link) -{ - int r; - char addr_buf[NM_UTILS_HWADDR_LEN_MAX * 3]; - char parent_buf[64]; - char buf[512]; - - _CHECK_SELF (self, klass, -NME_BUG); - - g_return_val_if_fail (name, -NME_BUG); - g_return_val_if_fail ((address != NULL) ^ (address_len == 0) , -NME_BUG); - g_return_val_if_fail (address_len <= NM_UTILS_HWADDR_LEN_MAX, -NME_BUG); - g_return_val_if_fail (parent >= 0, -NME_BUG); - - r = _link_add_check_existing (self, name, type, out_link); - if (r < 0) - return r; - - _LOG2D ("link: adding link: " - "%s " /* type */ - "\"%s\"" /* name */ - "%s%s" /* parent */ - "%s%s" /* address */ - "%s" /* extra_data */ - "", - nm_link_type_to_string (type), - name, - parent > 0 ? ", parent " : "", - parent > 0 ? nm_sprintf_buf (parent_buf, "%d", parent) : "", - address ? ", address: " : "", - address ? nm_utils_hwaddr_ntoa_buf (address, address_len, FALSE, addr_buf, sizeof (addr_buf)) : "", - ({ - char *buf_p = buf; - gsize buf_len = sizeof (buf); - - buf[0] = '\0'; - - switch (type) { - case NM_LINK_TYPE_VLAN: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_vlan_to_string ((const NMPlatformLnkVlan *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_VRF: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_vrf_to_string ((const NMPlatformLnkVrf *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_VXLAN: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_vxlan_to_string ((const NMPlatformLnkVxlan *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_VETH: - nm_sprintf_buf (buf, ", veth-peer \"%s\"", (const char *) extra_data); - break; - case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_gre_to_string ((const NMPlatformLnkGre *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_SIT: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_sit_to_string ((const NMPlatformLnkSit *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_IP6TNL: - case NM_LINK_TYPE_IP6GRE: - case NM_LINK_TYPE_IP6GRETAP: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_ip6tnl_to_string ((const NMPlatformLnkIp6Tnl *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_IPIP: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_ipip_to_string ((const NMPlatformLnkIpIp *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_MACSEC: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_macsec_to_string ((const NMPlatformLnkMacsec *) extra_data, buf_p, buf_len); - break; - case NM_LINK_TYPE_MACVLAN: - case NM_LINK_TYPE_MACVTAP: - nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); - nm_platform_lnk_macvlan_to_string ((const NMPlatformLnkMacvlan *) extra_data, buf_p, buf_len); - break; - default: - nm_assert (!extra_data); - break; - } - - buf; - })); - - return klass->link_add (self, type, name, parent, address, address_len, extra_data, out_link); +nm_platform_link_add(NMPlatform * self, + NMLinkType type, + const char * name, + int parent, + const void * address, + size_t address_len, + gconstpointer extra_data, + const NMPlatformLink **out_link) +{ + int r; + char addr_buf[NM_UTILS_HWADDR_LEN_MAX * 3]; + char parent_buf[64]; + char buf[512]; + + _CHECK_SELF(self, klass, -NME_BUG); + + g_return_val_if_fail(name, -NME_BUG); + g_return_val_if_fail((address != NULL) ^ (address_len == 0), -NME_BUG); + g_return_val_if_fail(address_len <= NM_UTILS_HWADDR_LEN_MAX, -NME_BUG); + g_return_val_if_fail(parent >= 0, -NME_BUG); + + r = _link_add_check_existing(self, name, type, out_link); + if (r < 0) + return r; + + _LOG2D("link: adding link: " + "%s " /* type */ + "\"%s\"" /* name */ + "%s%s" /* parent */ + "%s%s" /* address */ + "%s" /* extra_data */ + "", + nm_link_type_to_string(type), + name, + parent > 0 ? ", parent " : "", + parent > 0 ? nm_sprintf_buf(parent_buf, "%d", parent) : "", + address ? ", address: " : "", + address ? _nm_utils_hwaddr_ntoa(address, address_len, FALSE, addr_buf, sizeof(addr_buf)) + : "", + ({ + char *buf_p = buf; + gsize buf_len = sizeof(buf); + + buf[0] = '\0'; + + switch (type) { + case NM_LINK_TYPE_BRIDGE: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_bridge_to_string((const NMPlatformLnkBridge *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_VLAN: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_vlan_to_string((const NMPlatformLnkVlan *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_VRF: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_vrf_to_string((const NMPlatformLnkVrf *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_VXLAN: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_vxlan_to_string((const NMPlatformLnkVxlan *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_VETH: + nm_sprintf_buf(buf, ", veth-peer \"%s\"", (const char *) extra_data); + break; + case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_GRETAP: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_gre_to_string((const NMPlatformLnkGre *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_SIT: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_sit_to_string((const NMPlatformLnkSit *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_IP6TNL: + case NM_LINK_TYPE_IP6GRE: + case NM_LINK_TYPE_IP6GRETAP: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_ip6tnl_to_string((const NMPlatformLnkIp6Tnl *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_IPIP: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_ipip_to_string((const NMPlatformLnkIpIp *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_MACSEC: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_macsec_to_string((const NMPlatformLnkMacsec *) extra_data, + buf_p, + buf_len); + break; + case NM_LINK_TYPE_MACVLAN: + case NM_LINK_TYPE_MACVTAP: + nm_utils_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_macvlan_to_string((const NMPlatformLnkMacvlan *) extra_data, + buf_p, + buf_len); + break; + default: + nm_assert(!extra_data); + break; + } + + buf; + })); + + return klass->link_add(self, type, name, parent, address, address_len, extra_data, out_link); } /** @@ -1284,14 +1354,14 @@ nm_platform_link_add (NMPlatform *self, * @ifindex: Interface index */ gboolean -nm_platform_link_delete (NMPlatform *self, int ifindex) +nm_platform_link_delete(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - _LOG3D ("link: deleting"); - return klass->link_delete (self, ifindex); + _LOG3D("link: deleting"); + return klass->link_delete(self, ifindex); } /** @@ -1303,15 +1373,15 @@ nm_platform_link_delete (NMPlatform *self, int ifindex) * Returns: %TRUE on success. */ gboolean -nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd) +nm_platform_link_set_netns(NMPlatform *self, int ifindex, int netns_fd) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (netns_fd > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(netns_fd > 0, FALSE); - _LOG3D ("link: move link to network namespace with fd %d", netns_fd); - return klass->link_set_netns (self, ifindex, netns_fd); + _LOG3D("link: move link to network namespace with fd %d", netns_fd); + return klass->link_set_netns(self, ifindex, netns_fd); } /** @@ -1323,28 +1393,28 @@ nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd) * or 0. Interface name is owned by #NMPlatform, don't free it. */ int -nm_platform_link_get_ifindex (NMPlatform *self, const char *name) +nm_platform_link_get_ifindex(NMPlatform *self, const char *name) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get_by_ifname (self, name); - return pllink ? pllink->ifindex : 0; + pllink = nm_platform_link_get_by_ifname(self, name); + return pllink ? pllink->ifindex : 0; } const char * -nm_platform_if_indextoname (NMPlatform *self, int ifindex, char out_ifname[static 16 /* IFNAMSIZ */]) +nm_platform_if_indextoname(NMPlatform *self, int ifindex, char out_ifname[static 16 /* IFNAMSIZ */]) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - return nmp_utils_if_indextoname (ifindex, out_ifname); + return nmp_utils_if_indextoname(ifindex, out_ifname); } int -nm_platform_if_nametoindex (NMPlatform *self, const char *ifname) +nm_platform_if_nametoindex(NMPlatform *self, const char *ifname) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - return nmp_utils_if_nametoindex (ifname); + return nmp_utils_if_nametoindex(ifname); } /** @@ -1356,12 +1426,12 @@ nm_platform_if_nametoindex (NMPlatform *self, const char *ifname) * or %NULL. */ const char * -nm_platform_link_get_name (NMPlatform *self, int ifindex) +nm_platform_link_get_name(NMPlatform *self, int ifindex) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, ifindex); - return pllink ? pllink->name : NULL; + pllink = nm_platform_link_get(self, ifindex); + return pllink ? pllink->name : NULL; } /** @@ -1373,12 +1443,12 @@ nm_platform_link_get_name (NMPlatform *self, int ifindex) * NM_LINK_TYPE_NONE is returned. */ NMLinkType -nm_platform_link_get_type (NMPlatform *self, int ifindex) +nm_platform_link_get_type(NMPlatform *self, int ifindex) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, ifindex); - return pllink ? pllink->type : NM_LINK_TYPE_NONE; + pllink = nm_platform_link_get(self, ifindex); + return pllink ? pllink->type : NM_LINK_TYPE_NONE; } /** @@ -1391,46 +1461,43 @@ nm_platform_link_get_type (NMPlatform *self, int ifindex) * other cases it may not. On error, %NULL is returned. */ const char * -nm_platform_link_get_type_name (NMPlatform *self, int ifindex) +nm_platform_link_get_type_name(NMPlatform *self, int ifindex) { - const NMPObject *obj; + const NMPObject *obj; - obj = nm_platform_link_get_obj (self, ifindex, TRUE); - if (!obj) - return NULL; + obj = nm_platform_link_get_obj(self, ifindex, TRUE); + if (!obj) + return NULL; - if (obj->link.type != NM_LINK_TYPE_UNKNOWN) { - /* We could detect the @link_type. In this case the function returns - * our internal module names, which differs from rtnl_link_get_type(): - * - NM_LINK_TYPE_INFINIBAND (gives "infiniband", instead of "ipoib") - * - NM_LINK_TYPE_TAP (gives "tap", instead of "tun"). - * Note that this functions is only used by NMDeviceGeneric to - * set type_description. */ - return nm_link_type_to_string (obj->link.type); - } - /* Link type not detected. Fallback to rtnl_link_get_type()/IFLA_INFO_KIND. */ - return obj->link.kind ?: "unknown"; + if (obj->link.type != NM_LINK_TYPE_UNKNOWN) { + /* We could detect the @link_type. In this case the function returns + * our internal module names, which differs from rtnl_link_get_type(): + * - NM_LINK_TYPE_INFINIBAND (gives "infiniband", instead of "ipoib") + * - NM_LINK_TYPE_TAP (gives "tap", instead of "tun"). + * Note that this functions is only used by NMDeviceGeneric to + * set type_description. */ + return nm_link_type_to_string(obj->link.type); + } + /* Link type not detected. Fallback to rtnl_link_get_type()/IFLA_INFO_KIND. */ + return obj->link.kind ?: "unknown"; } static gboolean -link_get_udev_property (NMPlatform *self, - int ifindex, - const char *name, - const char **out_value) +link_get_udev_property(NMPlatform *self, int ifindex, const char *name, const char **out_value) { - struct udev_device *udevice = NULL; - const char *uproperty; + struct udev_device *udevice = NULL; + const char * uproperty; - udevice = nm_platform_link_get_udev_device (self, ifindex); - if (!udevice) - return FALSE; + udevice = nm_platform_link_get_udev_device(self, ifindex); + if (!udevice) + return FALSE; - uproperty = udev_device_get_property_value (udevice, name); - if (!uproperty) - return FALSE; + uproperty = udev_device_get_property_value(udevice, name); + if (!uproperty) + return FALSE; - NM_SET_OUT (out_value, uproperty); - return TRUE; + NM_SET_OUT(out_value, uproperty); + return TRUE; } /** @@ -1443,16 +1510,16 @@ link_get_udev_property (NMPlatform *self, * %FALSE otherwise (with @unmanaged unmodified). */ gboolean -nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanaged) +nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex, gboolean *unmanaged) { - const char *value; + const char *value; - if (link_get_udev_property (self, ifindex, "NM_UNMANAGED", &value)) { - NM_SET_OUT (unmanaged, nm_udev_utils_property_as_boolean (value)); - return TRUE; - } + if (link_get_udev_property(self, ifindex, "NM_UNMANAGED", &value)) { + NM_SET_OUT(unmanaged, nm_udev_utils_property_as_boolean(value)); + return TRUE; + } - return FALSE; + return FALSE; } /** @@ -1464,9 +1531,9 @@ nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanag * a physical device. */ gboolean -nm_platform_link_is_software (NMPlatform *self, int ifindex) +nm_platform_link_is_software(NMPlatform *self, int ifindex) { - return nm_link_type_is_software (nm_platform_link_get_type (self, ifindex)); + return nm_link_type_is_software(nm_platform_link_get_type(self, ifindex)); } /** @@ -1478,9 +1545,9 @@ nm_platform_link_is_software (NMPlatform *self, int ifindex) * other interfaces. */ gboolean -nm_platform_link_supports_slaves (NMPlatform *self, int ifindex) +nm_platform_link_supports_slaves(NMPlatform *self, int ifindex) { - return nm_link_type_supports_slaves (nm_platform_link_get_type (self, ifindex)); + return nm_link_type_supports_slaves(nm_platform_link_get_type(self, ifindex)); } /** @@ -1491,36 +1558,34 @@ nm_platform_link_supports_slaves (NMPlatform *self, int ifindex) * Reload the cache for ifindex synchronously. */ gboolean -nm_platform_link_refresh (NMPlatform *self, int ifindex) +nm_platform_link_refresh(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - if (klass->link_refresh) - return klass->link_refresh (self, ifindex); + if (klass->link_refresh) + return klass->link_refresh(self, ifindex); - return TRUE; + return TRUE; } int -nm_platform_link_get_ifi_flags (NMPlatform *self, - int ifindex, - guint requested_flags) +nm_platform_link_get_ifi_flags(NMPlatform *self, int ifindex, guint requested_flags) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - /* include invisible links (only in netlink, not udev). */ - pllink = NMP_OBJECT_CAST_LINK (nm_platform_link_get_obj (self, ifindex, FALSE)); - if (!pllink) - return -ENODEV; + /* include invisible links (only in netlink, not udev). */ + pllink = NMP_OBJECT_CAST_LINK(nm_platform_link_get_obj(self, ifindex, FALSE)); + if (!pllink) + return -ENODEV; - /* Errors are signaled as negative values. That means, you cannot request - * the most significant bit (2^31) with this API. Assert against that. */ - nm_assert ((int) requested_flags >= 0); - nm_assert (requested_flags < (guint) G_MAXINT); + /* Errors are signaled as negative values. That means, you cannot request + * the most significant bit (2^31) with this API. Assert against that. */ + nm_assert((int) requested_flags >= 0); + nm_assert(requested_flags < (guint) G_MAXINT); - return (int) (pllink->n_ifi_flags & requested_flags); + return (int) (pllink->n_ifi_flags & requested_flags); } /** @@ -1531,9 +1596,9 @@ nm_platform_link_get_ifi_flags (NMPlatform *self, * Check if the interface is up. */ gboolean -nm_platform_link_is_up (NMPlatform *self, int ifindex) +nm_platform_link_is_up(NMPlatform *self, int ifindex) { - return nm_platform_link_get_ifi_flags (self, ifindex, IFF_UP) == IFF_UP; + return nm_platform_link_get_ifi_flags(self, ifindex, IFF_UP) == IFF_UP; } /** @@ -1544,12 +1609,12 @@ nm_platform_link_is_up (NMPlatform *self, int ifindex) * Check if the interface is connected. */ gboolean -nm_platform_link_is_connected (NMPlatform *self, int ifindex) +nm_platform_link_is_connected(NMPlatform *self, int ifindex) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, ifindex); - return pllink ? pllink->connected : FALSE; + pllink = nm_platform_link_get(self, ifindex); + return pllink ? pllink->connected : FALSE; } /** @@ -1560,17 +1625,17 @@ nm_platform_link_is_connected (NMPlatform *self, int ifindex) * Check if the interface is configured to use ARP. */ gboolean -nm_platform_link_uses_arp (NMPlatform *self, int ifindex) +nm_platform_link_uses_arp(NMPlatform *self, int ifindex) { - int f; + int f; - f = nm_platform_link_get_ifi_flags (self, ifindex, IFF_NOARP); + f = nm_platform_link_get_ifi_flags(self, ifindex, IFF_NOARP); - if (f < 0) - return FALSE; - if (f == IFF_NOARP) - return FALSE; - return TRUE; + if (f < 0) + return FALSE; + if (f == IFF_NOARP) + return FALSE; + return TRUE; } /** @@ -1584,43 +1649,43 @@ nm_platform_link_uses_arp (NMPlatform *self, int ifindex) * Returns: %TRUE a tokenized identifier was available */ gboolean -nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid) +nm_platform_link_set_ipv6_token(NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - if (klass->link_set_token) - return klass->link_set_token (self, ifindex, iid); - return FALSE; + if (klass->link_set_token) + return klass->link_set_token(self, ifindex, iid); + return FALSE; } const char * -nm_platform_link_get_udi (NMPlatform *self, int ifindex) +nm_platform_link_get_udi(NMPlatform *self, int ifindex) { - struct udev_device *device; + struct udev_device *device; - device = nm_platform_link_get_udev_device (self, ifindex); - return device ? udev_device_get_syspath (device) : NULL; + device = nm_platform_link_get_udev_device(self, ifindex); + return device ? udev_device_get_syspath(device) : NULL; } const char * -nm_platform_link_get_path (NMPlatform *self, int ifindex) +nm_platform_link_get_path(NMPlatform *self, int ifindex) { - const char *value = NULL; + const char *value = NULL; - link_get_udev_property (self, ifindex, "ID_PATH", &value); + link_get_udev_property(self, ifindex, "ID_PATH", &value); - return value; + return value; } struct udev_device * -nm_platform_link_get_udev_device (NMPlatform *self, int ifindex) +nm_platform_link_get_udev_device(NMPlatform *self, int ifindex) { - const NMPObject *obj_cache; + const NMPObject *obj_cache; - obj_cache = nm_platform_link_get_obj (self, ifindex, FALSE); - return obj_cache ? obj_cache->_link.udev.device : NULL; + obj_cache = nm_platform_link_get_obj(self, ifindex, FALSE); + return obj_cache ? obj_cache->_link.udev.device : NULL; } /** @@ -1635,14 +1700,14 @@ nm_platform_link_get_udev_device (NMPlatform *self, int ifindex) * Returns: %TRUE if NM handles the IPv6LL address for @ifindex */ gboolean -nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex) +nm_platform_link_get_user_ipv6ll_enabled(NMPlatform *self, int ifindex) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, ifindex); - if (pllink && pllink->inet6_addr_gen_mode_inv) - return _nm_platform_uint8_inv (pllink->inet6_addr_gen_mode_inv) == NM_IN6_ADDR_GEN_MODE_NONE; - return FALSE; + pllink = nm_platform_link_get(self, ifindex); + if (pllink && pllink->inet6_addr_gen_mode_inv) + return _nm_platform_uint8_inv(pllink->inet6_addr_gen_mode_inv) == NM_IN6_ADDR_GEN_MODE_NONE; + return FALSE; } /** @@ -1657,13 +1722,13 @@ nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex) * Returns: the negative nm-error on failure. */ int -nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolean enabled) +nm_platform_link_set_user_ipv6ll_enabled(NMPlatform *self, int ifindex, gboolean enabled) { - _CHECK_SELF (self, klass, -NME_BUG); + _CHECK_SELF(self, klass, -NME_BUG); - g_return_val_if_fail (ifindex > 0, -NME_BUG); + g_return_val_if_fail(ifindex > 0, -NME_BUG); - return klass->link_set_user_ipv6ll_enabled (self, ifindex, enabled); + return klass->link_set_user_ipv6ll_enabled(self, ifindex, enabled); } /** @@ -1675,19 +1740,18 @@ nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolea * Set interface MAC address. */ int -nm_platform_link_set_address (NMPlatform *self, int ifindex, gconstpointer address, size_t length) +nm_platform_link_set_address(NMPlatform *self, int ifindex, gconstpointer address, size_t length) { - gs_free char *mac = NULL; + gs_free char *mac = NULL; - _CHECK_SELF (self, klass, -NME_BUG); + _CHECK_SELF(self, klass, -NME_BUG); - g_return_val_if_fail (ifindex > 0, -NME_BUG); - g_return_val_if_fail (address, -NME_BUG); - g_return_val_if_fail (length > 0, -NME_BUG); + g_return_val_if_fail(ifindex > 0, -NME_BUG); + g_return_val_if_fail(address, -NME_BUG); + g_return_val_if_fail(length > 0, -NME_BUG); - _LOG3D ("link: setting hardware address to %s", - (mac = nm_utils_hwaddr_ntoa (address, length))); - return klass->link_set_address (self, ifindex, address, length); + _LOG3D("link: setting hardware address to %s", (mac = nm_utils_hwaddr_ntoa(address, length))); + return klass->link_set_address(self, ifindex, address, length); } /** @@ -1700,12 +1764,12 @@ nm_platform_link_set_address (NMPlatform *self, int ifindex, gconstpointer addre * length @length. */ gconstpointer -nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length) +nm_platform_link_get_address(NMPlatform *self, int ifindex, size_t *length) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, ifindex); - return nmp_link_address_get (pllink ? &pllink->l_address : NULL, length); + pllink = nm_platform_link_get(self, ifindex); + return nmp_link_address_get(pllink ? &pllink->l_address : NULL, length); } /** @@ -1720,50 +1784,50 @@ nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length) * address. */ gboolean -nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex, guint8 *buf, size_t *length) +nm_platform_link_get_permanent_address(NMPlatform *self, int ifindex, guint8 *buf, size_t *length) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - if (length) - *length = 0; + if (length) + *length = 0; - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (buf, FALSE); - g_return_val_if_fail (length, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(buf, FALSE); + g_return_val_if_fail(length, FALSE); - if (klass->link_get_permanent_address) - return klass->link_get_permanent_address (self, ifindex, buf, length); - return FALSE; + if (klass->link_get_permanent_address) + return klass->link_get_permanent_address(self, ifindex, buf, length); + return FALSE; } gboolean -nm_platform_link_supports_carrier_detect (NMPlatform *self, int ifindex) +nm_platform_link_supports_carrier_detect(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - return klass->link_supports_carrier_detect (self, ifindex); + return klass->link_supports_carrier_detect(self, ifindex); } gboolean -nm_platform_link_supports_vlans (NMPlatform *self, int ifindex) +nm_platform_link_supports_vlans(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - return klass->link_supports_vlans (self, ifindex); + return klass->link_supports_vlans(self, ifindex); } gboolean -nm_platform_link_supports_sriov (NMPlatform *self, int ifindex) +nm_platform_link_supports_sriov(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - return klass->link_supports_sriov (self, ifindex); + return klass->link_supports_sriov(self, ifindex); } /** @@ -1782,66 +1846,69 @@ nm_platform_link_supports_sriov (NMPlatform *self, int ifindex) * always invoked, and asynchronously. */ void -nm_platform_link_set_sriov_params_async (NMPlatform *self, - int ifindex, - guint num_vfs, - NMTernary autoprobe, - NMPlatformAsyncCallback callback, - gpointer callback_data, - GCancellable *cancellable) +nm_platform_link_set_sriov_params_async(NMPlatform * self, + int ifindex, + guint num_vfs, + NMTernary autoprobe, + NMPlatformAsyncCallback callback, + gpointer callback_data, + GCancellable * cancellable) { - _CHECK_SELF_VOID (self, klass); + _CHECK_SELF_VOID(self, klass); - g_return_if_fail (ifindex > 0); + g_return_if_fail(ifindex > 0); - _LOG3D ("link: setting %u total VFs and autoprobe %d", num_vfs, (int) autoprobe); - klass->link_set_sriov_params_async (self, - ifindex, - num_vfs, - autoprobe, - callback, - callback_data, - cancellable); + _LOG3D("link: setting %u total VFs and autoprobe %d", num_vfs, (int) autoprobe); + klass->link_set_sriov_params_async(self, + ifindex, + num_vfs, + autoprobe, + callback, + callback_data, + cancellable); } gboolean -nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs) +nm_platform_link_set_sriov_vfs(NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs) { - guint i; - _CHECK_SELF (self, klass, FALSE); + guint i; + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - _LOG3D ("link: setting VFs"); - for (i = 0; vfs[i]; i++) { - const NMPlatformVF *vf = vfs[i]; + _LOG3D("link: setting VFs"); + for (i = 0; vfs[i]; i++) { + const NMPlatformVF *vf = vfs[i]; - _LOG3D ("link: VF %s", nm_platform_vf_to_string (vf, NULL, 0)); - } + _LOG3D("link: VF %s", nm_platform_vf_to_string(vf, NULL, 0)); + } - return klass->link_set_sriov_vfs (self, ifindex, vfs); + return klass->link_set_sriov_vfs(self, ifindex, vfs); } gboolean -nm_platform_link_set_bridge_vlans (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans) +nm_platform_link_set_bridge_vlans(NMPlatform * self, + int ifindex, + gboolean on_master, + const NMPlatformBridgeVlan *const *vlans) { - guint i; - _CHECK_SELF (self, klass, FALSE); + guint i; + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - _LOG3D ("link: %s bridge VLANs on %s", - vlans ? "setting" : "clearing", - on_master ? "master" : "self"); - if (vlans) { - for (i = 0; vlans[i]; i++) { - const NMPlatformBridgeVlan *vlan = vlans[i]; + _LOG3D("link: %s bridge VLANs on %s", + vlans ? "setting" : "clearing", + on_master ? "master" : "self"); + if (vlans) { + for (i = 0; vlans[i]; i++) { + const NMPlatformBridgeVlan *vlan = vlans[i]; - _LOG3D ("link: bridge VLAN %s", nm_platform_bridge_vlan_to_string (vlan, NULL, 0)); - } - } + _LOG3D("link: bridge VLAN %s", nm_platform_bridge_vlan_to_string(vlan, NULL, 0)); + } + } - return klass->link_set_bridge_vlans (self, ifindex, on_master, vlans); + return klass->link_set_bridge_vlans(self, ifindex, on_master, vlans); } /** @@ -1853,14 +1920,14 @@ nm_platform_link_set_bridge_vlans (NMPlatform *self, int ifindex, gboolean on_ma * Bring the interface up. */ gboolean -nm_platform_link_set_up (NMPlatform *self, int ifindex, gboolean *out_no_firmware) +nm_platform_link_set_up(NMPlatform *self, int ifindex, gboolean *out_no_firmware) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - _LOG3D ("link: setting up"); - return klass->link_set_up (self, ifindex, out_no_firmware); + _LOG3D("link: setting up"); + return klass->link_set_up(self, ifindex, out_no_firmware); } /** @@ -1871,14 +1938,14 @@ nm_platform_link_set_up (NMPlatform *self, int ifindex, gboolean *out_no_firmwar * Take the interface down. */ gboolean -nm_platform_link_set_down (NMPlatform *self, int ifindex) +nm_platform_link_set_down(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - _LOG3D ("link: setting down"); - return klass->link_set_down (self, ifindex); + _LOG3D("link: setting down"); + return klass->link_set_down(self, ifindex); } /** @@ -1889,14 +1956,14 @@ nm_platform_link_set_down (NMPlatform *self, int ifindex) * Enable ARP on the interface. */ gboolean -nm_platform_link_set_arp (NMPlatform *self, int ifindex) +nm_platform_link_set_arp(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - _LOG3D ("link: setting arp"); - return klass->link_set_arp (self, ifindex); + _LOG3D("link: setting arp"); + return klass->link_set_arp(self, ifindex); } /** @@ -1907,14 +1974,14 @@ nm_platform_link_set_arp (NMPlatform *self, int ifindex) * Disable ARP on the interface. */ gboolean -nm_platform_link_set_noarp (NMPlatform *self, int ifindex) +nm_platform_link_set_noarp(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - _LOG3D ("link: setting noarp"); - return klass->link_set_noarp (self, ifindex); + _LOG3D("link: setting noarp"); + return klass->link_set_noarp(self, ifindex); } /** @@ -1926,15 +1993,15 @@ nm_platform_link_set_noarp (NMPlatform *self, int ifindex) * Set interface MTU. */ int -nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu) +nm_platform_link_set_mtu(NMPlatform *self, int ifindex, guint32 mtu) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (mtu > 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); + g_return_val_if_fail(mtu > 0, FALSE); - _LOG3D ("link: setting mtu %"G_GUINT32_FORMAT, mtu); - return klass->link_set_mtu (self, ifindex, mtu); + _LOG3D("link: setting mtu %" G_GUINT32_FORMAT, mtu); + return klass->link_set_mtu(self, ifindex, mtu); } /** @@ -1945,12 +2012,12 @@ nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu) * Returns: MTU value for the interface or 0 on error. */ guint32 -nm_platform_link_get_mtu (NMPlatform *self, int ifindex) +nm_platform_link_get_mtu(NMPlatform *self, int ifindex) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, ifindex); - return pllink ? pllink->mtu : 0; + pllink = nm_platform_link_get(self, ifindex); + return pllink ? pllink->mtu : 0; } /** @@ -1962,19 +2029,19 @@ nm_platform_link_get_mtu (NMPlatform *self, int ifindex) * Set interface name. */ gboolean -nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name) +nm_platform_link_set_name(NMPlatform *self, int ifindex, const char *name) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (name, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); + g_return_val_if_fail(name, FALSE); - _LOG3D ("link: setting name %s", name); + _LOG3D("link: setting name %s", name); - if (strlen (name) + 1 > IFNAMSIZ) - return FALSE; + if (strlen(name) + 1 > IFNAMSIZ) + return FALSE; - return klass->link_set_name (self, ifindex, name); + return klass->link_set_name(self, ifindex, name); } /** @@ -1992,15 +2059,15 @@ nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name) * or if the interface has no physical port ID. */ char * -nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex) +nm_platform_link_get_physical_port_id(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - g_return_val_if_fail (ifindex >= 0, NULL); + g_return_val_if_fail(ifindex >= 0, NULL); - if (klass->link_get_physical_port_id) - return klass->link_get_physical_port_id (self, ifindex); - return NULL; + if (klass->link_get_physical_port_id) + return klass->link_get_physical_port_id(self, ifindex); + return NULL; } /** @@ -2016,15 +2083,15 @@ nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex) * interface has no device ID. */ guint -nm_platform_link_get_dev_id (NMPlatform *self, int ifindex) +nm_platform_link_get_dev_id(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, 0); + _CHECK_SELF(self, klass, 0); - g_return_val_if_fail (ifindex >= 0, 0); + g_return_val_if_fail(ifindex >= 0, 0); - if (klass->link_get_dev_id) - return klass->link_get_dev_id (self, ifindex); - return 0; + if (klass->link_get_dev_id) + return klass->link_get_dev_id(self, ifindex); + return 0; } /** @@ -2035,15 +2102,15 @@ nm_platform_link_get_dev_id (NMPlatform *self, int ifindex) * Returns: the "Wake-on-LAN" status for @ifindex. */ gboolean -nm_platform_link_get_wake_on_lan (NMPlatform *self, int ifindex) +nm_platform_link_get_wake_on_lan(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - if (klass->link_get_wake_on_lan) - return klass->link_get_wake_on_lan (self, ifindex); - return FALSE; + if (klass->link_get_wake_on_lan) + return klass->link_get_wake_on_lan(self, ifindex); + return FALSE; } /** @@ -2059,21 +2126,21 @@ nm_platform_link_get_wake_on_lan (NMPlatform *self, int ifindex) * failure. */ gboolean -nm_platform_link_get_driver_info (NMPlatform *self, - int ifindex, - char **out_driver_name, - char **out_driver_version, - char **out_fw_version) +nm_platform_link_get_driver_info(NMPlatform *self, + int ifindex, + char ** out_driver_name, + char ** out_driver_version, + char ** out_fw_version) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail(ifindex >= 0, FALSE); - return klass->link_get_driver_info (self, - ifindex, - out_driver_name, - out_driver_version, - out_fw_version); + return klass->link_get_driver_info(self, + ifindex, + out_driver_name, + out_driver_version, + out_fw_version); } /** @@ -2085,15 +2152,15 @@ nm_platform_link_get_driver_info (NMPlatform *self, * Enslave @ifindex to @master. */ gboolean -nm_platform_link_enslave (NMPlatform *self, int master, int ifindex) +nm_platform_link_enslave(NMPlatform *self, int master, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (master > 0, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(master > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - _LOG3D ("link: enslaving to master '%s'", nm_platform_link_get_name (self, master)); - return klass->link_enslave (self, master, ifindex); + _LOG3D("link: enslaving to master '%s'", nm_platform_link_get_name(self, master)); + return klass->link_enslave(self, master, ifindex); } /** @@ -2105,18 +2172,18 @@ nm_platform_link_enslave (NMPlatform *self, int master, int ifindex) * Release @slave from @master. */ gboolean -nm_platform_link_release (NMPlatform *self, int master, int ifindex) +nm_platform_link_release(NMPlatform *self, int master, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (master > 0, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(master > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - if (nm_platform_link_get_master (self, ifindex) != master) - return FALSE; + if (nm_platform_link_get_master(self, ifindex) != master) + return FALSE; - _LOG3D ("link: releasing from master '%s'", nm_platform_link_get_name (self, master)); - return klass->link_release (self, master, ifindex); + _LOG3D("link: releasing from master '%s'", nm_platform_link_get_name(self, master)); + return klass->link_release(self, master, ifindex); } /** @@ -2127,24 +2194,24 @@ nm_platform_link_release (NMPlatform *self, int master, int ifindex) * Returns: Interface index of the slave's master. */ int -nm_platform_link_get_master (NMPlatform *self, int slave) +nm_platform_link_get_master(NMPlatform *self, int slave) { - const NMPlatformLink *pllink; + const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, slave); - return pllink ? pllink->master : 0; + pllink = nm_platform_link_get(self, slave); + return pllink ? pllink->master : 0; } /*****************************************************************************/ gboolean -nm_platform_link_can_assume (NMPlatform *self, int ifindex) +nm_platform_link_can_assume(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - if (klass->link_can_assume) - return klass->link_can_assume (self, ifindex); - g_return_val_if_reached (FALSE); + if (klass->link_can_assume) + return klass->link_can_assume(self, ifindex); + g_return_val_if_reached(FALSE); } /*****************************************************************************/ @@ -2172,209 +2239,224 @@ nm_platform_link_can_assume (NMPlatform *self, int ifindex) * (but don't modify it). */ const NMPObject * -nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link) +nm_platform_link_get_lnk(NMPlatform * self, + int ifindex, + NMLinkType link_type, + const NMPlatformLink **out_link) { - const NMPObject *obj; + const NMPObject *obj; - obj = nm_platform_link_get_obj (self, ifindex, TRUE); - if (!obj) { - NM_SET_OUT (out_link, NULL); - return NULL; - } + obj = nm_platform_link_get_obj(self, ifindex, TRUE); + if (!obj) { + NM_SET_OUT(out_link, NULL); + return NULL; + } - NM_SET_OUT (out_link, &obj->link); + NM_SET_OUT(out_link, &obj->link); - if (!obj->_link.netlink.lnk) - return NULL; - if ( link_type != NM_LINK_TYPE_NONE - && ( link_type != obj->link.type - || link_type != NMP_OBJECT_GET_CLASS (obj->_link.netlink.lnk)->lnk_link_type)) - return NULL; + if (!obj->_link.netlink.lnk) + return NULL; + if (link_type != NM_LINK_TYPE_NONE + && (link_type != obj->link.type + || link_type != NMP_OBJECT_GET_CLASS(obj->_link.netlink.lnk)->lnk_link_type)) + return NULL; - return obj->_link.netlink.lnk; + return obj->_link.netlink.lnk; } static gconstpointer -_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link) +_link_get_lnk(NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link) { - const NMPObject *lnk; + const NMPObject *lnk; - lnk = nm_platform_link_get_lnk (self, ifindex, link_type, out_link); - return lnk ? &lnk->object : NULL; + lnk = nm_platform_link_get_lnk(self, ifindex, link_type, out_link); + return lnk ? &lnk->object : NULL; +} + +const NMPlatformLnkBridge * +nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_BRIDGE, out_link); } const NMPlatformLnkGre * -nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRE, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_GRE, out_link); } const NMPlatformLnkGre * -nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRETAP, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_GRETAP, out_link); } const NMPlatformLnkInfiniband * -nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_infiniband(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link); } const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_ip6tnl(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6TNL, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IP6TNL, out_link); } const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_ip6gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6GRE, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IP6GRE, out_link); } const NMPlatformLnkIp6Tnl * -nm_platform_link_get_lnk_ip6gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_ip6gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6GRETAP, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IP6GRETAP, out_link); } const NMPlatformLnkIpIp * -nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_ipip(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IPIP, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_IPIP, out_link); } const NMPlatformLnkMacsec * -nm_platform_link_get_lnk_macsec (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_macsec(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACSEC, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_MACSEC, out_link); } const NMPlatformLnkMacvlan * -nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_macvlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVLAN, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_MACVLAN, out_link); } const NMPlatformLnkMacvlan * -nm_platform_link_get_lnk_macvtap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_macvtap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVTAP, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_MACVTAP, out_link); } const NMPlatformLnkSit * -nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_sit(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_SIT, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_SIT, out_link); } const NMPlatformLnkTun * -nm_platform_link_get_lnk_tun (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_tun(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_TUN, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_TUN, out_link); } const NMPlatformLnkVlan * -nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_vlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VLAN, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_VLAN, out_link); } const NMPlatformLnkVrf * -nm_platform_link_get_lnk_vrf (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_vrf(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VRF, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_VRF, out_link); } const NMPlatformLnkVxlan * -nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_vxlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VXLAN, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_VXLAN, out_link); } const NMPlatformLnkWireGuard * -nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +nm_platform_link_get_lnk_wireguard(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { - return _link_get_lnk (self, ifindex, NM_LINK_TYPE_WIREGUARD, out_link); + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_WIREGUARD, out_link); } /*****************************************************************************/ -static -NM_UTILS_FLAGS2STR_DEFINE (_wireguard_change_flags_to_string, NMPlatformWireGuardChangeFlags, - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE, "none"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS, "replace-peers"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY, "has-private-key"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT, "has-listen-port"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK, "has-fwmark"), -); - -static -NM_UTILS_FLAGS2STR_DEFINE (_wireguard_change_peer_flags_to_string, NMPlatformWireGuardChangePeerFlags, - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE, "none"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME, "remove"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY, "psk"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL, "ka"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT, "ep"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, "aips"), - NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS, "remove-aips"), -); +static NM_UTILS_FLAGS2STR_DEFINE( + _wireguard_change_flags_to_string, + NMPlatformWireGuardChangeFlags, + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE, "none"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS, "replace-peers"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY, "has-private-key"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT, "has-listen-port"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK, "has-fwmark"), ); + +static NM_UTILS_FLAGS2STR_DEFINE( + _wireguard_change_peer_flags_to_string, + NMPlatformWireGuardChangePeerFlags, + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE, "none"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME, "remove"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY, "psk"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL, "ka"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT, "ep"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, "aips"), + NM_UTILS_FLAGS2STR(NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS, "remove-aips"), ); int -nm_platform_link_wireguard_change (NMPlatform *self, - int ifindex, - const NMPlatformLnkWireGuard *lnk_wireguard, - const NMPWireGuardPeer *peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags) -{ - _CHECK_SELF (self, klass, -NME_BUG); - - nm_assert (klass->link_wireguard_change); - - if (_LOGD_ENABLED ()) { - char buf_lnk[256]; - char buf_peers[512]; - char buf_change_flags[100]; - - buf_peers[0] = '\0'; - if (peers_len > 0) { - char *b = buf_peers; - gsize len = sizeof (buf_peers); - guint i; - - nm_utils_strbuf_append_str (&b, &len, " { "); - for (i = 0; i < peers_len; i++) { - nm_utils_strbuf_append_str (&b, &len, " { "); - nm_platform_wireguard_peer_to_string (&peers[i], b, len); - nm_utils_strbuf_seek_end (&b, &len); - if (peer_flags) { - nm_utils_strbuf_append (&b, &len, - " (%s)", - _wireguard_change_peer_flags_to_string (peer_flags[i], buf_change_flags, sizeof (buf_change_flags))); - } - nm_utils_strbuf_append_str (&b, &len, " } "); - } - nm_utils_strbuf_append_str (&b, &len, "}"); - } - - _LOG3D ("link: change wireguard ifindex %d, %s, (%s), %u peers%s", - ifindex, - nm_platform_lnk_wireguard_to_string (lnk_wireguard, buf_lnk, sizeof (buf_lnk)), - _wireguard_change_flags_to_string (change_flags, buf_change_flags, sizeof (buf_change_flags)), - peers_len, - buf_peers); - } - - return klass->link_wireguard_change (self, - ifindex, - lnk_wireguard, - peers, - peer_flags, - peers_len, - change_flags); +nm_platform_link_wireguard_change(NMPlatform * self, + int ifindex, + const NMPlatformLnkWireGuard * lnk_wireguard, + const NMPWireGuardPeer * peers, + const NMPlatformWireGuardChangePeerFlags *peer_flags, + guint peers_len, + NMPlatformWireGuardChangeFlags change_flags) +{ + _CHECK_SELF(self, klass, -NME_BUG); + + nm_assert(klass->link_wireguard_change); + + if (_LOGD_ENABLED()) { + char buf_lnk[256]; + char buf_peers[512]; + char buf_change_flags[100]; + + buf_peers[0] = '\0'; + if (peers_len > 0) { + char *b = buf_peers; + gsize len = sizeof(buf_peers); + guint i; + + nm_utils_strbuf_append_str(&b, &len, " { "); + for (i = 0; i < peers_len; i++) { + nm_utils_strbuf_append_str(&b, &len, " { "); + nm_platform_wireguard_peer_to_string(&peers[i], b, len); + nm_utils_strbuf_seek_end(&b, &len); + if (peer_flags) { + nm_utils_strbuf_append( + &b, + &len, + " (%s)", + _wireguard_change_peer_flags_to_string(peer_flags[i], + buf_change_flags, + sizeof(buf_change_flags))); + } + nm_utils_strbuf_append_str(&b, &len, " } "); + } + nm_utils_strbuf_append_str(&b, &len, "}"); + } + + _LOG3D("link: change wireguard ifindex %d, %s, (%s), %u peers%s", + ifindex, + nm_platform_lnk_wireguard_to_string(lnk_wireguard, buf_lnk, sizeof(buf_lnk)), + _wireguard_change_flags_to_string(change_flags, + buf_change_flags, + sizeof(buf_change_flags)), + peers_len, + buf_peers); + } + + return klass->link_wireguard_change(self, + ifindex, + lnk_wireguard, + peers, + peer_flags, + peers_len, + change_flags); } /*****************************************************************************/ @@ -2399,433 +2481,451 @@ nm_platform_link_wireguard_change (NMPlatform *self, * Create a TUN or TAP interface. */ int -nm_platform_link_tun_add (NMPlatform *self, - const char *name, - const NMPlatformLnkTun *props, - const NMPlatformLink **out_link, - int *out_fd) +nm_platform_link_tun_add(NMPlatform * self, + const char * name, + const NMPlatformLnkTun *props, + const NMPlatformLink ** out_link, + int * out_fd) { - char b[255]; - int r; + char b[255]; + int r; - _CHECK_SELF (self, klass, -NME_BUG); + _CHECK_SELF(self, klass, -NME_BUG); - g_return_val_if_fail (name, -NME_BUG); - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (NM_IN_SET (props->type, IFF_TUN, IFF_TAP), -NME_BUG); + g_return_val_if_fail(name, -NME_BUG); + g_return_val_if_fail(props, -NME_BUG); + g_return_val_if_fail(NM_IN_SET(props->type, IFF_TUN, IFF_TAP), -NME_BUG); - /* creating a non-persistant device requires that the caller handles - * the file descriptor. */ - g_return_val_if_fail (props->persist || out_fd, -NME_BUG); + /* creating a non-persistent device requires that the caller handles + * the file descriptor. */ + g_return_val_if_fail(props->persist || out_fd, -NME_BUG); - NM_SET_OUT (out_fd, -1); + NM_SET_OUT(out_fd, -1); - r = _link_add_check_existing (self, name, NM_LINK_TYPE_TUN, out_link); - if (r < 0) - return r; + r = _link_add_check_existing(self, name, NM_LINK_TYPE_TUN, out_link); + if (r < 0) + return r; - _LOG2D ("link: adding link %s", nm_platform_lnk_tun_to_string (props, b, sizeof (b))); + _LOG2D("link: adding link %s", nm_platform_lnk_tun_to_string(props, b, sizeof(b))); - if (!klass->link_tun_add (self, name, props, out_link, out_fd)) - return -NME_UNSPEC; - return 0; + if (!klass->link_tun_add(self, name, props, out_link, out_fd)) + return -NME_UNSPEC; + return 0; } gboolean -nm_platform_link_6lowpan_get_properties (NMPlatform *self, int ifindex, int *out_parent) +nm_platform_link_6lowpan_get_properties(NMPlatform *self, int ifindex, int *out_parent) { - const NMPlatformLink *plink; + const NMPlatformLink *plink; - plink = nm_platform_link_get (self, ifindex); - if (!plink) - return FALSE; + plink = nm_platform_link_get(self, ifindex); + if (!plink) + return FALSE; - if (plink->type != NM_LINK_TYPE_6LOWPAN) - return FALSE; + if (plink->type != NM_LINK_TYPE_6LOWPAN) + return FALSE; - if (plink->parent != 0) { - NM_SET_OUT (out_parent, plink->parent); - return TRUE; - } + if (plink->parent != 0) { + NM_SET_OUT(out_parent, plink->parent); + return TRUE; + } - /* As of 4.16 kernel does not expose the peer_ifindex as IFA_LINK. - * Find the WPAN device with the same MAC address. */ - if (out_parent) { - const NMPlatformLink *parent_plink; + /* As of 4.16 kernel does not expose the peer_ifindex as IFA_LINK. + * Find the WPAN device with the same MAC address. */ + if (out_parent) { + const NMPlatformLink *parent_plink; - parent_plink = nm_platform_link_get_by_address (self, - NM_LINK_TYPE_WPAN, - plink->l_address.data, - plink->l_address.len); - NM_SET_OUT (out_parent, parent_plink ? parent_plink->ifindex : -1); - } + parent_plink = nm_platform_link_get_by_address(self, + NM_LINK_TYPE_WPAN, + plink->l_address.data, + plink->l_address.len); + NM_SET_OUT(out_parent, parent_plink ? parent_plink->ifindex : -1); + } - return TRUE; + return TRUE; } /*****************************************************************************/ static gboolean -link_set_option (NMPlatform *self, int ifindex, const char *category, const char *option, const char *value) +link_set_option(NMPlatform *self, + int ifindex, + const char *category, + const char *option, + const char *value) { - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - const char *path; + nm_auto_close int dirfd = -1; + char ifname_verified[IFNAMSIZ]; + const char * path; - if (!category || !option) - return FALSE; + if (!category || !option) + return FALSE; - dirfd = nm_platform_sysctl_open_netdir (self, ifindex, ifname_verified); - if (dirfd < 0) - return FALSE; + dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname_verified); + if (dirfd < 0) + return FALSE; - path = nm_sprintf_buf_unsafe_a (strlen (category) + strlen (option) + 2, - "%s/%s", - category, - option); - return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_NETDIR_unsafe (dirfd, ifname_verified, path), value); + path = + nm_sprintf_buf_unsafe_a(strlen(category) + strlen(option) + 2, "%s/%s", category, option); + return nm_platform_sysctl_set(self, + NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname_verified, path), + value); } static char * -link_get_option (NMPlatform *self, int ifindex, const char *category, const char *option) +link_get_option(NMPlatform *self, int ifindex, const char *category, const char *option) { - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - const char *path; + nm_auto_close int dirfd = -1; + char ifname_verified[IFNAMSIZ]; + const char * path; - if (!category || !option) - return NULL; + if (!category || !option) + return NULL; - dirfd = nm_platform_sysctl_open_netdir (self, ifindex, ifname_verified); - if (dirfd < 0) - return NULL; + dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname_verified); + if (dirfd < 0) + return NULL; - path = nm_sprintf_buf_unsafe_a (strlen (category) + strlen (option) + 2, - "%s/%s", - category, option); - return nm_platform_sysctl_get (self, NMP_SYSCTL_PATHID_NETDIR_unsafe (dirfd, ifname_verified, path)); + path = + nm_sprintf_buf_unsafe_a(strlen(category) + strlen(option) + 2, "%s/%s", category, option); + return nm_platform_sysctl_get(self, + NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname_verified, path)); } static const char * -master_category (NMPlatform *self, int master) +master_category(NMPlatform *self, int master) { - switch (nm_platform_link_get_type (self, master)) { - case NM_LINK_TYPE_BRIDGE: - return "bridge"; - case NM_LINK_TYPE_BOND: - return "bonding"; - default: - return NULL; - } + switch (nm_platform_link_get_type(self, master)) { + case NM_LINK_TYPE_BRIDGE: + return "bridge"; + case NM_LINK_TYPE_BOND: + return "bonding"; + default: + return NULL; + } } static const char * -slave_category (NMPlatform *self, int slave) +slave_category(NMPlatform *self, int slave) { - int master = nm_platform_link_get_master (self, slave); + int master = nm_platform_link_get_master(self, slave); - if (master <= 0) - return NULL; + if (master <= 0) + return NULL; - switch (nm_platform_link_get_type (self, master)) { - case NM_LINK_TYPE_BRIDGE: - return "brport"; - default: - return NULL; - } + switch (nm_platform_link_get_type(self, master)) { + case NM_LINK_TYPE_BRIDGE: + return "brport"; + default: + return NULL; + } } gboolean -nm_platform_sysctl_master_set_option (NMPlatform *self, int ifindex, const char *option, const char *value) +nm_platform_sysctl_master_set_option(NMPlatform *self, + int ifindex, + const char *option, + const char *value) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (option, FALSE); - g_return_val_if_fail (value, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(option, FALSE); + g_return_val_if_fail(value, FALSE); - return link_set_option (self, ifindex, master_category (self, ifindex), option, value); + return link_set_option(self, ifindex, master_category(self, ifindex), option, value); } char * -nm_platform_sysctl_master_get_option (NMPlatform *self, int ifindex, const char *option) +nm_platform_sysctl_master_get_option(NMPlatform *self, int ifindex, const char *option) { - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (option, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(option, FALSE); - return link_get_option (self, ifindex, master_category (self, ifindex), option); + return link_get_option(self, ifindex, master_category(self, ifindex), option); } gboolean -nm_platform_sysctl_slave_set_option (NMPlatform *self, int ifindex, const char *option, const char *value) +nm_platform_sysctl_slave_set_option(NMPlatform *self, + int ifindex, + const char *option, + const char *value) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (option, FALSE); - g_return_val_if_fail (value, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(option, FALSE); + g_return_val_if_fail(value, FALSE); - return link_set_option (self, ifindex, slave_category (self, ifindex), option, value); + return link_set_option(self, ifindex, slave_category(self, ifindex), option, value); } char * -nm_platform_sysctl_slave_get_option (NMPlatform *self, int ifindex, const char *option) +nm_platform_sysctl_slave_get_option(NMPlatform *self, int ifindex, const char *option) { - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (option, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(option, FALSE); - return link_get_option (self, ifindex, slave_category (self, ifindex), option); + return link_get_option(self, ifindex, slave_category(self, ifindex), option); } /*****************************************************************************/ gboolean -nm_platform_link_vlan_change (NMPlatform *self, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map) -{ - _CHECK_SELF (self, klass, FALSE); - - nm_assert (klass->link_vlan_change); - - g_return_val_if_fail (!n_ingress_map || ingress_map, FALSE); - g_return_val_if_fail (!n_egress_map || egress_map, FALSE); - - flags_set &= flags_mask; - - if (_LOGD_ENABLED ()) { - char buf[512]; - char *b = buf; - gsize len, i; - - b[0] = '\0'; - len = sizeof (buf); - - if (flags_mask) - nm_utils_strbuf_append (&b, &len, " flags 0x%x/0x%x", (unsigned) flags_set, (unsigned) flags_mask); - - if (ingress_reset_all || n_ingress_map) { - nm_utils_strbuf_append_str (&b, &len, " ingress-qos-map"); - nm_platform_vlan_qos_mapping_to_string ("", ingress_map, n_ingress_map, b, len); - i = strlen (b); - b += i; - len -= i; - if (ingress_reset_all) - nm_utils_strbuf_append_str (&b, &len, " (reset-all)"); - } - - if (egress_reset_all || n_egress_map) { - nm_utils_strbuf_append_str (&b, &len, " egress-qos-map"); - nm_platform_vlan_qos_mapping_to_string ("", egress_map, n_egress_map, b, len); - i = strlen (b); - b += i; - len -= i; - if (egress_reset_all) - nm_utils_strbuf_append_str (&b, &len, " (reset-all)"); - } - - _LOG3D ("link: change vlan %s", buf); - } - return klass->link_vlan_change (self, - ifindex, - flags_mask, - flags_set, - ingress_reset_all, - ingress_map, - n_ingress_map, - egress_reset_all, - egress_map, - n_egress_map); +nm_platform_link_vlan_change(NMPlatform * self, + int ifindex, + NMVlanFlags flags_mask, + NMVlanFlags flags_set, + gboolean ingress_reset_all, + const NMVlanQosMapping *ingress_map, + gsize n_ingress_map, + gboolean egress_reset_all, + const NMVlanQosMapping *egress_map, + gsize n_egress_map) +{ + _CHECK_SELF(self, klass, FALSE); + + nm_assert(klass->link_vlan_change); + + g_return_val_if_fail(!n_ingress_map || ingress_map, FALSE); + g_return_val_if_fail(!n_egress_map || egress_map, FALSE); + + flags_set &= flags_mask; + + if (_LOGD_ENABLED()) { + char buf[512]; + char *b = buf; + gsize len, i; + + b[0] = '\0'; + len = sizeof(buf); + + if (flags_mask) + nm_utils_strbuf_append(&b, + &len, + " flags 0x%x/0x%x", + (unsigned) flags_set, + (unsigned) flags_mask); + + if (ingress_reset_all || n_ingress_map) { + nm_utils_strbuf_append_str(&b, &len, " ingress-qos-map"); + nm_platform_vlan_qos_mapping_to_string("", ingress_map, n_ingress_map, b, len); + i = strlen(b); + b += i; + len -= i; + if (ingress_reset_all) + nm_utils_strbuf_append_str(&b, &len, " (reset-all)"); + } + + if (egress_reset_all || n_egress_map) { + nm_utils_strbuf_append_str(&b, &len, " egress-qos-map"); + nm_platform_vlan_qos_mapping_to_string("", egress_map, n_egress_map, b, len); + i = strlen(b); + b += i; + len -= i; + if (egress_reset_all) + nm_utils_strbuf_append_str(&b, &len, " (reset-all)"); + } + + _LOG3D("link: change vlan %s", buf); + } + return klass->link_vlan_change(self, + ifindex, + flags_mask, + flags_set, + ingress_reset_all, + ingress_map, + n_ingress_map, + egress_reset_all, + egress_map, + n_egress_map); } gboolean -nm_platform_link_vlan_set_ingress_map (NMPlatform *self, int ifindex, int from, int to) +nm_platform_link_vlan_set_ingress_map(NMPlatform *self, int ifindex, int from, int to) { - NMVlanQosMapping map = { - .from = from, - .to = to, - }; + NMVlanQosMapping map = { + .from = from, + .to = to, + }; - return nm_platform_link_vlan_change (self, ifindex, 0, 0, FALSE, &map, 1, FALSE, NULL, 0); + return nm_platform_link_vlan_change(self, ifindex, 0, 0, FALSE, &map, 1, FALSE, NULL, 0); } gboolean -nm_platform_link_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, int to) +nm_platform_link_vlan_set_egress_map(NMPlatform *self, int ifindex, int from, int to) { - NMVlanQosMapping map = { - .from = from, - .to = to, - }; + NMVlanQosMapping map = { + .from = from, + .to = to, + }; - return nm_platform_link_vlan_change (self, ifindex, 0, 0, FALSE, NULL, 0, FALSE, &map, 1); + return nm_platform_link_vlan_change(self, ifindex, 0, 0, FALSE, NULL, 0, FALSE, &map, 1); } static int -_infiniband_add_add_or_delete (NMPlatform *self, - int ifindex, - int p_key, - gboolean add, - const NMPlatformLink **out_link) +_infiniband_add_add_or_delete(NMPlatform * self, + int ifindex, + int p_key, + gboolean add, + const NMPlatformLink **out_link) { - char name[IFNAMSIZ]; - const NMPlatformLink *parent_link; - int r; + char name[IFNAMSIZ]; + const NMPlatformLink *parent_link; + int r; - _CHECK_SELF (self, klass, -NME_BUG); + _CHECK_SELF(self, klass, -NME_BUG); - g_return_val_if_fail (ifindex >= 0, -NME_BUG); - g_return_val_if_fail (p_key >= 0 && p_key <= 0xffff, -NME_BUG); + g_return_val_if_fail(ifindex >= 0, -NME_BUG); + g_return_val_if_fail(p_key >= 0 && p_key <= 0xffff, -NME_BUG); - /* the special keys 0x0000 and 0x8000 are not allowed. */ - if (NM_IN_SET (p_key, 0, 0x8000)) - return -NME_UNSPEC; + /* the special keys 0x0000 and 0x8000 are not allowed. */ + if (NM_IN_SET(p_key, 0, 0x8000)) + return -NME_UNSPEC; - parent_link = nm_platform_link_get (self, ifindex); - if (!parent_link) - return -NME_PL_NOT_FOUND; + parent_link = nm_platform_link_get(self, ifindex); + if (!parent_link) + return -NME_PL_NOT_FOUND; - if (parent_link->type != NM_LINK_TYPE_INFINIBAND) - return -NME_PL_WRONG_TYPE; + if (parent_link->type != NM_LINK_TYPE_INFINIBAND) + return -NME_PL_WRONG_TYPE; - nm_utils_new_infiniband_name (name, parent_link->name, p_key); + nm_utils_new_infiniband_name(name, parent_link->name, p_key); - if (add) { - r = _link_add_check_existing (self, name, NM_LINK_TYPE_INFINIBAND, out_link); - if (r < 0) - return r; + if (add) { + r = _link_add_check_existing(self, name, NM_LINK_TYPE_INFINIBAND, out_link); + if (r < 0) + return r; - _LOG3D ("link: adding infiniband partition %s, key %d", name, p_key); - if (!klass->infiniband_partition_add (self, ifindex, p_key, out_link)) - return -NME_UNSPEC; - } else { - _LOG3D ("link: deleting infiniband partition %s, key %d", name, p_key); + _LOG3D("link: adding infiniband partition %s, key %d", name, p_key); + if (!klass->infiniband_partition_add(self, ifindex, p_key, out_link)) + return -NME_UNSPEC; + } else { + _LOG3D("link: deleting infiniband partition %s, key %d", name, p_key); - if (!klass->infiniband_partition_delete (self, ifindex, p_key)) - return -NME_UNSPEC; - } + if (!klass->infiniband_partition_delete(self, ifindex, p_key)) + return -NME_UNSPEC; + } - return 0; + return 0; } int -nm_platform_link_infiniband_add (NMPlatform *self, - int parent, - int p_key, - const NMPlatformLink **out_link) +nm_platform_link_infiniband_add(NMPlatform * self, + int parent, + int p_key, + const NMPlatformLink **out_link) { - return _infiniband_add_add_or_delete (self, parent, p_key, TRUE, out_link); + return _infiniband_add_add_or_delete(self, parent, p_key, TRUE, out_link); } int -nm_platform_link_infiniband_delete (NMPlatform *self, - int parent, - int p_key) +nm_platform_link_infiniband_delete(NMPlatform *self, int parent, int p_key) { - return _infiniband_add_add_or_delete (self, parent, p_key, FALSE, NULL); + return _infiniband_add_add_or_delete(self, parent, p_key, FALSE, NULL); } gboolean -nm_platform_link_infiniband_get_properties (NMPlatform *self, - int ifindex, - int *out_parent, - int *out_p_key, - const char **out_mode) -{ - nm_auto_close int dirfd = -1; - char ifname_verified[IFNAMSIZ]; - const NMPlatformLnkInfiniband *plnk; - const NMPlatformLink *plink; - char *contents; - const char *mode; - int p_key = 0; - - _CHECK_SELF (self, klass, FALSE); - - g_return_val_if_fail (ifindex > 0, FALSE); - - plnk = nm_platform_link_get_lnk_infiniband (self, ifindex, &plink); - - if ( !plink - || plink->type != NM_LINK_TYPE_INFINIBAND) - return FALSE; - - if (plnk) { - NM_SET_OUT (out_parent, plink->parent); - NM_SET_OUT (out_p_key, plnk->p_key); - NM_SET_OUT (out_mode, plnk->mode); - return TRUE; - } - - /* Could not get the link information via netlink. To support older kernels, - * fallback to reading sysfs. */ - - dirfd = nm_platform_sysctl_open_netdir (self, ifindex, ifname_verified); - if (dirfd < 0) - return FALSE; - - contents = nm_platform_sysctl_get (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_verified, "mode")); - if (!contents) - return FALSE; - if (strstr (contents, "datagram")) - mode = "datagram"; - else if (strstr (contents, "connected")) - mode = "connected"; - else - mode = NULL; - g_free (contents); - - p_key = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname_verified, "pkey"), 16, 0, 0xFFFF, -1); - if (p_key < 0) - return FALSE; - - NM_SET_OUT (out_parent, plink->parent); - NM_SET_OUT (out_p_key, p_key); - NM_SET_OUT (out_mode, mode); - return TRUE; +nm_platform_link_infiniband_get_properties(NMPlatform * self, + int ifindex, + int * out_parent, + int * out_p_key, + const char **out_mode) +{ + nm_auto_close int dirfd = -1; + char ifname_verified[IFNAMSIZ]; + const NMPlatformLnkInfiniband *plnk; + const NMPlatformLink * plink; + char * contents; + const char * mode; + int p_key = 0; + + _CHECK_SELF(self, klass, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + + plnk = nm_platform_link_get_lnk_infiniband(self, ifindex, &plink); + + if (!plink || plink->type != NM_LINK_TYPE_INFINIBAND) + return FALSE; + + if (plnk) { + NM_SET_OUT(out_parent, plink->parent); + NM_SET_OUT(out_p_key, plnk->p_key); + NM_SET_OUT(out_mode, plnk->mode); + return TRUE; + } + + /* Could not get the link information via netlink. To support older kernels, + * fallback to reading sysfs. */ + + dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname_verified); + if (dirfd < 0) + return FALSE; + + contents = + nm_platform_sysctl_get(self, NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "mode")); + if (!contents) + return FALSE; + if (strstr(contents, "datagram")) + mode = "datagram"; + else if (strstr(contents, "connected")) + mode = "connected"; + else + mode = NULL; + g_free(contents); + + p_key = + nm_platform_sysctl_get_int_checked(self, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname_verified, "pkey"), + 16, + 0, + 0xFFFF, + -1); + if (p_key < 0) + return FALSE; + + NM_SET_OUT(out_parent, plink->parent); + NM_SET_OUT(out_p_key, p_key); + NM_SET_OUT(out_mode, mode); + return TRUE; } gboolean -nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_peer_ifindex) +nm_platform_link_veth_get_properties(NMPlatform *self, int ifindex, int *out_peer_ifindex) { - const NMPlatformLink *plink; - int peer_ifindex; + const NMPlatformLink *plink; + int peer_ifindex; - plink = nm_platform_link_get (self, ifindex); - if (!plink) - return FALSE; + plink = nm_platform_link_get(self, ifindex); + if (!plink) + return FALSE; - if (plink->type != NM_LINK_TYPE_VETH) - return FALSE; + if (plink->type != NM_LINK_TYPE_VETH) + return FALSE; - if (plink->parent != 0) { - NM_SET_OUT (out_peer_ifindex, plink->parent); - return TRUE; - } + if (plink->parent != 0) { + NM_SET_OUT(out_peer_ifindex, plink->parent); + return TRUE; + } - /* Pre-4.1 kernel did not expose the peer_ifindex as IFA_LINK. Lookup via ethtool. */ - if (out_peer_ifindex) { - nm_auto_pop_netns NMPNetns *netns = NULL; + /* Pre-4.1 kernel did not expose the peer_ifindex as IFA_LINK. Lookup via ethtool. */ + if (out_peer_ifindex) { + nm_auto_pop_netns NMPNetns *netns = NULL; - if (!nm_platform_netns_push (self, &netns)) - return FALSE; - peer_ifindex = nmp_utils_ethtool_get_peer_ifindex (plink->ifindex); - if (peer_ifindex <= 0) - return FALSE; + if (!nm_platform_netns_push(self, &netns)) + return FALSE; + peer_ifindex = nmp_utils_ethtool_get_peer_ifindex(plink->ifindex); + if (peer_ifindex <= 0) + return FALSE; - *out_peer_ifindex = peer_ifindex; - } - return TRUE; + *out_peer_ifindex = peer_ifindex; + } + return TRUE; } /** @@ -2851,490 +2951,504 @@ nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_pe * * Returns: #TRUE, if the properties could be read. */ gboolean -nm_platform_link_tun_get_properties (NMPlatform *self, - int ifindex, - NMPlatformLnkTun *out_properties) -{ - const NMPObject *plobj; - const NMPObject *pllnk; - char ifname[IFNAMSIZ]; - gint64 owner; - gint64 group; - gint64 flags; - - /* we consider also invisible links (those that are not yet in udev). */ - plobj = nm_platform_link_get_obj (self, ifindex, FALSE); - if (!plobj) - return FALSE; - - if (NMP_OBJECT_CAST_LINK (plobj)->type != NM_LINK_TYPE_TUN) - return FALSE; - - pllnk = plobj->_link.netlink.lnk; - if (pllnk) { - nm_assert (NMP_OBJECT_GET_TYPE (pllnk) == NMP_OBJECT_TYPE_LNK_TUN); - nm_assert (NMP_OBJECT_GET_CLASS (pllnk)->lnk_link_type == NM_LINK_TYPE_TUN); - - /* recent kernels expose tun properties via netlink and thus we have them - * in the platform cache. */ - NM_SET_OUT (out_properties, pllnk->lnk_tun); - return TRUE; - } - - /* fallback to reading sysctl. */ - { - nm_auto_close int dirfd = -1; - - dirfd = nm_platform_sysctl_open_netdir (self, ifindex, ifname); - if (dirfd < 0) - return FALSE; - - owner = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "owner"), 10, -1, G_MAXUINT32, -2); - if (owner == -2) - return FALSE; - - group = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "group"), 10, -1, G_MAXUINT32, -2); - if (group == -2) - return FALSE; - - flags = nm_platform_sysctl_get_int_checked (self, NMP_SYSCTL_PATHID_NETDIR (dirfd, ifname, "tun_flags"), 16, 0, G_MAXINT64, -1); - if (flags == -1) - return FALSE; - } - - if (out_properties) { - memset (out_properties, 0, sizeof (*out_properties)); - if (owner != -1) { - out_properties->owner_valid = TRUE; - out_properties->owner = owner; - } - if (group != -1) { - out_properties->group_valid = TRUE; - out_properties->group = group; - } - out_properties->type = (flags & TUN_TYPE_MASK); - out_properties->pi = !(flags & IFF_NO_PI); - out_properties->vnet_hdr = !!(flags & IFF_VNET_HDR); - out_properties->multi_queue = !!(flags & NM_IFF_MULTI_QUEUE); - out_properties->persist = !!(flags & IFF_PERSIST); - } - return TRUE; +nm_platform_link_tun_get_properties(NMPlatform *self, int ifindex, NMPlatformLnkTun *out_properties) +{ + const NMPObject *plobj; + const NMPObject *pllnk; + char ifname[IFNAMSIZ]; + gint64 owner; + gint64 group; + gint64 flags; + + /* we consider also invisible links (those that are not yet in udev). */ + plobj = nm_platform_link_get_obj(self, ifindex, FALSE); + if (!plobj) + return FALSE; + + if (NMP_OBJECT_CAST_LINK(plobj)->type != NM_LINK_TYPE_TUN) + return FALSE; + + pllnk = plobj->_link.netlink.lnk; + if (pllnk) { + nm_assert(NMP_OBJECT_GET_TYPE(pllnk) == NMP_OBJECT_TYPE_LNK_TUN); + nm_assert(NMP_OBJECT_GET_CLASS(pllnk)->lnk_link_type == NM_LINK_TYPE_TUN); + + /* recent kernels expose tun properties via netlink and thus we have them + * in the platform cache. */ + NM_SET_OUT(out_properties, pllnk->lnk_tun); + return TRUE; + } + + /* fallback to reading sysctl. */ + { + nm_auto_close int dirfd = -1; + + dirfd = nm_platform_sysctl_open_netdir(self, ifindex, ifname); + if (dirfd < 0) + return FALSE; + + owner = nm_platform_sysctl_get_int_checked(self, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "owner"), + 10, + -1, + G_MAXUINT32, + -2); + if (owner == -2) + return FALSE; + + group = nm_platform_sysctl_get_int_checked(self, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "group"), + 10, + -1, + G_MAXUINT32, + -2); + if (group == -2) + return FALSE; + + flags = + nm_platform_sysctl_get_int_checked(self, + NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "tun_flags"), + 16, + 0, + G_MAXINT64, + -1); + if (flags == -1) + return FALSE; + } + + if (out_properties) { + memset(out_properties, 0, sizeof(*out_properties)); + if (owner != -1) { + out_properties->owner_valid = TRUE; + out_properties->owner = owner; + } + if (group != -1) { + out_properties->group_valid = TRUE; + out_properties->group = group; + } + out_properties->type = (flags & TUN_TYPE_MASK); + out_properties->pi = !(flags & IFF_NO_PI); + out_properties->vnet_hdr = !!(flags & IFF_VNET_HDR); + out_properties->multi_queue = !!(flags & NM_IFF_MULTI_QUEUE); + out_properties->persist = !!(flags & IFF_PERSIST); + } + return TRUE; } gboolean -nm_platform_wifi_get_capabilities (NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps) +nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wifi_get_capabilities (self, ifindex, caps); + return klass->wifi_get_capabilities(self, ifindex, caps); } gboolean -nm_platform_wifi_get_bssid (NMPlatform *self, int ifindex, guint8 *bssid) +nm_platform_wifi_get_bssid(NMPlatform *self, int ifindex, guint8 *bssid) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wifi_get_bssid (self, ifindex, bssid); + return klass->wifi_get_bssid(self, ifindex, bssid); } guint32 -nm_platform_wifi_get_frequency (NMPlatform *self, int ifindex) +nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, 0); + _CHECK_SELF(self, klass, 0); - g_return_val_if_fail (ifindex > 0, 0); + g_return_val_if_fail(ifindex > 0, 0); - return klass->wifi_get_frequency (self, ifindex); + return klass->wifi_get_frequency(self, ifindex); } int -nm_platform_wifi_get_quality (NMPlatform *self, int ifindex) +nm_platform_wifi_get_quality(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, 0); + _CHECK_SELF(self, klass, 0); - g_return_val_if_fail (ifindex > 0, 0); + g_return_val_if_fail(ifindex > 0, 0); - return klass->wifi_get_quality (self, ifindex); + return klass->wifi_get_quality(self, ifindex); } guint32 -nm_platform_wifi_get_rate (NMPlatform *self, int ifindex) +nm_platform_wifi_get_rate(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, 0); + _CHECK_SELF(self, klass, 0); - g_return_val_if_fail (ifindex > 0, 0); + g_return_val_if_fail(ifindex > 0, 0); - return klass->wifi_get_rate (self, ifindex); + return klass->wifi_get_rate(self, ifindex); } NM80211Mode -nm_platform_wifi_get_mode (NMPlatform *self, int ifindex) +nm_platform_wifi_get_mode(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, NM_802_11_MODE_UNKNOWN); + _CHECK_SELF(self, klass, NM_802_11_MODE_UNKNOWN); - g_return_val_if_fail (ifindex > 0, NM_802_11_MODE_UNKNOWN); + g_return_val_if_fail(ifindex > 0, NM_802_11_MODE_UNKNOWN); - return klass->wifi_get_mode (self, ifindex); + return klass->wifi_get_mode(self, ifindex); } void -nm_platform_wifi_set_mode (NMPlatform *self, int ifindex, NM80211Mode mode) +nm_platform_wifi_set_mode(NMPlatform *self, int ifindex, NM80211Mode mode) { - _CHECK_SELF_VOID (self, klass); + _CHECK_SELF_VOID(self, klass); - g_return_if_fail (ifindex > 0); + g_return_if_fail(ifindex > 0); - klass->wifi_set_mode (self, ifindex, mode); + klass->wifi_set_mode(self, ifindex, mode); } static void -wifi_set_powersave (NMPlatform *p, int ifindex, guint32 powersave) +wifi_set_powersave(NMPlatform *p, int ifindex, guint32 powersave) { - /* empty */ + /* empty */ } void -nm_platform_wifi_set_powersave (NMPlatform *self, int ifindex, guint32 powersave) +nm_platform_wifi_set_powersave(NMPlatform *self, int ifindex, guint32 powersave) { - _CHECK_SELF_VOID (self, klass); + _CHECK_SELF_VOID(self, klass); - g_return_if_fail (ifindex > 0); + g_return_if_fail(ifindex > 0); - klass->wifi_set_powersave (self, ifindex, powersave); + klass->wifi_set_powersave(self, ifindex, powersave); } guint32 -nm_platform_wifi_find_frequency (NMPlatform *self, int ifindex, const guint32 *freqs) +nm_platform_wifi_find_frequency(NMPlatform *self, int ifindex, const guint32 *freqs) { - _CHECK_SELF (self, klass, 0); + _CHECK_SELF(self, klass, 0); - g_return_val_if_fail (ifindex > 0, 0); - g_return_val_if_fail (freqs != NULL, 0); + g_return_val_if_fail(ifindex > 0, 0); + g_return_val_if_fail(freqs != NULL, 0); - return klass->wifi_find_frequency (self, ifindex, freqs); + return klass->wifi_find_frequency(self, ifindex, freqs); } void -nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gboolean running) +nm_platform_wifi_indicate_addressing_running(NMPlatform *self, int ifindex, gboolean running) { - _CHECK_SELF_VOID (self, klass); + _CHECK_SELF_VOID(self, klass); - g_return_if_fail (ifindex > 0); + g_return_if_fail(ifindex > 0); - klass->wifi_indicate_addressing_running (self, ifindex, running); + klass->wifi_indicate_addressing_running(self, ifindex, running); } NMSettingWirelessWakeOnWLan -nm_platform_wifi_get_wake_on_wlan (NMPlatform *self, int ifindex) +nm_platform_wifi_get_wake_on_wlan(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wifi_get_wake_on_wlan (self, ifindex); + return klass->wifi_get_wake_on_wlan(self, ifindex); } gboolean -nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl) +nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wifi_set_wake_on_wlan (self, ifindex, wowl); + return klass->wifi_set_wake_on_wlan(self, ifindex, wowl); } guint32 -nm_platform_mesh_get_channel (NMPlatform *self, int ifindex) +nm_platform_mesh_get_channel(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, 0); + _CHECK_SELF(self, klass, 0); - g_return_val_if_fail (ifindex > 0, 0); + g_return_val_if_fail(ifindex > 0, 0); - return klass->mesh_get_channel (self, ifindex); + return klass->mesh_get_channel(self, ifindex); } gboolean -nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel) +nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->mesh_set_channel (self, ifindex, channel); + return klass->mesh_set_channel(self, ifindex, channel); } gboolean -nm_platform_mesh_set_ssid (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len) +nm_platform_mesh_set_ssid(NMPlatform *self, int ifindex, const guint8 *ssid, gsize len) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (ssid != NULL, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(ssid != NULL, FALSE); - return klass->mesh_set_ssid (self, ifindex, ssid, len); + return klass->mesh_set_ssid(self, ifindex, ssid, len); } guint16 -nm_platform_wpan_get_pan_id (NMPlatform *self, int ifindex) +nm_platform_wpan_get_pan_id(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wpan_get_pan_id (self, ifindex); + return klass->wpan_get_pan_id(self, ifindex); } gboolean -nm_platform_wpan_set_pan_id (NMPlatform *self, int ifindex, guint16 pan_id) +nm_platform_wpan_set_pan_id(NMPlatform *self, int ifindex, guint16 pan_id) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wpan_set_pan_id (self, ifindex, pan_id); + return klass->wpan_set_pan_id(self, ifindex, pan_id); } guint16 -nm_platform_wpan_get_short_addr (NMPlatform *self, int ifindex) +nm_platform_wpan_get_short_addr(NMPlatform *self, int ifindex) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wpan_get_short_addr (self, ifindex); + return klass->wpan_get_short_addr(self, ifindex); } gboolean -nm_platform_wpan_set_short_addr (NMPlatform *self, int ifindex, guint16 short_addr) +nm_platform_wpan_set_short_addr(NMPlatform *self, int ifindex, guint16 short_addr) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wpan_set_short_addr (self, ifindex, short_addr); + return klass->wpan_set_short_addr(self, ifindex, short_addr); } gboolean -nm_platform_wpan_set_channel (NMPlatform *self, int ifindex, guint8 page, guint8 channel) +nm_platform_wpan_set_channel(NMPlatform *self, int ifindex, guint8 page, guint8 channel) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wpan_set_channel (self, ifindex, page, channel); + return klass->wpan_set_channel(self, ifindex, page, channel); } -#define TO_STRING_DEV_BUF_SIZE (5+15+1) +#define TO_STRING_DEV_BUF_SIZE (5 + 15 + 1) static const char * -_to_string_dev (NMPlatform *self, int ifindex, char *buf, size_t size) +_to_string_dev(NMPlatform *self, int ifindex, char *buf, size_t size) { - g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE); + g_assert(buf && size >= TO_STRING_DEV_BUF_SIZE); - if (ifindex) { - const char *name = ifindex > 0 && self ? nm_platform_link_get_name (self, ifindex) : NULL; - char *buf2; + if (ifindex) { + const char *name = ifindex > 0 && self ? nm_platform_link_get_name(self, ifindex) : NULL; + char * buf2; - strcpy (buf, " dev "); - buf2 = buf + 5; - size -= 5; + strcpy(buf, " dev "); + buf2 = buf + 5; + size -= 5; - if (name) - g_strlcpy (buf2, name, size); - else - g_snprintf (buf2, size, "%d", ifindex); - } else - buf[0] = 0; + if (name) + g_strlcpy(buf2, name, size); + else + g_snprintf(buf2, size, "%d", ifindex); + } else + buf[0] = 0; - return buf; + return buf; } #define TO_STRING_IFA_FLAGS_BUF_SIZE 256 static const char * -_to_string_ifa_flags (guint32 ifa_flags, char *buf, gsize size) +_to_string_ifa_flags(guint32 ifa_flags, char *buf, gsize size) { #define S_FLAGS_PREFIX " flags " - nm_assert (buf && size >= TO_STRING_IFA_FLAGS_BUF_SIZE && size > NM_STRLEN (S_FLAGS_PREFIX)); - - if (!ifa_flags) - buf[0] = '\0'; - else { - nm_platform_addr_flags2str (ifa_flags, &buf[NM_STRLEN (S_FLAGS_PREFIX)], size - NM_STRLEN (S_FLAGS_PREFIX)); - if (buf[NM_STRLEN (S_FLAGS_PREFIX)] == '\0') - buf[0] = '\0'; - else - memcpy (buf, S_FLAGS_PREFIX, NM_STRLEN (S_FLAGS_PREFIX)); - } - return buf; + nm_assert(buf && size >= TO_STRING_IFA_FLAGS_BUF_SIZE && size > NM_STRLEN(S_FLAGS_PREFIX)); + + if (!ifa_flags) + buf[0] = '\0'; + else { + nm_platform_addr_flags2str(ifa_flags, + &buf[NM_STRLEN(S_FLAGS_PREFIX)], + size - NM_STRLEN(S_FLAGS_PREFIX)); + if (buf[NM_STRLEN(S_FLAGS_PREFIX)] == '\0') + buf[0] = '\0'; + else + memcpy(buf, S_FLAGS_PREFIX, NM_STRLEN(S_FLAGS_PREFIX)); + } + return buf; } /*****************************************************************************/ gboolean -nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMSettingWiredWakeOnLan wol, const char *wol_password) +nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, + int ifindex, + NMSettingWiredWakeOnLan wol, + const char * wol_password) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return nmp_utils_ethtool_set_wake_on_lan (ifindex, wol, wol_password); + return nmp_utils_ethtool_set_wake_on_lan(ifindex, wol, wol_password); } gboolean -nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex) +nm_platform_ethtool_set_link_settings(NMPlatform * self, + int ifindex, + gboolean autoneg, + guint32 speed, + NMPlatformLinkDuplexType duplex) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return nmp_utils_ethtool_set_link_settings (ifindex, autoneg, speed, duplex); + return nmp_utils_ethtool_set_link_settings(ifindex, autoneg, speed, duplex); } gboolean -nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex) +nm_platform_ethtool_get_link_settings(NMPlatform * self, + int ifindex, + gboolean * out_autoneg, + guint32 * out_speed, + NMPlatformLinkDuplexType *out_duplex) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return nmp_utils_ethtool_get_link_settings (ifindex, out_autoneg, out_speed, out_duplex); + return nmp_utils_ethtool_get_link_settings(ifindex, out_autoneg, out_speed, out_duplex); } -NM_UTILS_LOOKUP_STR_DEFINE (nm_platform_link_duplex_type_to_string, NMPlatformLinkDuplexType, - NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), - NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_UNKNOWN, "unknown"), - NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_FULL, "full"), - NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_HALF, "half"), -); +NM_UTILS_LOOKUP_STR_DEFINE(nm_platform_link_duplex_type_to_string, + NMPlatformLinkDuplexType, + NM_UTILS_LOOKUP_DEFAULT_WARN(NULL), + NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_FULL, "full"), + NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_HALF, "half"), ); /*****************************************************************************/ NMEthtoolFeatureStates * -nm_platform_ethtool_get_link_features (NMPlatform *self, int ifindex) +nm_platform_ethtool_get_link_features(NMPlatform *self, int ifindex) { - _CHECK_SELF_NETNS (self, klass, netns, NULL); + _CHECK_SELF_NETNS(self, klass, netns, NULL); - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail(ifindex > 0, NULL); - return nmp_utils_ethtool_get_features (ifindex); + return nmp_utils_ethtool_get_features(ifindex); } gboolean -nm_platform_ethtool_set_features (NMPlatform *self, - int ifindex, - const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */) +nm_platform_ethtool_set_features( + NMPlatform * self, + int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return nmp_utils_ethtool_set_features (ifindex, features, requested, do_set); + return nmp_utils_ethtool_set_features(ifindex, features, requested, do_set); } gboolean -nm_platform_ethtool_get_link_coalesce (NMPlatform *self, - int ifindex, - NMEthtoolCoalesceState *coalesce) +nm_platform_ethtool_get_link_coalesce(NMPlatform * self, + int ifindex, + NMEthtoolCoalesceState *coalesce) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (coalesce, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(coalesce, FALSE); - return nmp_utils_ethtool_get_coalesce (ifindex, coalesce); + return nmp_utils_ethtool_get_coalesce(ifindex, coalesce); } gboolean -nm_platform_ethtool_set_coalesce (NMPlatform *self, - int ifindex, - const NMEthtoolCoalesceState *coalesce) +nm_platform_ethtool_set_coalesce(NMPlatform * self, + int ifindex, + const NMEthtoolCoalesceState *coalesce) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return nmp_utils_ethtool_set_coalesce (ifindex, coalesce); + return nmp_utils_ethtool_set_coalesce(ifindex, coalesce); } gboolean -nm_platform_ethtool_get_link_ring (NMPlatform *self, - int ifindex, - NMEthtoolRingState *ring) +nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (ring, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(ring, FALSE); - return nmp_utils_ethtool_get_ring (ifindex, ring); + return nmp_utils_ethtool_get_ring(ifindex, ring); } gboolean -nm_platform_ethtool_set_ring (NMPlatform *self, - int ifindex, - const NMEthtoolRingState *ring) +nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring) { - _CHECK_SELF_NETNS (self, klass, netns, FALSE); + _CHECK_SELF_NETNS(self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); - return nmp_utils_ethtool_set_ring (ifindex, ring); + return nmp_utils_ethtool_set_ring(ifindex, ring); } /*****************************************************************************/ const NMDedupMultiHeadEntry * -nm_platform_lookup_all (NMPlatform *self, - NMPCacheIdType cache_id_type, - const NMPObject *obj) +nm_platform_lookup_all(NMPlatform *self, NMPCacheIdType cache_id_type, const NMPObject *obj) { - return nmp_cache_lookup_all (nm_platform_get_cache (self), - cache_id_type, - obj); + return nmp_cache_lookup_all(nm_platform_get_cache(self), cache_id_type, obj); } const NMDedupMultiEntry * -nm_platform_lookup_entry (NMPlatform *self, - NMPCacheIdType cache_id_type, - const NMPObject *obj) +nm_platform_lookup_entry(NMPlatform *self, NMPCacheIdType cache_id_type, const NMPObject *obj) { - return nmp_cache_lookup_entry_with_idx_type (nm_platform_get_cache (self), - cache_id_type, - obj); + return nmp_cache_lookup_entry_with_idx_type(nm_platform_get_cache(self), cache_id_type, obj); } const NMDedupMultiHeadEntry * -nm_platform_lookup (NMPlatform *self, - const NMPLookup *lookup) +nm_platform_lookup(NMPlatform *self, const NMPLookup *lookup) { - return nmp_cache_lookup (nm_platform_get_cache (self), - lookup); + return nmp_cache_lookup(nm_platform_get_cache(self), lookup); } gboolean -nm_platform_lookup_predicate_routes_main (const NMPObject *obj, - gpointer user_data) +nm_platform_lookup_predicate_routes_main(const NMPObject *obj, gpointer user_data) { - nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); - return nm_platform_route_table_is_main (obj->ip_route.table_coerced); + nm_assert( + NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); + return nm_platform_route_table_is_main( + nm_platform_ip_route_get_effective_table(&obj->ip_route)); } gboolean -nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj, - gpointer user_data) +nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel(const NMPObject *obj, + gpointer user_data) { - nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); - return nm_platform_route_table_is_main (obj->ip_route.table_coerced) - && obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL; + nm_assert( + NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); + return nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&obj->ip_route)) + && obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL; } /** @@ -3356,347 +3470,401 @@ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *ob * Returns: the result of the lookup. */ GPtrArray * -nm_platform_lookup_clone (NMPlatform *self, - const NMPLookup *lookup, - NMPObjectPredicateFunc predicate, - gpointer user_data) +nm_platform_lookup_clone(NMPlatform * self, + const NMPLookup * lookup, + NMPObjectPredicateFunc predicate, + gpointer user_data) { - return nm_dedup_multi_objs_to_ptr_array_head (nm_platform_lookup (self, lookup), - (NMDedupMultiFcnSelectPredicate) predicate, - user_data); + return nm_dedup_multi_objs_to_ptr_array_head(nm_platform_lookup(self, lookup), + (NMDedupMultiFcnSelectPredicate) predicate, + user_data); } void -nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, guint8 plen) +nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen) { - nm_assert (plen <= 32); + nm_assert(plen <= 32); - addr->address = address; - addr->peer_address = address; - addr->plen = plen; + addr->address = address; + addr->peer_address = address; + addr->plen = plen; } const struct in6_addr * -nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr) +nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr) { - if ( IN6_IS_ADDR_UNSPECIFIED (&addr->peer_address) - || IN6_ARE_ADDR_EQUAL (&addr->peer_address, &addr->address)) - return &addr->address; - return &addr->peer_address; + if (IN6_IS_ADDR_UNSPECIFIED(&addr->peer_address) + || IN6_ARE_ADDR_EQUAL(&addr->peer_address, &addr->address)) + return &addr->address; + return &addr->peer_address; +} + +gboolean +nm_platform_ip6_address_match(const NMPlatformIP6Address *addr, NMPlatformMatchFlags match_flag) +{ + nm_assert(!NM_FLAGS_ANY( + match_flag, + ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))); + nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY)); + nm_assert(NM_FLAGS_ANY(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)); + + if (IN6_IS_ADDR_LINKLOCAL(&addr->address)) { + if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL)) + return FALSE; + } else { + if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL)) + return FALSE; + } + + if (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_DADFAILED)) { + if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED)) + return FALSE; + } else if (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_TENTATIVE) + && !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { + if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) + return FALSE; + } else { + if (!NM_FLAGS_HAS(match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) + return FALSE; + } + + return TRUE; } gboolean -nm_platform_ip4_address_add (NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) -{ - _CHECK_SELF (self, klass, FALSE); - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (plen <= 32, FALSE); - g_return_val_if_fail (lifetime > 0, FALSE); - g_return_val_if_fail (preferred <= lifetime, FALSE); - g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE); - - if (_LOGD_ENABLED ()) { - NMPlatformIP4Address addr; - - addr = (NMPlatformIP4Address) { - .ifindex = ifindex, - .address = address, - .peer_address = peer_address, - .plen = plen, - .timestamp = 0, /* set it at zero, which to_string will treat as *now* */ - .lifetime = lifetime, - .preferred = preferred, - .n_ifa_flags = flags, - .broadcast_address = broadcast_address, - .use_ip4_broadcast_address = TRUE, - }; - if (label) - g_strlcpy (addr.label, label, sizeof (addr.label)); - - _LOG3D ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr, NULL, 0)); - } - return klass->ip4_address_add (self, ifindex, address, plen, peer_address, broadcast_address, lifetime, preferred, flags, label); +nm_platform_ip4_address_add(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address, + in_addr_t broadcast_address, + guint32 lifetime, + guint32 preferred, + guint32 flags, + const char *label) +{ + _CHECK_SELF(self, klass, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(plen <= 32, FALSE); + g_return_val_if_fail(lifetime > 0, FALSE); + g_return_val_if_fail(preferred <= lifetime, FALSE); + g_return_val_if_fail(!label || strlen(label) < sizeof(((NMPlatformIP4Address *) NULL)->label), + FALSE); + + if (_LOGD_ENABLED()) { + NMPlatformIP4Address addr; + + addr = (NMPlatformIP4Address){ + .ifindex = ifindex, + .address = address, + .peer_address = peer_address, + .plen = plen, + .timestamp = 0, /* set it at zero, which to_string will treat as *now* */ + .lifetime = lifetime, + .preferred = preferred, + .n_ifa_flags = flags, + .broadcast_address = broadcast_address, + .use_ip4_broadcast_address = TRUE, + }; + if (label) + g_strlcpy(addr.label, label, sizeof(addr.label)); + + _LOG3D("address: adding or updating IPv4 address: %s", + nm_platform_ip4_address_to_string(&addr, NULL, 0)); + } + return klass->ip4_address_add(self, + ifindex, + address, + plen, + peer_address, + broadcast_address, + lifetime, + preferred, + flags, + label); } gboolean -nm_platform_ip6_address_add (NMPlatform *self, - int ifindex, - struct in6_addr address, - guint8 plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags) -{ - _CHECK_SELF (self, klass, FALSE); - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (plen <= 128, FALSE); - g_return_val_if_fail (lifetime > 0, FALSE); - g_return_val_if_fail (preferred <= lifetime, FALSE); - - if (_LOGD_ENABLED ()) { - NMPlatformIP6Address addr = { 0 }; - - addr.ifindex = ifindex; - addr.address = address; - addr.peer_address = peer_address; - addr.plen = plen; - addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */ - addr.lifetime = lifetime; - addr.preferred = preferred; - addr.n_ifa_flags = flags; - - _LOG3D ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr, NULL, 0)); - } - return klass->ip6_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, flags); +nm_platform_ip6_address_add(NMPlatform * self, + int ifindex, + struct in6_addr address, + guint8 plen, + struct in6_addr peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags) +{ + _CHECK_SELF(self, klass, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(plen <= 128, FALSE); + g_return_val_if_fail(lifetime > 0, FALSE); + g_return_val_if_fail(preferred <= lifetime, FALSE); + + if (_LOGD_ENABLED()) { + NMPlatformIP6Address addr = {0}; + + addr.ifindex = ifindex; + addr.address = address; + addr.peer_address = peer_address; + addr.plen = plen; + addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */ + addr.lifetime = lifetime; + addr.preferred = preferred; + addr.n_ifa_flags = flags; + + _LOG3D("address: adding or updating IPv6 address: %s", + nm_platform_ip6_address_to_string(&addr, NULL, 0)); + } + return klass + ->ip6_address_add(self, ifindex, address, plen, peer_address, lifetime, preferred, flags); } gboolean -nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address) +nm_platform_ip4_address_delete(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address) { - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char b1[NM_UTILS_INET_ADDRSTRLEN]; - char b2[NM_UTILS_INET_ADDRSTRLEN]; - char str_peer[INET_ADDRSTRLEN + 50]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char b1[NM_UTILS_INET_ADDRSTRLEN]; + char b2[NM_UTILS_INET_ADDRSTRLEN]; + char str_peer[INET_ADDRSTRLEN + 50]; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (plen <= 32, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(plen <= 32, FALSE); - _LOG3D ("address: deleting IPv4 address %s/%d, %s%s", - _nm_utils_inet4_ntop (address, b1), - plen, - peer_address != address - ? nm_sprintf_buf (str_peer, - "peer %s, ", - _nm_utils_inet4_ntop (peer_address, b2)) - : "", - _to_string_dev (self, ifindex, str_dev, sizeof (str_dev))); - return klass->ip4_address_delete (self, ifindex, address, plen, peer_address); + _LOG3D("address: deleting IPv4 address %s/%d, %s%s", + _nm_utils_inet4_ntop(address, b1), + plen, + peer_address != address + ? nm_sprintf_buf(str_peer, "peer %s, ", _nm_utils_inet4_ntop(peer_address, b2)) + : "", + _to_string_dev(self, ifindex, str_dev, sizeof(str_dev))); + return klass->ip4_address_delete(self, ifindex, address, plen, peer_address); } gboolean -nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen) +nm_platform_ip6_address_delete(NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen) { - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (plen <= 128, FALSE); + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(plen <= 128, FALSE); - _LOG3D ("address: deleting IPv6 address %s/%d, %s", - _nm_utils_inet6_ntop (&address, sbuf), plen, - _to_string_dev (self, ifindex, str_dev, sizeof (str_dev))); - return klass->ip6_address_delete (self, ifindex, address, plen); + _LOG3D("address: deleting IPv6 address %s/%d, %s", + _nm_utils_inet6_ntop(&address, sbuf), + plen, + _to_string_dev(self, ifindex, str_dev, sizeof(str_dev))); + return klass->ip6_address_delete(self, ifindex, address, plen); } const NMPlatformIP4Address * -nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, guint32 peer_address) +nm_platform_ip4_address_get(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address) { - NMPObject obj_id; - const NMPObject *obj; + NMPObject obj_id; + const NMPObject *obj; - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - g_return_val_if_fail (plen <= 32, NULL); + g_return_val_if_fail(plen <= 32, NULL); - nmp_object_stackinit_id_ip4_address (&obj_id, ifindex, address, plen, peer_address); - obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id); - nm_assert (!obj || nmp_object_is_visible (obj)); - return NMP_OBJECT_CAST_IP4_ADDRESS (obj); + nmp_object_stackinit_id_ip4_address(&obj_id, ifindex, address, plen, peer_address); + obj = nmp_cache_lookup_obj(nm_platform_get_cache(self), &obj_id); + nm_assert(!obj || nmp_object_is_visible(obj)); + return NMP_OBJECT_CAST_IP4_ADDRESS(obj); } const NMPlatformIP6Address * -nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address) +nm_platform_ip6_address_get(NMPlatform *self, int ifindex, const struct in6_addr *address) { - NMPObject obj_id; - const NMPObject *obj; + NMPObject obj_id; + const NMPObject *obj; + + _CHECK_SELF(self, klass, NULL); - _CHECK_SELF (self, klass, NULL); + nm_assert(address); - nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &address); - obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id); - nm_assert (!obj || nmp_object_is_visible (obj)); - return NMP_OBJECT_CAST_IP6_ADDRESS (obj); + nmp_object_stackinit_id_ip6_address(&obj_id, ifindex, address); + obj = nmp_cache_lookup_obj(nm_platform_get_cache(self), &obj_id); + nm_assert(!obj || nmp_object_is_visible(obj)); + return NMP_OBJECT_CAST_IP6_ADDRESS(obj); } static gboolean -_addr_array_clean_expired (int addr_family, int ifindex, GPtrArray *array, guint32 now, GHashTable **idx) +_addr_array_clean_expired(int addr_family, + int ifindex, + GPtrArray * array, + guint32 now, + GHashTable **idx) { - guint i; - gboolean any_addrs = FALSE; + guint i; + gboolean any_addrs = FALSE; - nm_assert_addr_family (addr_family); - nm_assert (ifindex > 0); - nm_assert (now > 0); + nm_assert_addr_family(addr_family); + nm_assert(ifindex > 0); + nm_assert(now > 0); - if (!array) - return FALSE; + if (!array) + return FALSE; - /* remove all addresses that are already expired. */ - for (i = 0; i < array->len; i++) { - const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS (array->pdata[i]); + /* remove all addresses that are already expired. */ + for (i = 0; i < array->len; i++) { + const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(array->pdata[i]); #if NM_MORE_ASSERTS > 10 - nm_assert (a); - nm_assert (a->ifindex == ifindex); - { - const NMPObject *o = NMP_OBJECT_UP_CAST (a); - guint j; - - nm_assert (NMP_OBJECT_GET_CLASS (o)->addr_family == addr_family); - for (j = i + 1; j < array->len; j++) { - const NMPObject *o2 = array->pdata[j]; - - nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_GET_TYPE (o2)); - nm_assert (!nmp_object_id_equal (o, o2)); - } - } + nm_assert(a); + nm_assert(a->ifindex == ifindex); + { + const NMPObject *o = NMP_OBJECT_UP_CAST(a); + guint j; + + nm_assert(NMP_OBJECT_GET_CLASS(o)->addr_family == addr_family); + for (j = i + 1; j < array->len; j++) { + const NMPObject *o2 = array->pdata[j]; + + nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_GET_TYPE(o2)); + nm_assert(!nmp_object_id_equal(o, o2)); + } + } #endif - if ( addr_family == AF_INET6 - && NM_FLAGS_HAS (a->n_ifa_flags, IFA_F_TEMPORARY)) { - /* temporary addresses are never added explicitly by NetworkManager but - * kernel adds them via mngtempaddr flag. - * - * We drop them from this list. */ - goto clear_and_next; - } - - if (!nm_utils_lifetime_get (a->timestamp, a->lifetime, a->preferred, - now, NULL)) - goto clear_and_next; - - if (idx) { - if (G_UNLIKELY (!*idx)) { - *idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal); - } - if (!g_hash_table_add (*idx, (gpointer) NMP_OBJECT_UP_CAST (a))) - nm_assert_not_reached (); - } - any_addrs = TRUE; - continue; + if (addr_family == AF_INET6 && NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TEMPORARY)) { + /* temporary addresses are never added explicitly by NetworkManager but + * kernel adds them via mngtempaddr flag. + * + * We drop them from this list. */ + goto clear_and_next; + } + + if (!nm_utils_lifetime_get(a->timestamp, a->lifetime, a->preferred, now, NULL)) + goto clear_and_next; + + if (idx) { + if (G_UNLIKELY(!*idx)) { + *idx = g_hash_table_new((GHashFunc) nmp_object_id_hash, + (GEqualFunc) nmp_object_id_equal); + } + if (!g_hash_table_add(*idx, (gpointer) NMP_OBJECT_UP_CAST(a))) + nm_assert_not_reached(); + } + any_addrs = TRUE; + continue; clear_and_next: - nmp_object_unref (g_steal_pointer (&array->pdata[i])); - } + nmp_object_unref(g_steal_pointer(&array->pdata[i])); + } - return any_addrs; + return any_addrs; } static gboolean -ip4_addr_subnets_is_plain_address (const GPtrArray *addresses, gconstpointer needle) +ip4_addr_subnets_is_plain_address(const GPtrArray *addresses, gconstpointer needle) { - return needle >= (gconstpointer) &addresses->pdata[0] - && needle < (gconstpointer) &addresses->pdata[addresses->len]; + return needle >= (gconstpointer) &addresses->pdata[0] + && needle < (gconstpointer) &addresses->pdata[addresses->len]; } static const NMPObject ** -ip4_addr_subnets_addr_list_get (const GPtrArray *addr_list, guint idx) +ip4_addr_subnets_addr_list_get(const GPtrArray *addr_list, guint idx) { - nm_assert (addr_list); - nm_assert (addr_list->len > 1); - nm_assert (idx < addr_list->len); - nm_assert (addr_list->pdata[idx]); - nm_assert ( !(*((gpointer *) addr_list->pdata[idx])) - || NMP_OBJECT_CAST_IP4_ADDRESS (*((gpointer *) addr_list->pdata[idx]))); - nm_assert (idx == 0 || ip4_addr_subnets_addr_list_get (addr_list, idx - 1)); - return addr_list->pdata[idx]; + nm_assert(addr_list); + nm_assert(addr_list->len > 1); + nm_assert(idx < addr_list->len); + nm_assert(addr_list->pdata[idx]); + nm_assert(!(*((gpointer *) addr_list->pdata[idx])) + || NMP_OBJECT_CAST_IP4_ADDRESS(*((gpointer *) addr_list->pdata[idx]))); + nm_assert(idx == 0 || ip4_addr_subnets_addr_list_get(addr_list, idx - 1)); + return addr_list->pdata[idx]; } static void -ip4_addr_subnets_destroy_index (GHashTable *subnets, const GPtrArray *addresses) +ip4_addr_subnets_destroy_index(GHashTable *subnets, const GPtrArray *addresses) { - GHashTableIter iter; - gpointer p; + GHashTableIter iter; + gpointer p; - if (!subnets) - return; + if (!subnets) + return; - g_hash_table_iter_init (&iter, subnets); - while (g_hash_table_iter_next (&iter, NULL, &p)) { - if (!ip4_addr_subnets_is_plain_address (addresses, p)) - g_ptr_array_free ((GPtrArray *) p, TRUE); - } + g_hash_table_iter_init(&iter, subnets); + while (g_hash_table_iter_next(&iter, NULL, &p)) { + if (!ip4_addr_subnets_is_plain_address(addresses, p)) + g_ptr_array_free((GPtrArray *) p, TRUE); + } - g_hash_table_unref (subnets); + g_hash_table_unref(subnets); } static GHashTable * -ip4_addr_subnets_build_index (const GPtrArray *addresses, - gboolean consider_flags, - gboolean full_index) -{ - GHashTable *subnets; - guint i; - - nm_assert (addresses && addresses->len); - - subnets = g_hash_table_new (nm_direct_hash, NULL); - - /* Build a hash table of all addresses per subnet */ - for (i = 0; i < addresses->len; i++) { - const NMPlatformIP4Address *address; - gpointer p_address; - GPtrArray *addr_list; - guint32 net; - int position; - gpointer p; - - if (!addresses->pdata[i]) - continue; - - p_address = &addresses->pdata[i]; - address = NMP_OBJECT_CAST_IP4_ADDRESS (addresses->pdata[i]); - - net = address->address & _nm_utils_ip4_prefix_to_netmask (address->plen); - if (!g_hash_table_lookup_extended (subnets, GUINT_TO_POINTER (net), NULL, &p)) { - g_hash_table_insert (subnets, GUINT_TO_POINTER (net), p_address); - continue; - } - nm_assert (p); - - if (full_index) { - if (ip4_addr_subnets_is_plain_address (addresses, p)) { - addr_list = g_ptr_array_new (); - g_hash_table_insert (subnets, GUINT_TO_POINTER (net), addr_list); - g_ptr_array_add (addr_list, p); - } else - addr_list = p; - - if ( !consider_flags - || NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY)) - position = -1; /* append */ - else - position = 0; /* prepend */ - g_ptr_array_insert (addr_list, position, p_address); - } else { - /* we only care about the primary. No need to track the secondaries - * as a GPtrArray. */ - nm_assert (ip4_addr_subnets_is_plain_address (addresses, p)); - if ( consider_flags - && !NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY)) { - g_hash_table_insert (subnets, GUINT_TO_POINTER (net), p_address); - } - } - } - - return subnets; +ip4_addr_subnets_build_index(const GPtrArray *addresses, + gboolean consider_flags, + gboolean full_index) +{ + GHashTable *subnets; + guint i; + + nm_assert(addresses && addresses->len); + + subnets = g_hash_table_new(nm_direct_hash, NULL); + + /* Build a hash table of all addresses per subnet */ + for (i = 0; i < addresses->len; i++) { + const NMPlatformIP4Address *address; + gpointer p_address; + GPtrArray * addr_list; + guint32 net; + int position; + gpointer p; + + if (!addresses->pdata[i]) + continue; + + p_address = &addresses->pdata[i]; + address = NMP_OBJECT_CAST_IP4_ADDRESS(addresses->pdata[i]); + + net = address->address & _nm_utils_ip4_prefix_to_netmask(address->plen); + if (!g_hash_table_lookup_extended(subnets, GUINT_TO_POINTER(net), NULL, &p)) { + g_hash_table_insert(subnets, GUINT_TO_POINTER(net), p_address); + continue; + } + nm_assert(p); + + if (full_index) { + if (ip4_addr_subnets_is_plain_address(addresses, p)) { + addr_list = g_ptr_array_new(); + g_hash_table_insert(subnets, GUINT_TO_POINTER(net), addr_list); + g_ptr_array_add(addr_list, p); + } else + addr_list = p; + + if (!consider_flags || NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_SECONDARY)) + position = -1; /* append */ + else + position = 0; /* prepend */ + g_ptr_array_insert(addr_list, position, p_address); + } else { + /* we only care about the primary. No need to track the secondaries + * as a GPtrArray. */ + nm_assert(ip4_addr_subnets_is_plain_address(addresses, p)); + if (consider_flags && !NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_SECONDARY)) { + g_hash_table_insert(subnets, GUINT_TO_POINTER(net), p_address); + } + } + } + + return subnets; } /** @@ -3712,237 +3880,76 @@ ip4_addr_subnets_build_index (const GPtrArray *addresses, * Returns: %TRUE if the address is secondary, %FALSE otherwise */ static gboolean -ip4_addr_subnets_is_secondary (const NMPObject *address, - GHashTable *subnets, - const GPtrArray *addresses, - const GPtrArray **out_addr_list) -{ - const NMPlatformIP4Address *a; - const GPtrArray *addr_list; - gconstpointer p; - guint32 net; - const NMPObject **o; - - a = NMP_OBJECT_CAST_IP4_ADDRESS (address); - - net = a->address & _nm_utils_ip4_prefix_to_netmask (a->plen); - p = g_hash_table_lookup (subnets, GUINT_TO_POINTER (net)); - nm_assert (p); - if (!ip4_addr_subnets_is_plain_address (addresses, p)) { - addr_list = p; - nm_assert (addr_list->len > 1); - NM_SET_OUT (out_addr_list, addr_list); - o = ip4_addr_subnets_addr_list_get (addr_list, 0); - nm_assert (o && *o); - if (*o != address) - return TRUE; - } else { - NM_SET_OUT (out_addr_list, NULL); - return address != *((gconstpointer *) p); - } - return FALSE; -} - -/** - * nm_platform_ip4_address_sync: - * @self: platform instance - * @ifindex: Interface index - * @known_addresses: List of addresses. The list will be modified and only - * addresses that were successfully added will be kept in the list. - * That means, expired addresses and addresses that could not be added - * will be dropped. - * Hence, the input argument @known_addresses is also an output argument - * telling which addresses were successfully added. - * Addresses are removed by unrefing the instance via nmp_object_unref() - * and leaving a NULL tombstone. - * - * A convenience function to synchronize addresses for a specific interface - * with the least possible disturbance. It simply removes addresses that are - * not listed and adds addresses that are. - * - * Returns: %TRUE on success. - */ -gboolean -nm_platform_ip4_address_sync (NMPlatform *self, - int ifindex, - GPtrArray *known_addresses) -{ - gs_unref_ptrarray GPtrArray *plat_addresses = NULL; - const NMPlatformIP4Address *known_address; - gint32 now = nm_utils_get_monotonic_timestamp_sec (); - GHashTable *plat_subnets = NULL; - GHashTable *known_subnets = NULL; - gs_unref_hashtable GHashTable *known_addresses_idx = NULL; - guint i, j, len; - NMPLookup lookup; - guint32 lifetime, preferred; - guint32 ifa_flags; - - _CHECK_SELF (self, klass, FALSE); - - if (!_addr_array_clean_expired (AF_INET, ifindex, known_addresses, now, &known_addresses_idx)) - known_addresses = NULL; - - plat_addresses = nm_platform_lookup_clone (self, - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_IP4_ADDRESS, - ifindex), - NULL, NULL); - if (plat_addresses) - plat_subnets = ip4_addr_subnets_build_index (plat_addresses, TRUE, TRUE); - - /* Delete unknown addresses */ - len = plat_addresses ? plat_addresses->len : 0; - for (i = 0; i < len; i++) { - const NMPObject *plat_obj; - const NMPlatformIP4Address *plat_address; - const GPtrArray *addr_list; - - plat_obj = plat_addresses->pdata[i]; - if (!plat_obj) { - /* Already deleted */ - continue; - } - - plat_address = NMP_OBJECT_CAST_IP4_ADDRESS (plat_obj); - - if (known_addresses) { - const NMPObject *o; - - o = g_hash_table_lookup (known_addresses_idx, plat_obj); - if (o) { - gboolean secondary; - - if (!known_subnets) - known_subnets = ip4_addr_subnets_build_index (known_addresses, FALSE, FALSE); - - secondary = ip4_addr_subnets_is_secondary (o, known_subnets, known_addresses, NULL); - if (secondary == NM_FLAGS_HAS (plat_address->n_ifa_flags, IFA_F_SECONDARY)) { - /* if we have an existing known-address, with matching secondary role, - * do not delete the platform-address. */ - continue; - } - } - } - - nm_platform_ip4_address_delete (self, ifindex, - plat_address->address, - plat_address->plen, - plat_address->peer_address); - - if ( !ip4_addr_subnets_is_secondary (plat_obj, plat_subnets, plat_addresses, &addr_list) - && addr_list) { - /* If we just deleted a primary addresses and there were - * secondary ones the kernel can do two things, depending on - * version and sysctl setting: delete also secondary addresses - * or promote a secondary to primary. Ensure that secondary - * addresses are deleted, so that we can start with a clean - * slate and add addresses in the right order. */ - for (j = 1; j < addr_list->len; j++) { - const NMPObject **o; - - o = ip4_addr_subnets_addr_list_get (addr_list, j); - nm_assert (o); - - if (*o) { - const NMPlatformIP4Address *a; - - a = NMP_OBJECT_CAST_IP4_ADDRESS (*o); - nm_platform_ip4_address_delete (self, ifindex, - a->address, - a->plen, - a->peer_address); - nmp_object_unref (*o); - *o = NULL; - } - } - } - } - ip4_addr_subnets_destroy_index (plat_subnets, plat_addresses); - - if (!known_addresses) - return TRUE; - - ip4_addr_subnets_destroy_index (known_subnets, known_addresses); - - ifa_flags = nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) - ? IFA_F_NOPREFIXROUTE - : 0; - - /* Add missing addresses */ - for (i = 0; i < known_addresses->len; i++) { - const NMPObject *o; - - o = known_addresses->pdata[i]; - if (!o) - continue; - - known_address = NMP_OBJECT_CAST_IP4_ADDRESS (o); - - lifetime = nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, - now, &preferred); - if (!lifetime) - goto delete_and_next2; - - if (!nm_platform_ip4_address_add (self, - ifindex, - known_address->address, - known_address->plen, - known_address->peer_address, - nm_platform_ip4_broadcast_address_from_addr (known_address), - lifetime, - preferred, - ifa_flags, - known_address->label)) - goto delete_and_next2; - - continue; -delete_and_next2: - nmp_object_unref (o); - known_addresses->pdata[i] = NULL; - } - - return TRUE; +ip4_addr_subnets_is_secondary(const NMPObject * address, + GHashTable * subnets, + const GPtrArray * addresses, + const GPtrArray **out_addr_list) +{ + const NMPlatformIP4Address *a; + const GPtrArray * addr_list; + gconstpointer p; + guint32 net; + const NMPObject ** o; + + a = NMP_OBJECT_CAST_IP4_ADDRESS(address); + + net = a->address & _nm_utils_ip4_prefix_to_netmask(a->plen); + p = g_hash_table_lookup(subnets, GUINT_TO_POINTER(net)); + nm_assert(p); + if (!ip4_addr_subnets_is_plain_address(addresses, p)) { + addr_list = p; + nm_assert(addr_list->len > 1); + NM_SET_OUT(out_addr_list, addr_list); + o = ip4_addr_subnets_addr_list_get(addr_list, 0); + nm_assert(o && *o); + if (*o != address) + return TRUE; + } else { + NM_SET_OUT(out_addr_list, NULL); + return address != *((gconstpointer *) p); + } + return FALSE; } typedef enum { - IP6_ADDR_SCOPE_LOOPBACK, - IP6_ADDR_SCOPE_LINKLOCAL, - IP6_ADDR_SCOPE_SITELOCAL, - IP6_ADDR_SCOPE_OTHER, + IP6_ADDR_SCOPE_LOOPBACK, + IP6_ADDR_SCOPE_LINKLOCAL, + IP6_ADDR_SCOPE_SITELOCAL, + IP6_ADDR_SCOPE_OTHER, } IP6AddrScope; static IP6AddrScope -ip6_address_scope (const NMPlatformIP6Address *a) +ip6_address_scope(const NMPlatformIP6Address *a) { - if (IN6_IS_ADDR_LOOPBACK (&a->address)) - return IP6_ADDR_SCOPE_LOOPBACK; - if (IN6_IS_ADDR_LINKLOCAL (&a->address)) - return IP6_ADDR_SCOPE_LINKLOCAL; - if (IN6_IS_ADDR_SITELOCAL (&a->address)) - return IP6_ADDR_SCOPE_SITELOCAL; - return IP6_ADDR_SCOPE_OTHER; + if (IN6_IS_ADDR_LOOPBACK(&a->address)) + return IP6_ADDR_SCOPE_LOOPBACK; + if (IN6_IS_ADDR_LINKLOCAL(&a->address)) + return IP6_ADDR_SCOPE_LINKLOCAL; + if (IN6_IS_ADDR_SITELOCAL(&a->address)) + return IP6_ADDR_SCOPE_SITELOCAL; + return IP6_ADDR_SCOPE_OTHER; } static int -ip6_address_scope_cmp (gconstpointer p_a, gconstpointer p_b, gpointer increasing) +ip6_address_scope_cmp(gconstpointer p_a, gconstpointer p_b, gpointer increasing) { - const NMPlatformIP6Address *a; - const NMPlatformIP6Address *b; + const NMPlatformIP6Address *a; + const NMPlatformIP6Address *b; - if (!increasing) - NM_SWAP (p_a, p_b); + if (!increasing) + NM_SWAP(&p_a, &p_b); - a = NMP_OBJECT_CAST_IP6_ADDRESS (*(const NMPObject *const*) p_a); - b = NMP_OBJECT_CAST_IP6_ADDRESS (*(const NMPObject *const*) p_b); + a = NMP_OBJECT_CAST_IP6_ADDRESS(*(const NMPObject *const *) p_a); + b = NMP_OBJECT_CAST_IP6_ADDRESS(*(const NMPObject *const *) p_b); - NM_CMP_DIRECT (ip6_address_scope (a), ip6_address_scope (b)); - return 0; + NM_CMP_DIRECT(ip6_address_scope(a), ip6_address_scope(b)); + return 0; } /** - * nm_platform_ip6_address_sync: + * nm_platform_ip_address_sync: * @self: platform instance + * @addr_family: the address family AF_INET or AF_INET6. * @ifindex: Interface index * @known_addresses: List of addresses. The list will be modified and only * addresses that were successfully added will be kept in the list. @@ -3952,7 +3959,13 @@ ip6_address_scope_cmp (gconstpointer p_a, gconstpointer p_b, gpointer increasing * telling which addresses were successfully added. * Addresses are removed by unrefing the instance via nmp_object_unref() * and leaving a NULL tombstone. - * @full_sync: Also remove link-local and temporary addresses. + * @addresses_prune: (allow-none): the list of addresses to delete. + * If platform has such an address configured, it will be deleted + * at the beginning of the sync. Note that the array will be modified + * by the function. + * Note that the addresses must be properly sorted, by their priority. + * Create this list with nm_platform_ip_address_get_prune_list() which + * gets the sorting right. * * A convenience function to synchronize addresses for a specific interface * with the least possible disturbance. It simply removes addresses that are @@ -3961,286 +3974,446 @@ ip6_address_scope_cmp (gconstpointer p_a, gconstpointer p_b, gpointer increasing * Returns: %TRUE on success. */ gboolean -nm_platform_ip6_address_sync (NMPlatform *self, - int ifindex, - GPtrArray *known_addresses, - gboolean full_sync) -{ - gs_unref_ptrarray GPtrArray *plat_addresses = NULL; - gint32 now = nm_utils_get_monotonic_timestamp_sec (); - guint i_plat, i_know; - gs_unref_hashtable GHashTable *known_addresses_idx = NULL; - NMPLookup lookup; - guint32 ifa_flags; - - /* The order we want to enforce is only among addresses with the same - * scope, as the kernel keeps addresses sorted by scope. Therefore, - * apply the same sorting to known addresses, so that we don't try to - * unnecessary change the order of addresses with different scopes. */ - if (known_addresses) - g_ptr_array_sort_with_data (known_addresses, ip6_address_scope_cmp, GINT_TO_POINTER (TRUE)); - - if (!_addr_array_clean_expired (AF_INET6, ifindex, known_addresses, now, &known_addresses_idx)) - known_addresses = NULL; - - /* @plat_addresses is in decreasing priority order (highest priority addresses first), contrary to - * @known_addresses which is in increasing priority order (lowest priority addresses first). */ - plat_addresses = nm_platform_lookup_clone (self, - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_IP6_ADDRESS, - ifindex), - NULL, NULL); - - if (plat_addresses) { - guint known_addresses_len; - IP6AddrScope cur_scope; - gboolean delete_remaining_addrs; - - g_ptr_array_sort_with_data (plat_addresses, ip6_address_scope_cmp, GINT_TO_POINTER (FALSE)); - - known_addresses_len = known_addresses ? known_addresses->len : 0; - - /* First, compare every address whether it is still a "known address", that is, whether - * to keep it or to delete it. - * - * If we don't find a matching valid address in @known_addresses, we will delete - * plat_addr. - * - * Certain addresses, like temporary addresses, are ignored by this function - * if not run with full_sync. These addresses are usually not managed by NetworkManager - * directly, or at least, they are not managed via nm_platform_ip6_address_sync(). - * Only in full_sync mode, we really want to get rid of them (usually, when we take - * the interface down). - * - * Note that we mark handled addresses by setting it to %NULL in @plat_addresses array. */ - for (i_plat = 0; i_plat < plat_addresses->len; i_plat++) { - const NMPObject *plat_obj = plat_addresses->pdata[i_plat]; - const NMPObject *know_obj; - const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS (plat_obj); - - if (NM_FLAGS_HAS (plat_addr->n_ifa_flags, IFA_F_TEMPORARY)) { - if (!full_sync) { - /* just mark as handled, without actually deleting the address. */ - goto clear_and_next; - } - } else if (known_addresses_idx) { - know_obj = g_hash_table_lookup (known_addresses_idx, plat_obj); - if ( know_obj - && plat_addr->plen == NMP_OBJECT_CAST_IP6_ADDRESS (know_obj)->plen) { - /* technically, plen is not part of the ID for IPv6 addresses and thus - * @plat_addr is essentially the same address as @know_addr (regrading - * its identity, not its other attributes). - * However, we cannot modify an existing addresses' plen without - * removing and readding it. Thus, only keep plat_addr, if the plen - * matches. - * - * keep this one, and continue */ - continue; - } - } - - nm_platform_ip6_address_delete (self, ifindex, plat_addr->address, plat_addr->plen); -clear_and_next: - nmp_object_unref (g_steal_pointer (&plat_addresses->pdata[i_plat])); - } - - /* Next, we must preserve the priority of the routes. That is, source address - * selection will choose addresses in the order as they are reported by kernel. - * Note that the order in @plat_addresses of the remaining matches is highest - * priority first. - * We need to compare this to the order of addresses with same scope in - * @known_addresses (which has lowest priority first). - * - * If we find a first discrepancy, we need to delete all remaining addresses - * with same scope from that point on, because below we must re-add all the - * addresses in the right order to get their priority right. */ - cur_scope = IP6_ADDR_SCOPE_LOOPBACK; - delete_remaining_addrs = FALSE; - i_plat = plat_addresses->len; - i_know = 0; - while (i_plat > 0) { - const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS (plat_addresses->pdata[--i_plat]); - IP6AddrScope plat_scope; - - if (!plat_addr) - continue; - - plat_scope = ip6_address_scope (plat_addr); - if (cur_scope != plat_scope) { - nm_assert (cur_scope < plat_scope); - delete_remaining_addrs = FALSE; - cur_scope = plat_scope; - } - - if (!delete_remaining_addrs) { - delete_remaining_addrs = TRUE; - for (; i_know < known_addresses_len; i_know++) { - const NMPlatformIP6Address *know_addr = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i_know]); - IP6AddrScope know_scope; - - if (!know_addr) - continue; - - know_scope = ip6_address_scope (know_addr); - if (know_scope < plat_scope) - continue; - - if (IN6_ARE_ADDR_EQUAL (&plat_addr->address, &know_addr->address)) { - /* we have a match. Mark address as handled. */ - i_know++; - delete_remaining_addrs = FALSE; - goto next_plat; - } - - /* plat_address has no match. Now delete_remaining_addrs is TRUE and we will - * delete all the remaining addresses with cur_scope. */ - break; - } - } - - nm_platform_ip6_address_delete (self, ifindex, plat_addr->address, plat_addr->plen); -next_plat: - ; - } - } - - if (!known_addresses) - return TRUE; - - ifa_flags = nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) - ? IFA_F_NOPREFIXROUTE - : 0; - - /* Add missing addresses. New addresses are added by kernel with top - * priority. - */ - for (i_know = 0; i_know < known_addresses->len; i_know++) { - const NMPlatformIP6Address *known_address = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i_know]); - guint32 lifetime, preferred; - - if (!known_address) - continue; - - lifetime = nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred, - now, &preferred); - - if (!nm_platform_ip6_address_add (self, ifindex, known_address->address, - known_address->plen, known_address->peer_address, - lifetime, preferred, - ifa_flags | known_address->n_ifa_flags)) - return FALSE; - } - - return TRUE; +nm_platform_ip_address_sync(NMPlatform *self, + int addr_family, + int ifindex, + GPtrArray * known_addresses, + GPtrArray * addresses_prune) +{ + const gint32 now = nm_utils_get_monotonic_timestamp_sec(); + const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + gs_unref_hashtable GHashTable *known_addresses_idx = NULL; + GPtrArray * plat_addresses; + GHashTable * known_subnets = NULL; + guint32 ifa_flags; + guint i_plat; + guint i_know; + guint i; + guint j; + + _CHECK_SELF(self, klass, FALSE); + + /* The order we want to enforce is only among addresses with the same + * scope, as the kernel keeps addresses sorted by scope. Therefore, + * apply the same sorting to known addresses, so that we don't try to + * unnecessary change the order of addresses with different scopes. */ + if (!IS_IPv4) { + if (known_addresses) + g_ptr_array_sort_with_data(known_addresses, + ip6_address_scope_cmp, + GINT_TO_POINTER(TRUE)); + } + + if (!_addr_array_clean_expired(addr_family, + ifindex, + known_addresses, + now, + &known_addresses_idx)) + known_addresses = NULL; + + /* @plat_addresses must be sorted in decreasing priority order (highest priority addresses first), contrary to + * @known_addresses which is in increasing priority order (lowest priority addresses first). */ + plat_addresses = addresses_prune; + + if (nm_g_ptr_array_len(plat_addresses) > 0) { + /* Delete unknown addresses */ + if (IS_IPv4) { + GHashTable *plat_subnets; + + plat_subnets = ip4_addr_subnets_build_index(plat_addresses, TRUE, TRUE); + + for (i = 0; i < plat_addresses->len; i++) { + const NMPObject * plat_obj; + const NMPlatformIP4Address *plat_address; + const GPtrArray * addr_list; + + plat_obj = plat_addresses->pdata[i]; + if (!plat_obj) { + /* Already deleted */ + continue; + } + + plat_address = NMP_OBJECT_CAST_IP4_ADDRESS(plat_obj); + + if (known_addresses) { + const NMPObject *o; + + o = g_hash_table_lookup(known_addresses_idx, plat_obj); + if (o) { + gboolean secondary; + + if (!known_subnets) + known_subnets = + ip4_addr_subnets_build_index(known_addresses, FALSE, FALSE); + + secondary = + ip4_addr_subnets_is_secondary(o, known_subnets, known_addresses, NULL); + if (secondary == NM_FLAGS_HAS(plat_address->n_ifa_flags, IFA_F_SECONDARY)) { + /* if we have an existing known-address, with matching secondary role, + * do not delete the platform-address. */ + continue; + } + } + } + + nm_platform_ip4_address_delete(self, + ifindex, + plat_address->address, + plat_address->plen, + plat_address->peer_address); + + if (!ip4_addr_subnets_is_secondary(plat_obj, + plat_subnets, + plat_addresses, + &addr_list) + && addr_list) { + /* If we just deleted a primary addresses and there were + * secondary ones the kernel can do two things, depending on + * version and sysctl setting: delete also secondary addresses + * or promote a secondary to primary. Ensure that secondary + * addresses are deleted, so that we can start with a clean + * slate and add addresses in the right order. */ + for (j = 1; j < addr_list->len; j++) { + const NMPObject **o; + + o = ip4_addr_subnets_addr_list_get(addr_list, j); + nm_assert(o); + + if (*o) { + const NMPlatformIP4Address *a; + + a = NMP_OBJECT_CAST_IP4_ADDRESS(*o); + nm_platform_ip4_address_delete(self, + ifindex, + a->address, + a->plen, + a->peer_address); + nmp_object_unref(*o); + *o = NULL; + } + } + } + } + ip4_addr_subnets_destroy_index(plat_subnets, plat_addresses); + } else { + guint known_addresses_len; + IP6AddrScope cur_scope; + gboolean delete_remaining_addrs; + + g_ptr_array_sort_with_data(plat_addresses, + ip6_address_scope_cmp, + GINT_TO_POINTER(FALSE)); + + known_addresses_len = known_addresses ? known_addresses->len : 0; + + /* First, compare every address whether it is still a "known address", that is, whether + * to keep it or to delete it. + * + * If we don't find a matching valid address in @known_addresses, we will delete + * plat_addr. + * + * Certain addresses, like temporary addresses, are ignored by this function + * if not run with full_sync. These addresses are usually not managed by NetworkManager + * directly, or at least, they are not managed via nm_platform_ip6_address_sync(). + * Only in full_sync mode, we really want to get rid of them (usually, when we take + * the interface down). + * + * Note that we mark handled addresses by setting it to %NULL in @plat_addresses array. */ + for (i_plat = 0; i_plat < plat_addresses->len; i_plat++) { + const NMPObject * plat_obj = plat_addresses->pdata[i_plat]; + const NMPObject * know_obj; + const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS(plat_obj); + + if (known_addresses_idx) { + know_obj = g_hash_table_lookup(known_addresses_idx, plat_obj); + if (know_obj + && plat_addr->plen == NMP_OBJECT_CAST_IP6_ADDRESS(know_obj)->plen) { + /* technically, plen is not part of the ID for IPv6 addresses and thus + * @plat_addr is essentially the same address as @know_addr (regrading + * its identity, not its other attributes). + * However, we cannot modify an existing addresses' plen without + * removing and readding it. Thus, only keep plat_addr, if the plen + * matches. + * + * keep this one, and continue */ + continue; + } + } + + nm_platform_ip6_address_delete(self, ifindex, plat_addr->address, plat_addr->plen); + nmp_object_unref(g_steal_pointer(&plat_addresses->pdata[i_plat])); + } + + /* Next, we must preserve the priority of the routes. That is, source address + * selection will choose addresses in the order as they are reported by kernel. + * Note that the order in @plat_addresses of the remaining matches is highest + * priority first. + * We need to compare this to the order of addresses with same scope in + * @known_addresses (which has lowest priority first). + * + * If we find a first discrepancy, we need to delete all remaining addresses + * with same scope from that point on, because below we must re-add all the + * addresses in the right order to get their priority right. */ + cur_scope = IP6_ADDR_SCOPE_LOOPBACK; + delete_remaining_addrs = FALSE; + i_plat = plat_addresses->len; + i_know = 0; + while (i_plat > 0) { + const NMPlatformIP6Address *plat_addr = + NMP_OBJECT_CAST_IP6_ADDRESS(plat_addresses->pdata[--i_plat]); + IP6AddrScope plat_scope; + + if (!plat_addr) + continue; + + plat_scope = ip6_address_scope(plat_addr); + if (cur_scope != plat_scope) { + nm_assert(cur_scope < plat_scope); + delete_remaining_addrs = FALSE; + cur_scope = plat_scope; + } + + if (!delete_remaining_addrs) { + delete_remaining_addrs = TRUE; + for (; i_know < known_addresses_len; i_know++) { + const NMPlatformIP6Address *know_addr = + NMP_OBJECT_CAST_IP6_ADDRESS(known_addresses->pdata[i_know]); + IP6AddrScope know_scope; + + if (!know_addr) + continue; + + know_scope = ip6_address_scope(know_addr); + if (know_scope < plat_scope) + continue; + + if (IN6_ARE_ADDR_EQUAL(&plat_addr->address, &know_addr->address)) { + /* we have a match. Mark address as handled. */ + i_know++; + delete_remaining_addrs = FALSE; + goto next_plat; + } + + /* plat_address has no match. Now delete_remaining_addrs is TRUE and we will + * delete all the remaining addresses with cur_scope. */ + break; + } + } + + nm_platform_ip6_address_delete(self, ifindex, plat_addr->address, plat_addr->plen); +next_plat:; + } + } + } + + if (!known_addresses) + return TRUE; + + if (IS_IPv4) + ip4_addr_subnets_destroy_index(known_subnets, known_addresses); + + ifa_flags = nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS) + ? IFA_F_NOPREFIXROUTE + : 0; + + /* Add missing addresses. New addresses are added by kernel with top + * priority. + */ + for (i_know = 0; i_know < known_addresses->len; i_know++) { + const NMPlatformIPXAddress *known_address; + const NMPObject * o; + guint32 lifetime; + guint32 preferred; + + o = known_addresses->pdata[i_know]; + if (!o) + continue; + + nm_assert(NMP_OBJECT_GET_TYPE(o) == NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)); + + known_address = NMP_OBJECT_CAST_IPX_ADDRESS(o); + + lifetime = nm_utils_lifetime_get(known_address->ax.timestamp, + known_address->ax.lifetime, + known_address->ax.preferred, + now, + &preferred); + nm_assert(lifetime > 0); + + if (IS_IPv4) { + if (!nm_platform_ip4_address_add( + self, + ifindex, + known_address->a4.address, + known_address->a4.plen, + known_address->a4.peer_address, + nm_platform_ip4_broadcast_address_from_addr(&known_address->a4), + lifetime, + preferred, + ifa_flags, + known_address->a4.label)) { + /* ignore error, for unclear reasons. */ + } + } else { + if (!nm_platform_ip6_address_add(self, + ifindex, + known_address->a6.address, + known_address->a6.plen, + known_address->a6.peer_address, + lifetime, + preferred, + ifa_flags | known_address->a6.n_ifa_flags)) + return FALSE; + } + } + + return TRUE; } gboolean -nm_platform_ip_address_flush (NMPlatform *self, - int addr_family, - int ifindex) +nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex) { - gboolean success = TRUE; + gboolean success = TRUE; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, - AF_INET, - AF_INET6)); + nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) - success &= nm_platform_ip4_address_sync (self, ifindex, NULL); - if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) - success &= nm_platform_ip6_address_sync (self, ifindex, NULL, TRUE); - return success; + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) + success &= nm_platform_ip4_address_sync(self, ifindex, NULL); + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) + success &= nm_platform_ip6_address_sync(self, ifindex, NULL, TRUE); + return success; } /*****************************************************************************/ static gboolean -_err_inval_due_to_ipv6_tentative_pref_src (NMPlatform *self, const NMPObject *obj) +_err_inval_due_to_ipv6_tentative_pref_src(NMPlatform *self, const NMPObject *obj) +{ + const NMPlatformIP6Route * r; + const NMPlatformIP6Address *a; + + nm_assert(NM_IS_PLATFORM(self)); + nm_assert(NMP_OBJECT_IS_VALID(obj)); + + /* trying to add an IPv6 route with pref-src fails, if the address is + * still tentative (rh#1452684). We need to hack around that. + * + * Detect it, by guessing whether that's the case. */ + + if (NMP_OBJECT_GET_TYPE(obj) != NMP_OBJECT_TYPE_IP6_ROUTE) + return FALSE; + + r = NMP_OBJECT_CAST_IP6_ROUTE(obj); + + /* we only allow this workaround for routes added manually by the user. */ + if (r->rt_source != NM_IP_CONFIG_SOURCE_USER) + return FALSE; + + if (IN6_IS_ADDR_UNSPECIFIED(&r->pref_src)) + return FALSE; + + a = nm_platform_ip6_address_get(self, r->ifindex, &r->pref_src); + if (!a) + return FALSE; + if (!NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TENTATIVE) + || NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_DADFAILED)) + return FALSE; + + return TRUE; +} + +GPtrArray * +nm_platform_ip_address_get_prune_list(NMPlatform *self, + int addr_family, + int ifindex, + gboolean exclude_ipv6_temporary_addrs) { - const NMPlatformIP6Route *r; - const NMPlatformIP6Address *a; + const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const NMDedupMultiHeadEntry *head_entry; + NMPLookup lookup; + GPtrArray * result; + CList * iter; - nm_assert (NM_IS_PLATFORM (self)); - nm_assert (NMP_OBJECT_IS_VALID (obj)); + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(NM_IS_IPv4(addr_family)), ifindex); - /* trying to add an IPv6 route with pref-src fails, if the address is - * still tentative (rh#1452684). We need to hack around that. - * - * Detect it, by guessing whether that's the case. */ + head_entry = nm_platform_lookup(self, &lookup); - if (NMP_OBJECT_GET_TYPE (obj) != NMP_OBJECT_TYPE_IP6_ROUTE) - return FALSE; + if (!head_entry) + return NULL; - r = NMP_OBJECT_CAST_IP6_ROUTE (obj); + result = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nmp_object_unref); - /* we only allow this workaround for routes added manually by the user. */ - if (r->rt_source != NM_IP_CONFIG_SOURCE_USER) - return FALSE; + c_list_for_each (iter, &head_entry->lst_entries_head) { + const NMPObject *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj; - if (IN6_IS_ADDR_UNSPECIFIED (&r->pref_src)) - return FALSE; + if (!IS_IPv4) { + if (exclude_ipv6_temporary_addrs + && NM_FLAGS_HAS(NMP_OBJECT_CAST_IP_ADDRESS(obj)->n_ifa_flags, IFA_F_TEMPORARY)) + continue; + } - a = nm_platform_ip6_address_get (self, r->ifindex, r->pref_src); - if (!a) - return FALSE; - if ( !NM_FLAGS_HAS (a->n_ifa_flags, IFA_F_TENTATIVE) - || NM_FLAGS_HAS (a->n_ifa_flags, IFA_F_DADFAILED)) - return FALSE; + g_ptr_array_add(result, (gpointer) nmp_object_ref(obj)); + } - return TRUE; + if (result->len == 0) { + g_ptr_array_unref(result); + return NULL; + } + return result; } GPtrArray * -nm_platform_ip_route_get_prune_list (NMPlatform *self, - int addr_family, - int ifindex, - NMIPRouteTableSyncMode route_table_sync) -{ - NMPLookup lookup; - GPtrArray *routes_prune; - const NMDedupMultiHeadEntry *head_entry; - CList *iter; - - nm_assert (NM_IS_PLATFORM (self)); - nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - nm_assert (NM_IN_SET (route_table_sync, NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, - NM_IP_ROUTE_TABLE_SYNC_MODE_FULL, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL)); - - nmp_lookup_init_object (&lookup, - addr_family == AF_INET - ? NMP_OBJECT_TYPE_IP4_ROUTE - : NMP_OBJECT_TYPE_IP6_ROUTE, - ifindex); - head_entry = nm_platform_lookup (self, &lookup); - if (!head_entry) - return NULL; - - routes_prune = g_ptr_array_new_full (head_entry->len, - (GDestroyNotify) nm_dedup_multi_obj_unref); - - c_list_for_each (iter, &head_entry->lst_entries_head) { - const NMPObject *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj; - - if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_FULL) { - if (nm_platform_route_table_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced, TRUE) == RT_TABLE_LOCAL) - continue; - } else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) { - if (!nm_platform_route_table_is_main (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced)) - continue; - } else - nm_assert (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); - - g_ptr_array_add (routes_prune, (gpointer) nmp_object_ref (obj)); - } - - if (routes_prune->len == 0) { - g_ptr_array_unref (routes_prune); - return NULL; - } - return routes_prune; +nm_platform_ip_route_get_prune_list(NMPlatform * self, + int addr_family, + int ifindex, + NMIPRouteTableSyncMode route_table_sync) +{ + NMPLookup lookup; + GPtrArray * routes_prune; + const NMDedupMultiHeadEntry *head_entry; + CList * iter; + + nm_assert(NM_IS_PLATFORM(self)); + nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + nm_assert(NM_IN_SET(route_table_sync, + NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, + NM_IP_ROUTE_TABLE_SYNC_MODE_FULL, + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL)); + + nmp_lookup_init_object(&lookup, + addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ROUTE + : NMP_OBJECT_TYPE_IP6_ROUTE, + ifindex); + head_entry = nm_platform_lookup(self, &lookup); + if (!head_entry) + return NULL; + + routes_prune = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref); + + c_list_for_each (iter, &head_entry->lst_entries_head) { + const NMPObject *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj; + + if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_FULL) { + if (nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj)) + == RT_TABLE_LOCAL) + continue; + } else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) { + if (!nm_platform_route_table_is_main( + nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj)))) + continue; + } else + nm_assert(route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); + + g_ptr_array_add(routes_prune, (gpointer) nmp_object_ref(obj)); + } + + if (routes_prune->len == 0) { + g_ptr_array_unref(routes_prune); + return NULL; + } + return routes_prune; } /** @@ -4261,288 +4434,319 @@ nm_platform_ip_route_get_prune_list (NMPlatform *self, * Returns: %TRUE on success. */ gboolean -nm_platform_ip_route_sync (NMPlatform *self, - int addr_family, - int ifindex, - GPtrArray *routes, - GPtrArray *routes_prune, - GPtrArray **out_temporary_not_available) -{ - const NMPlatformVTableRoute *vt; - gs_unref_hashtable GHashTable *routes_idx = NULL; - const NMPObject *conf_o; - const NMDedupMultiEntry *plat_entry; - guint i; - int i_type; - gboolean success = TRUE; - char sbuf1[sizeof (_nm_utils_to_string_buffer)]; - char sbuf2[sizeof (_nm_utils_to_string_buffer)]; - const gboolean IS_IPv4 = (addr_family == AF_INET); - - nm_assert (NM_IS_PLATFORM (self)); - nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - nm_assert (ifindex > 0); - - vt = &nm_platform_vtable_route.vx[IS_IPv4]; - - for (i_type = 0; routes && i_type < 2; i_type++) { - for (i = 0; i < routes->len; i++) { - int r, r2; - gboolean gateway_route_added = FALSE; - - conf_o = routes->pdata[i]; - -#define VTABLE_IS_DEVICE_ROUTE(vt, o) (vt->is_ip4 \ - ? (NMP_OBJECT_CAST_IP4_ROUTE (o)->gateway == 0) \ - : IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (o)->gateway) ) - - if ( (i_type == 0 && !VTABLE_IS_DEVICE_ROUTE (vt, conf_o)) - || (i_type == 1 && VTABLE_IS_DEVICE_ROUTE (vt, conf_o))) { - /* we add routes in two runs over @i_type. - * - * First device routes, then gateway routes. */ - continue; - } - - if (!routes_idx) { - routes_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal); - } - if (!g_hash_table_insert (routes_idx, (gpointer) conf_o, (gpointer) conf_o)) { - _LOG3D ("route-sync: skip adding duplicate route %s", - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1))); - continue; - } - - if ( !IS_IPv4 - && NMP_OBJECT_CAST_IP6_ROUTE (conf_o)->metric == 0) { - /* User space cannot add routes with metric 0. However, kernel can, and we might track such - * routes in @route as they are present external. Skip them silently. */ - continue; - } - - plat_entry = nm_platform_lookup_entry (self, - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - conf_o); - if (plat_entry) { - const NMPObject *plat_o; - - plat_o = plat_entry->obj; - - if (vt->route_cmp (NMP_OBJECT_CAST_IPX_ROUTE (conf_o), - NMP_OBJECT_CAST_IPX_ROUTE (plat_o), - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) == 0) - continue; - - /* we need to replace the existing route with a (slightly) different - * one. Delete it first. */ - if (!nm_platform_object_delete (self, plat_o)) { - /* ignore error. */ - } - } +nm_platform_ip_route_sync(NMPlatform *self, + int addr_family, + int ifindex, + GPtrArray * routes, + GPtrArray * routes_prune, + GPtrArray **out_temporary_not_available) +{ + const NMPlatformVTableRoute *vt; + gs_unref_hashtable GHashTable *routes_idx = NULL; + const NMPObject * conf_o; + const NMDedupMultiEntry * plat_entry; + guint i; + int i_type; + gboolean success = TRUE; + char sbuf1[sizeof(_nm_utils_to_string_buffer)]; + char sbuf2[sizeof(_nm_utils_to_string_buffer)]; + const gboolean IS_IPv4 = (addr_family == AF_INET); + + nm_assert(NM_IS_PLATFORM(self)); + nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + nm_assert(ifindex > 0); + + vt = &nm_platform_vtable_route.vx[IS_IPv4]; + + for (i_type = 0; routes && i_type < 2; i_type++) { + for (i = 0; i < routes->len; i++) { + int r, r2; + gboolean gateway_route_added = FALSE; + + conf_o = routes->pdata[i]; + +#define VTABLE_IS_DEVICE_ROUTE(vt, o) \ + (vt->is_ip4 ? (NMP_OBJECT_CAST_IP4_ROUTE(o)->gateway == 0) \ + : IN6_IS_ADDR_UNSPECIFIED(&NMP_OBJECT_CAST_IP6_ROUTE(o)->gateway)) + + if ((i_type == 0 && !VTABLE_IS_DEVICE_ROUTE(vt, conf_o)) + || (i_type == 1 && VTABLE_IS_DEVICE_ROUTE(vt, conf_o))) { + /* we add routes in two runs over @i_type. + * + * First device routes, then gateway routes. */ + continue; + } + + if (!routes_idx) { + routes_idx = g_hash_table_new((GHashFunc) nmp_object_id_hash, + (GEqualFunc) nmp_object_id_equal); + } + if (!g_hash_table_insert(routes_idx, (gpointer) conf_o, (gpointer) conf_o)) { + _LOG3D("route-sync: skip adding duplicate route %s", + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1))); + continue; + } + + if (!IS_IPv4 + && nm_platform_ip6_route_get_effective_metric(NMP_OBJECT_CAST_IP6_ROUTE(conf_o)) + == 0) { + /* User space cannot add routes with metric 0. However, kernel can, and we might track such + * routes in @route as they are present external. Skip them silently. */ + continue; + } + + plat_entry = nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, conf_o); + if (plat_entry) { + const NMPObject *plat_o; + + plat_o = plat_entry->obj; + + if (vt->route_cmp(NMP_OBJECT_CAST_IPX_ROUTE(conf_o), + NMP_OBJECT_CAST_IPX_ROUTE(plat_o), + NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + == 0) + continue; + + /* we need to replace the existing route with a (slightly) different + * one. Delete it first. */ + if (!nm_platform_object_delete(self, plat_o)) { + /* ignore error. */ + } + } sync_route_add: - r = nm_platform_ip_route_add (self, - NMP_NLM_FLAG_APPEND - | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, - conf_o); - if (r < 0) { - if (r == -EEXIST) { - /* Don't fail for EEXIST. It's not clear that the existing route - * is identical to the one that we were about to add. However, - * above we should have deleted conflicting (non-identical) routes. */ - if (_LOGD_ENABLED ()) { - plat_entry = nm_platform_lookup_entry (self, - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - conf_o); - if (!plat_entry) { - _LOG3D ("route-sync: adding route %s failed with EEXIST, however we cannot find such a route", - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1))); - } else if (vt->route_cmp (NMP_OBJECT_CAST_IPX_ROUTE (conf_o), - NMP_OBJECT_CAST_IPX_ROUTE (plat_entry->obj), - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) != 0) { - _LOG3D ("route-sync: adding route %s failed due to existing (different!) route %s", - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nmp_object_to_string (plat_entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf2, sizeof (sbuf2))); - } - } - } else if (NMP_OBJECT_CAST_IP_ROUTE (conf_o)->rt_source < NM_IP_CONFIG_SOURCE_USER) { - _LOG3D ("route-sync: ignore failure to add IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_strerror (r)); - } else if ( r == -EINVAL - && out_temporary_not_available - && _err_inval_due_to_ipv6_tentative_pref_src (self, conf_o)) { - _LOG3D ("route-sync: ignore failure to add IPv6 route with tentative IPv6 pref-src: %s: %s", - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_strerror (r)); - if (!*out_temporary_not_available) - *out_temporary_not_available = g_ptr_array_new_full (0, (GDestroyNotify) nmp_object_unref); - g_ptr_array_add (*out_temporary_not_available, (gpointer) nmp_object_ref (conf_o)); - } else if ( !gateway_route_added - && ( ( r == -ENETUNREACH - && vt->is_ip4 - && !!NMP_OBJECT_CAST_IP4_ROUTE (conf_o)->gateway) - || ( r == -EHOSTUNREACH - && !vt->is_ip4 - && !IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (conf_o)->gateway)))) { - NMPObject oo; - - if (vt->is_ip4) { - const NMPlatformIP4Route *rt = NMP_OBJECT_CAST_IP4_ROUTE (conf_o); - - nmp_object_stackinit (&oo, - NMP_OBJECT_TYPE_IP4_ROUTE, - &((NMPlatformIP4Route) { - .ifindex = rt->ifindex, - .network = rt->gateway, - .plen = 32, - .metric = rt->metric, - .rt_source = rt->rt_source, - .table_coerced = rt->table_coerced, - })); - } else { - const NMPlatformIP6Route *rt = NMP_OBJECT_CAST_IP6_ROUTE (conf_o); - - nmp_object_stackinit (&oo, - NMP_OBJECT_TYPE_IP6_ROUTE, - &((NMPlatformIP6Route) { - .ifindex = rt->ifindex, - .network = rt->gateway, - .plen = 128, - .metric = rt->metric, - .rt_source = rt->rt_source, - .table_coerced = rt->table_coerced, - })); - } - - _LOG3D ("route-sync: failure to add IPv%c route: %s: %s; try adding direct route to gateway %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_strerror (r), - nmp_object_to_string (&oo, NMP_OBJECT_TO_STRING_PUBLIC, sbuf2, sizeof (sbuf2))); - - r2 = nm_platform_ip_route_add (self, - NMP_NLM_FLAG_APPEND - | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, - &oo); - - if (r2 < 0) { - _LOG3D ("route-sync: failure to add gateway IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_strerror (r2)); - } - - gateway_route_added = TRUE; - goto sync_route_add; - } else { - _LOG3W ("route-sync: failure to add IPv%c route: %s: %s", - vt->is_ip4 ? '4' : '6', - nmp_object_to_string (conf_o, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof (sbuf1)), - nm_strerror (r)); - success = FALSE; - } - } - } - } - - if (routes_prune) { - for (i = 0; i < routes_prune->len; i++) { - const NMPObject *prune_o; - - prune_o = routes_prune->pdata[i]; - - nm_assert ( (addr_family == AF_INET && NMP_OBJECT_GET_TYPE (prune_o) == NMP_OBJECT_TYPE_IP4_ROUTE) - || (addr_family == AF_INET6 && NMP_OBJECT_GET_TYPE (prune_o) == NMP_OBJECT_TYPE_IP6_ROUTE)); - - if ( routes_idx - && g_hash_table_lookup (routes_idx, prune_o)) - continue; - - if (!nm_platform_lookup_entry (self, - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - prune_o)) - continue; - - if (!nm_platform_object_delete (self, prune_o)) { - /* ignore error... */ - } - } - } - - return success; + r = nm_platform_ip_route_add(self, + NMP_NLM_FLAG_APPEND + | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, + conf_o); + if (r < 0) { + if (r == -EEXIST) { + /* Don't fail for EEXIST. It's not clear that the existing route + * is identical to the one that we were about to add. However, + * above we should have deleted conflicting (non-identical) routes. */ + if (_LOGD_ENABLED()) { + plat_entry = + nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, conf_o); + if (!plat_entry) { + _LOG3D("route-sync: adding route %s failed with EEXIST, however we " + "cannot find such a route", + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1))); + } else if (vt->route_cmp(NMP_OBJECT_CAST_IPX_ROUTE(conf_o), + NMP_OBJECT_CAST_IPX_ROUTE(plat_entry->obj), + NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + != 0) { + _LOG3D("route-sync: adding route %s failed due to existing " + "(different!) route %s", + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1)), + nmp_object_to_string(plat_entry->obj, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf2, + sizeof(sbuf2))); + } + } + } else if (NMP_OBJECT_CAST_IP_ROUTE(conf_o)->rt_source < NM_IP_CONFIG_SOURCE_USER) { + _LOG3D("route-sync: ignore failure to add IPv%c route: %s: %s", + vt->is_ip4 ? '4' : '6', + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1)), + nm_strerror(r)); + } else if (r == -EINVAL && out_temporary_not_available + && _err_inval_due_to_ipv6_tentative_pref_src(self, conf_o)) { + _LOG3D("route-sync: ignore failure to add IPv6 route with tentative IPv6 " + "pref-src: %s: %s", + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1)), + nm_strerror(r)); + if (!*out_temporary_not_available) + *out_temporary_not_available = + g_ptr_array_new_full(0, (GDestroyNotify) nmp_object_unref); + g_ptr_array_add(*out_temporary_not_available, + (gpointer) nmp_object_ref(conf_o)); + } else if (!gateway_route_added + && ((r == -ENETUNREACH && vt->is_ip4 + && !!NMP_OBJECT_CAST_IP4_ROUTE(conf_o)->gateway) + || (r == -EHOSTUNREACH && !vt->is_ip4 + && !IN6_IS_ADDR_UNSPECIFIED( + &NMP_OBJECT_CAST_IP6_ROUTE(conf_o)->gateway)))) { + NMPObject oo; + + if (vt->is_ip4) { + const NMPlatformIP4Route *rt = NMP_OBJECT_CAST_IP4_ROUTE(conf_o); + + nmp_object_stackinit( + &oo, + NMP_OBJECT_TYPE_IP4_ROUTE, + &((NMPlatformIP4Route){ + .ifindex = rt->ifindex, + .network = rt->gateway, + .plen = 32, + .metric = nm_platform_ip4_route_get_effective_metric(rt), + .rt_source = rt->rt_source, + .table_coerced = nm_platform_ip_route_get_effective_table( + NM_PLATFORM_IP_ROUTE_CAST(rt)), + })); + } else { + const NMPlatformIP6Route *rt = NMP_OBJECT_CAST_IP6_ROUTE(conf_o); + + nmp_object_stackinit( + &oo, + NMP_OBJECT_TYPE_IP6_ROUTE, + &((NMPlatformIP6Route){ + .ifindex = rt->ifindex, + .network = rt->gateway, + .plen = 128, + .metric = nm_platform_ip6_route_get_effective_metric(rt), + .rt_source = rt->rt_source, + .table_coerced = nm_platform_ip_route_get_effective_table( + NM_PLATFORM_IP_ROUTE_CAST(rt)), + })); + } + + _LOG3D("route-sync: failure to add IPv%c route: %s: %s; try adding direct " + "route to gateway %s", + vt->is_ip4 ? '4' : '6', + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1)), + nm_strerror(r), + nmp_object_to_string(&oo, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf2, + sizeof(sbuf2))); + + r2 = nm_platform_ip_route_add(self, + NMP_NLM_FLAG_APPEND + | NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE, + &oo); + + if (r2 < 0) { + _LOG3D("route-sync: failure to add gateway IPv%c route: %s: %s", + vt->is_ip4 ? '4' : '6', + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1)), + nm_strerror(r2)); + } + + gateway_route_added = TRUE; + goto sync_route_add; + } else { + _LOG3W("route-sync: failure to add IPv%c route: %s: %s", + vt->is_ip4 ? '4' : '6', + nmp_object_to_string(conf_o, + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf1, + sizeof(sbuf1)), + nm_strerror(r)); + success = FALSE; + } + } + } + } + + if (routes_prune) { + for (i = 0; i < routes_prune->len; i++) { + const NMPObject *prune_o; + + prune_o = routes_prune->pdata[i]; + + nm_assert((addr_family == AF_INET + && NMP_OBJECT_GET_TYPE(prune_o) == NMP_OBJECT_TYPE_IP4_ROUTE) + || (addr_family == AF_INET6 + && NMP_OBJECT_GET_TYPE(prune_o) == NMP_OBJECT_TYPE_IP6_ROUTE)); + + if (routes_idx && g_hash_table_lookup(routes_idx, prune_o)) + continue; + + if (!nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, prune_o)) + continue; + + if (!nm_platform_object_delete(self, prune_o)) { + /* ignore error... */ + } + } + } + + return success; } gboolean -nm_platform_ip_route_flush (NMPlatform *self, - int addr_family, - int ifindex) +nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex) { - gboolean success = TRUE; + gboolean success = TRUE; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, - AF_INET, - AF_INET6)); + nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) { - gs_unref_ptrarray GPtrArray *routes_prune = NULL; + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) { + gs_unref_ptrarray GPtrArray *routes_prune = NULL; - routes_prune = nm_platform_ip_route_get_prune_list (self, - AF_INET, - ifindex, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); - success &= nm_platform_ip_route_sync (self, AF_INET, ifindex, NULL, routes_prune, NULL); - } - if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) { - gs_unref_ptrarray GPtrArray *routes_prune = NULL; + routes_prune = nm_platform_ip_route_get_prune_list(self, + AF_INET, + ifindex, + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); + success &= nm_platform_ip_route_sync(self, AF_INET, ifindex, NULL, routes_prune, NULL); + } + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) { + gs_unref_ptrarray GPtrArray *routes_prune = NULL; - routes_prune = nm_platform_ip_route_get_prune_list (self, - AF_INET6, - ifindex, - NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); - success &= nm_platform_ip_route_sync (self, AF_INET6, ifindex, NULL, routes_prune, NULL); - } - return success; + routes_prune = nm_platform_ip_route_get_prune_list(self, + AF_INET6, + ifindex, + NM_IP_ROUTE_TABLE_SYNC_MODE_ALL); + success &= nm_platform_ip_route_sync(self, AF_INET6, ifindex, NULL, routes_prune, NULL); + } + return success; } /*****************************************************************************/ static guint8 -_ip_route_scope_inv_get_normalized (const NMPlatformIP4Route *route) -{ - /* in kernel, you cannot set scope to RT_SCOPE_NOWHERE (255). - * That means, in NM, we treat RT_SCOPE_NOWHERE as unset, and detect - * it based on the presence of the gateway. In other words, when adding - * a route with scope RT_SCOPE_NOWHERE (in NetworkManager) to kernel, - * the resulting scope will be either "link" or "universe" (depending - * on the gateway). - * - * Note that internally, we track @scope_inv is the inverse of scope, - * so that the default equals zero (~(RT_SCOPE_NOWHERE)). - **/ - if (route->scope_inv == 0) { - if (route->type_coerced == nm_platform_route_type_coerce (RTN_LOCAL)) - return nm_platform_route_scope_inv (RT_SCOPE_HOST); - else { - return nm_platform_route_scope_inv (!route->gateway - ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); - } - } - return route->scope_inv; +_ip_route_scope_inv_get_normalized(const NMPlatformIP4Route *route) +{ + /* in kernel, you cannot set scope to RT_SCOPE_NOWHERE (255). + * That means, in NM, we treat RT_SCOPE_NOWHERE as unset, and detect + * it based on the presence of the gateway. In other words, when adding + * a route with scope RT_SCOPE_NOWHERE (in NetworkManager) to kernel, + * the resulting scope will be either "link" or "universe" (depending + * on the gateway). + * + * Note that internally, we track @scope_inv is the inverse of scope, + * so that the default equals zero (~(RT_SCOPE_NOWHERE)). + **/ + if (route->scope_inv == 0) { + if (route->type_coerced == nm_platform_route_type_coerce(RTN_LOCAL)) + return nm_platform_route_scope_inv(RT_SCOPE_HOST); + else { + return nm_platform_route_scope_inv(!route->gateway ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); + } + } + return route->scope_inv; } static guint8 -_route_pref_normalize (guint8 pref) +_route_pref_normalize(guint8 pref) { - /* for kernel (and ICMPv6) pref can only have one of 3 values. Normalize. */ - return NM_IN_SET (pref, NM_ICMPV6_ROUTER_PREF_LOW, - NM_ICMPV6_ROUTER_PREF_HIGH) - ? pref - : NM_ICMPV6_ROUTER_PREF_MEDIUM; + /* for kernel (and ICMPv6) pref can only have one of 3 values. Normalize. */ + return NM_IN_SET(pref, NM_ICMPV6_ROUTER_PREF_LOW, NM_ICMPV6_ROUTER_PREF_HIGH) + ? pref + : NM_ICMPV6_ROUTER_PREF_MEDIUM; } /** @@ -4559,340 +4763,328 @@ _route_pref_normalize (guint8 pref) * compare equal with NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL. */ void -nm_platform_ip_route_normalize (int addr_family, - NMPlatformIPRoute *route) -{ - NMPlatformIP4Route *r4; - NMPlatformIP6Route *r6; - - switch (addr_family) { - case AF_INET: - r4 = (NMPlatformIP4Route *) route; - r4->table_coerced = nm_platform_route_table_coerce (nm_platform_route_table_uncoerce (r4->table_coerced, TRUE)); - r4->network = nm_utils_ip4_address_clear_host_address (r4->network, r4->plen); - r4->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r4->rt_source); - r4->scope_inv = _ip_route_scope_inv_get_normalized (r4); - break; - case AF_INET6: - r6 = (NMPlatformIP6Route *) route; - r6->table_coerced = nm_platform_route_table_coerce (nm_platform_route_table_uncoerce (r6->table_coerced, TRUE)); - nm_utils_ip6_address_clear_host_address (&r6->network, &r6->network, r6->plen); - r6->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r6->rt_source), - nm_utils_ip6_address_clear_host_address (&r6->src, &r6->src, r6->src_plen); - break; - default: - nm_assert_not_reached (); - break; - } +nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route) +{ + NMPlatformIP4Route *r4; + NMPlatformIP6Route *r6; + + route->table_coerced = + nm_platform_route_table_coerce(nm_platform_ip_route_get_effective_table(route)); + route->table_any = FALSE; + + route->rt_source = nmp_utils_ip_config_source_round_trip_rtprot(route->rt_source); + + switch (addr_family) { + case AF_INET: + r4 = (NMPlatformIP4Route *) route; + route->metric = nm_platform_ip4_route_get_effective_metric(r4); + route->metric_any = FALSE; + r4->network = nm_utils_ip4_address_clear_host_address(r4->network, r4->plen); + r4->scope_inv = _ip_route_scope_inv_get_normalized(r4); + break; + case AF_INET6: + r6 = (NMPlatformIP6Route *) route; + route->metric = nm_platform_ip6_route_get_effective_metric(r6); + route->metric_any = FALSE; + nm_utils_ip6_address_clear_host_address(&r6->network, &r6->network, r6->plen); + nm_utils_ip6_address_clear_host_address(&r6->src, &r6->src, r6->src_plen); + break; + default: + nm_assert_not_reached(); + break; + } } static int -_ip_route_add (NMPlatform *self, - NMPNlmFlags flags, - int addr_family, - gconstpointer route) +_ip_route_add(NMPlatform *self, NMPNlmFlags flags, int addr_family, gconstpointer route) { - char sbuf[sizeof (_nm_utils_to_string_buffer)]; - int ifindex; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + int ifindex; - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF(self, klass, FALSE); - nm_assert (route); - nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); + nm_assert(route); + nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - ifindex = ((const NMPlatformIPRoute *) route)->ifindex; - _LOG3D ("route: %-10s IPv%c route: %s", - _nmp_nlm_flag_to_string (flags & NMP_NLM_FLAG_FMASK), - nm_utils_addr_family_to_char (addr_family), - addr_family == AF_INET - ? nm_platform_ip4_route_to_string (route, sbuf, sizeof (sbuf)) - : nm_platform_ip6_route_to_string (route, sbuf, sizeof (sbuf))); + ifindex = ((const NMPlatformIPRoute *) route)->ifindex; + _LOG3D("route: %-10s IPv%c route: %s", + _nmp_nlm_flag_to_string(flags & NMP_NLM_FLAG_FMASK), + nm_utils_addr_family_to_char(addr_family), + addr_family == AF_INET ? nm_platform_ip4_route_to_string(route, sbuf, sizeof(sbuf)) + : nm_platform_ip6_route_to_string(route, sbuf, sizeof(sbuf))); - return klass->ip_route_add (self, flags, addr_family, route); + return klass->ip_route_add(self, flags, addr_family, route); } int -nm_platform_ip_route_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPObject *route) +nm_platform_ip_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPObject *route) { - int addr_family; + int addr_family; - switch (NMP_OBJECT_GET_TYPE (route)) { - case NMP_OBJECT_TYPE_IP4_ROUTE: - addr_family = AF_INET; - break; - case NMP_OBJECT_TYPE_IP6_ROUTE: - addr_family = AF_INET6; - break; - default: - g_return_val_if_reached (FALSE); - } + switch (NMP_OBJECT_GET_TYPE(route)) { + case NMP_OBJECT_TYPE_IP4_ROUTE: + addr_family = AF_INET; + break; + case NMP_OBJECT_TYPE_IP6_ROUTE: + addr_family = AF_INET6; + break; + default: + g_return_val_if_reached(FALSE); + } - return _ip_route_add (self, flags, addr_family, NMP_OBJECT_CAST_IP_ROUTE (route)); + return _ip_route_add(self, flags, addr_family, NMP_OBJECT_CAST_IP_ROUTE(route)); } int -nm_platform_ip4_route_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformIP4Route *route) +nm_platform_ip4_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route) { - return _ip_route_add (self, flags, AF_INET, route); + return _ip_route_add(self, flags, AF_INET, route); } int -nm_platform_ip6_route_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformIP6Route *route) +nm_platform_ip6_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *route) { - return _ip_route_add (self, flags, AF_INET6, route); + return _ip_route_add(self, flags, AF_INET6, route); } gboolean -nm_platform_object_delete (NMPlatform *self, - const NMPObject *obj) -{ - int ifindex; - - _CHECK_SELF (self, klass, FALSE); - - switch (NMP_OBJECT_GET_TYPE (obj)) { - case NMP_OBJECT_TYPE_ROUTING_RULE: - _LOGD ("%s: delete %s", - NMP_OBJECT_GET_CLASS (obj)->obj_type_name, - nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - break; - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - case NMP_OBJECT_TYPE_QDISC: - case NMP_OBJECT_TYPE_TFILTER: - ifindex = NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (obj)->ifindex; - _LOG3D ("%s: delete %s", - NMP_OBJECT_GET_CLASS (obj)->obj_type_name, - nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - break; - default: - g_return_val_if_reached (FALSE); - } - - return klass->object_delete (self, obj); +nm_platform_object_delete(NMPlatform *self, const NMPObject *obj) +{ + int ifindex; + + _CHECK_SELF(self, klass, FALSE); + + switch (NMP_OBJECT_GET_TYPE(obj)) { + case NMP_OBJECT_TYPE_ROUTING_RULE: + _LOGD("%s: delete %s", + NMP_OBJECT_GET_CLASS(obj)->obj_type_name, + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + break; + case NMP_OBJECT_TYPE_IP4_ROUTE: + case NMP_OBJECT_TYPE_IP6_ROUTE: + case NMP_OBJECT_TYPE_QDISC: + case NMP_OBJECT_TYPE_TFILTER: + ifindex = NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj)->ifindex; + _LOG3D("%s: delete %s", + NMP_OBJECT_GET_CLASS(obj)->obj_type_name, + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + break; + default: + g_return_val_if_reached(FALSE); + } + + return klass->object_delete(self, obj); } /*****************************************************************************/ int -nm_platform_ip_route_get (NMPlatform *self, - int addr_family, - gconstpointer address /* in_addr_t or struct in6_addr */, - int oif_ifindex, - NMPObject **out_route) -{ - nm_auto_nmpobj NMPObject *route = NULL; - int result; - char buf[NM_UTILS_INET_ADDRSTRLEN]; - char buf_oif[64]; - - _CHECK_SELF (self, klass, FALSE); - - g_return_val_if_fail (address, -NME_BUG); - g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, - AF_INET6), -NME_BUG); - - _LOGT ("route: get IPv%c route for: %s%s", - nm_utils_addr_family_to_char (addr_family), - inet_ntop (addr_family, address, buf, sizeof (buf)), - oif_ifindex > 0 ? nm_sprintf_buf (buf_oif, " oif %d", oif_ifindex) : ""); - - if (!klass->ip_route_get) - result = -NME_PL_OPNOTSUPP; - else { - result = klass->ip_route_get (self, - addr_family, - address, - oif_ifindex, - &route); - } - - if (result < 0) { - nm_assert (!route); - _LOGW ("route: get IPv%c route for: %s failed with %s", - nm_utils_addr_family_to_char (addr_family), - inet_ntop (addr_family, address, buf, sizeof (buf)), - nm_strerror (result)); - } else { - nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (route), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - nm_assert (!NMP_OBJECT_IS_STACKINIT (route)); - nm_assert (route->parent._ref_count == 1); - _LOGD ("route: get IPv%c route for: %s succeeded: %s", - nm_utils_addr_family_to_char (addr_family), - inet_ntop (addr_family, address, buf, sizeof (buf)), - nmp_object_to_string (route, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - NM_SET_OUT (out_route, g_steal_pointer (&route)); - } - return result; +nm_platform_ip_route_get(NMPlatform * self, + int addr_family, + gconstpointer address /* in_addr_t or struct in6_addr */, + int oif_ifindex, + NMPObject ** out_route) +{ + nm_auto_nmpobj NMPObject *route = NULL; + int result; + char buf[NM_UTILS_INET_ADDRSTRLEN]; + char buf_oif[64]; + + _CHECK_SELF(self, klass, FALSE); + + g_return_val_if_fail(address, -NME_BUG); + g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), -NME_BUG); + + _LOGT("route: get IPv%c route for: %s%s", + nm_utils_addr_family_to_char(addr_family), + inet_ntop(addr_family, address, buf, sizeof(buf)), + oif_ifindex > 0 ? nm_sprintf_buf(buf_oif, " oif %d", oif_ifindex) : ""); + + if (!klass->ip_route_get) + result = -NME_PL_OPNOTSUPP; + else { + result = klass->ip_route_get(self, addr_family, address, oif_ifindex, &route); + } + + if (result < 0) { + nm_assert(!route); + _LOGW("route: get IPv%c route for: %s failed with %s", + nm_utils_addr_family_to_char(addr_family), + inet_ntop(addr_family, address, buf, sizeof(buf)), + nm_strerror(result)); + } else { + nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(route), + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE)); + nm_assert(!NMP_OBJECT_IS_STACKINIT(route)); + nm_assert(route->parent._ref_count == 1); + _LOGD("route: get IPv%c route for: %s succeeded: %s", + nm_utils_addr_family_to_char(addr_family), + inet_ntop(addr_family, address, buf, sizeof(buf)), + nmp_object_to_string(route, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + NM_SET_OUT(out_route, g_steal_pointer(&route)); + } + return result; } /*****************************************************************************/ -#define IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS ((int) 1500) -#define IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S ((int) (((IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS + 999) * 3) / 1000)) +#define IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS ((int) 1500) +#define IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S \ + ((int) (((IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS + 999) * 3) / 1000)) static gint64 -_ip4_dev_route_blacklist_timeout_ms_get (gint64 timeout_msec) +_ip4_dev_route_blacklist_timeout_ms_get(gint64 timeout_msec) { - return timeout_msec >> 1; + return timeout_msec >> 1; } static gint64 -_ip4_dev_route_blacklist_timeout_ms_marked (gint64 timeout_msec) +_ip4_dev_route_blacklist_timeout_ms_marked(gint64 timeout_msec) { - return !!(timeout_msec & ((gint64) 1)); + return !!(timeout_msec & ((gint64) 1)); } static gboolean -_ip4_dev_route_blacklist_check_cb (gpointer user_data) +_ip4_dev_route_blacklist_check_cb(gpointer user_data) { - NMPlatform *self = user_data; - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self); - GHashTableIter iter; - const NMPObject *p_obj; - gint64 *p_timeout_ms; - gint64 now_ms; + NMPlatform * self = user_data; + NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); + GHashTableIter iter; + const NMPObject * p_obj; + gint64 * p_timeout_ms; + gint64 now_ms; - priv->ip4_dev_route_blacklist_check_id = 0; + priv->ip4_dev_route_blacklist_check_id = 0; again: - if (!priv->ip4_dev_route_blacklist_hash) - goto out; + if (!priv->ip4_dev_route_blacklist_hash) + goto out; - now_ms = nm_utils_get_monotonic_timestamp_msec (); + now_ms = nm_utils_get_monotonic_timestamp_msec(); - g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash); - while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { - if (!_ip4_dev_route_blacklist_timeout_ms_marked (*p_timeout_ms)) - continue; + g_hash_table_iter_init(&iter, priv->ip4_dev_route_blacklist_hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { + if (!_ip4_dev_route_blacklist_timeout_ms_marked(*p_timeout_ms)) + continue; - /* unmark because we checked it. */ - *p_timeout_ms = *p_timeout_ms & ~((gint64) 1); + /* unmark because we checked it. */ + *p_timeout_ms = *p_timeout_ms & ~((gint64) 1); - if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get (*p_timeout_ms)) - continue; + if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get(*p_timeout_ms)) + continue; - if (!nm_platform_lookup_entry (self, - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - p_obj)) - continue; + if (!nm_platform_lookup_entry(self, NMP_CACHE_ID_TYPE_OBJECT_TYPE, p_obj)) + continue; - _LOGT ("ip4-dev-route: delete %s", - nmp_object_to_string (p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - nm_platform_object_delete (self, p_obj); - goto again; - } + _LOGT("ip4-dev-route: delete %s", + nmp_object_to_string(p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + nm_platform_object_delete(self, p_obj); + goto again; + } out: - return G_SOURCE_REMOVE; + return G_SOURCE_REMOVE; } static void -_ip4_dev_route_blacklist_check_schedule (NMPlatform *self) +_ip4_dev_route_blacklist_check_schedule(NMPlatform *self) { - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self); + NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - if (!priv->ip4_dev_route_blacklist_check_id) { - priv->ip4_dev_route_blacklist_check_id = g_idle_add_full (G_PRIORITY_HIGH, - _ip4_dev_route_blacklist_check_cb, - self, - NULL); - } + if (!priv->ip4_dev_route_blacklist_check_id) { + priv->ip4_dev_route_blacklist_check_id = + g_idle_add_full(G_PRIORITY_HIGH, _ip4_dev_route_blacklist_check_cb, self, NULL); + } } static void -_ip4_dev_route_blacklist_notify_route (NMPlatform *self, - const NMPObject *obj) +_ip4_dev_route_blacklist_notify_route(NMPlatform *self, const NMPObject *obj) { - NMPlatformPrivate *priv; - const NMPObject *p_obj; - gint64 *p_timeout_ms; - gint64 now_ms; + NMPlatformPrivate *priv; + const NMPObject * p_obj; + gint64 * p_timeout_ms; + gint64 now_ms; - nm_assert (NM_IS_PLATFORM (self)); - nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP4_ROUTE); + nm_assert(NM_IS_PLATFORM(self)); + nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP4_ROUTE); - priv = NM_PLATFORM_GET_PRIVATE (self); + priv = NM_PLATFORM_GET_PRIVATE(self); - nm_assert (priv->ip4_dev_route_blacklist_gc_timeout_id); + nm_assert(priv->ip4_dev_route_blacklist_gc_timeout_id); - if (!g_hash_table_lookup_extended (priv->ip4_dev_route_blacklist_hash, - obj, - (gpointer *) &p_obj, - (gpointer *) &p_timeout_ms)) - return; + if (!g_hash_table_lookup_extended(priv->ip4_dev_route_blacklist_hash, + obj, + (gpointer *) &p_obj, + (gpointer *) &p_timeout_ms)) + return; - now_ms = nm_utils_get_monotonic_timestamp_msec (); - if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get (*p_timeout_ms)) { - /* already expired. Wait for gc. */ - return; - } + now_ms = nm_utils_get_monotonic_timestamp_msec(); + if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get(*p_timeout_ms)) { + /* already expired. Wait for gc. */ + return; + } - if (_ip4_dev_route_blacklist_timeout_ms_marked (*p_timeout_ms)) { - nm_assert (priv->ip4_dev_route_blacklist_check_id); - return; - } + if (_ip4_dev_route_blacklist_timeout_ms_marked(*p_timeout_ms)) { + nm_assert(priv->ip4_dev_route_blacklist_check_id); + return; + } - /* We cannot delete it right away because we are in the process of receiving netlink messages. - * It may be possible to do so, but complicated and error prone. - * - * Instead, we mark the entry and schedule an idle action (with high priority). */ - *p_timeout_ms = (*p_timeout_ms) | ((gint64) 1); - _ip4_dev_route_blacklist_check_schedule (self); + /* We cannot delete it right away because we are in the process of receiving netlink messages. + * It may be possible to do so, but complicated and error prone. + * + * Instead, we mark the entry and schedule an idle action (with high priority). */ + *p_timeout_ms = (*p_timeout_ms) | ((gint64) 1); + _ip4_dev_route_blacklist_check_schedule(self); } static gboolean -_ip4_dev_route_blacklist_gc_timeout_handle (gpointer user_data) +_ip4_dev_route_blacklist_gc_timeout_handle(gpointer user_data) { - NMPlatform *self = user_data; - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self); - GHashTableIter iter; - const NMPObject *p_obj; - gint64 *p_timeout_ms; - gint64 now_ms; + NMPlatform * self = user_data; + NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); + GHashTableIter iter; + const NMPObject * p_obj; + gint64 * p_timeout_ms; + gint64 now_ms; - nm_assert (priv->ip4_dev_route_blacklist_gc_timeout_id); + nm_assert(priv->ip4_dev_route_blacklist_gc_timeout_id); - now_ms = nm_utils_get_monotonic_timestamp_msec (); + now_ms = nm_utils_get_monotonic_timestamp_msec(); - g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash); - while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { - if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get (*p_timeout_ms)) { - _LOGT ("ip4-dev-route: cleanup %s", - nmp_object_to_string (p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - g_hash_table_iter_remove (&iter); - } - } + g_hash_table_iter_init(&iter, priv->ip4_dev_route_blacklist_hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { + if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get(*p_timeout_ms)) { + _LOGT("ip4-dev-route: cleanup %s", + nmp_object_to_string(p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + g_hash_table_iter_remove(&iter); + } + } - _ip4_dev_route_blacklist_schedule (self); - return G_SOURCE_CONTINUE; + _ip4_dev_route_blacklist_schedule(self); + return G_SOURCE_CONTINUE; } static void -_ip4_dev_route_blacklist_schedule (NMPlatform *self) -{ - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self); - - if ( !priv->ip4_dev_route_blacklist_hash - || g_hash_table_size (priv->ip4_dev_route_blacklist_hash) == 0) { - nm_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); - nm_clear_g_source (&priv->ip4_dev_route_blacklist_gc_timeout_id); - } else { - if (!priv->ip4_dev_route_blacklist_gc_timeout_id) { - /* this timeout is only to garbage collect the expired entries from priv->ip4_dev_route_blacklist_hash. - * It can run infrequently, and it doesn't hurt if expired entries linger around a bit - * longer then necessary. */ - priv->ip4_dev_route_blacklist_gc_timeout_id = g_timeout_add_seconds (IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S, - _ip4_dev_route_blacklist_gc_timeout_handle, - self); - } - } +_ip4_dev_route_blacklist_schedule(NMPlatform *self) +{ + NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); + + if (!priv->ip4_dev_route_blacklist_hash + || g_hash_table_size(priv->ip4_dev_route_blacklist_hash) == 0) { + nm_clear_pointer(&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); + nm_clear_g_source(&priv->ip4_dev_route_blacklist_gc_timeout_id); + } else { + if (!priv->ip4_dev_route_blacklist_gc_timeout_id) { + /* this timeout is only to garbage collect the expired entries from priv->ip4_dev_route_blacklist_hash. + * It can run infrequently, and it doesn't hurt if expired entries linger around a bit + * longer then necessary. */ + priv->ip4_dev_route_blacklist_gc_timeout_id = + g_timeout_add_seconds(IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S, + _ip4_dev_route_blacklist_gc_timeout_handle, + self); + } + } } /** @@ -4920,116 +5112,116 @@ _ip4_dev_route_blacklist_schedule (NMPlatform *self) * routes as well. */ void -nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, - int ifindex, - GPtrArray *ip4_dev_route_blacklist) -{ - NMPlatformPrivate *priv; - GHashTableIter iter; - const NMPObject *p_obj; - guint i; - gint64 timeout_msec; - gint64 timeout_msec_val; - gint64 *p_timeout_ms; - gboolean needs_check = FALSE; - - nm_assert (NM_IS_PLATFORM (self)); - nm_assert (ifindex > 0); - - priv = NM_PLATFORM_GET_PRIVATE (self); - - /* first, expire all for current ifindex... */ - if (priv->ip4_dev_route_blacklist_hash) { - g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash); - while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { - if (NMP_OBJECT_CAST_IP4_ROUTE (p_obj)->ifindex == ifindex) { - /* we could g_hash_table_iter_remove(&iter) the current entry. - * Instead, just expire it and let _ip4_dev_route_blacklist_gc_timeout_handle() - * handle it. - * - * The assumption is, that ip4_dev_route_blacklist contains the very same entry - * again, with a new timeout. So, we can un-expire it below. */ - *p_timeout_ms = 0; - } - } - } - - if ( ip4_dev_route_blacklist - && ip4_dev_route_blacklist->len > 0) { - - if (!priv->ip4_dev_route_blacklist_hash) { - priv->ip4_dev_route_blacklist_hash = g_hash_table_new_full ((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal, - (GDestroyNotify) nmp_object_unref, - nm_g_slice_free_fcn_gint64); - } - - timeout_msec = nm_utils_get_monotonic_timestamp_msec () + IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS; - timeout_msec_val = (timeout_msec << 1) | ((gint64) 1); - for (i = 0; i < ip4_dev_route_blacklist->len; i++) { - const NMPObject *o; - - needs_check = TRUE; - o = ip4_dev_route_blacklist->pdata[i]; - if (g_hash_table_lookup_extended (priv->ip4_dev_route_blacklist_hash, - o, - (gpointer *) &p_obj, - (gpointer *) &p_timeout_ms)) { - if (nmp_object_equal (p_obj, o)) { - /* un-expire and reuse the entry. */ - _LOGT ("ip4-dev-route: register %s (update)", - nmp_object_to_string (p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - *p_timeout_ms = timeout_msec_val; - continue; - } - } - - _LOGT ("ip4-dev-route: register %s", - nmp_object_to_string (o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - p_timeout_ms = g_slice_new (gint64); - *p_timeout_ms = timeout_msec_val; - g_hash_table_replace (priv->ip4_dev_route_blacklist_hash, - (gpointer) nmp_object_ref (o), - p_timeout_ms); - } - } - - _ip4_dev_route_blacklist_schedule (self); - - if (needs_check) - _ip4_dev_route_blacklist_check_schedule (self); +nm_platform_ip4_dev_route_blacklist_set(NMPlatform *self, + int ifindex, + GPtrArray * ip4_dev_route_blacklist) +{ + NMPlatformPrivate *priv; + GHashTableIter iter; + const NMPObject * p_obj; + guint i; + gint64 timeout_msec; + gint64 timeout_msec_val; + gint64 * p_timeout_ms; + gboolean needs_check = FALSE; + + nm_assert(NM_IS_PLATFORM(self)); + nm_assert(ifindex > 0); + + /* TODO: the blacklist should be maintained by NML3Cfg. */ + + priv = NM_PLATFORM_GET_PRIVATE(self); + + /* first, expire all for current ifindex... */ + if (priv->ip4_dev_route_blacklist_hash) { + g_hash_table_iter_init(&iter, priv->ip4_dev_route_blacklist_hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) { + if (NMP_OBJECT_CAST_IP4_ROUTE(p_obj)->ifindex == ifindex) { + /* we could g_hash_table_iter_remove(&iter) the current entry. + * Instead, just expire it and let _ip4_dev_route_blacklist_gc_timeout_handle() + * handle it. + * + * The assumption is, that ip4_dev_route_blacklist contains the very same entry + * again, with a new timeout. So, we can un-expire it below. */ + *p_timeout_ms = 0; + } + } + } + + if (ip4_dev_route_blacklist && ip4_dev_route_blacklist->len > 0) { + if (!priv->ip4_dev_route_blacklist_hash) { + priv->ip4_dev_route_blacklist_hash = + g_hash_table_new_full((GHashFunc) nmp_object_id_hash, + (GEqualFunc) nmp_object_id_equal, + (GDestroyNotify) nmp_object_unref, + nm_g_slice_free_fcn_gint64); + } + + timeout_msec = nm_utils_get_monotonic_timestamp_msec() + IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS; + timeout_msec_val = (timeout_msec << 1) | ((gint64) 1); + for (i = 0; i < ip4_dev_route_blacklist->len; i++) { + const NMPObject *o; + + needs_check = TRUE; + o = ip4_dev_route_blacklist->pdata[i]; + if (g_hash_table_lookup_extended(priv->ip4_dev_route_blacklist_hash, + o, + (gpointer *) &p_obj, + (gpointer *) &p_timeout_ms)) { + if (nmp_object_equal(p_obj, o)) { + /* un-expire and reuse the entry. */ + _LOGT("ip4-dev-route: register %s (update)", + nmp_object_to_string(p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + *p_timeout_ms = timeout_msec_val; + continue; + } + } + + _LOGT("ip4-dev-route: register %s", + nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + p_timeout_ms = g_slice_new(gint64); + *p_timeout_ms = timeout_msec_val; + g_hash_table_replace(priv->ip4_dev_route_blacklist_hash, + (gpointer) nmp_object_ref(o), + p_timeout_ms); + } + } + + _ip4_dev_route_blacklist_schedule(self); + + if (needs_check) + _ip4_dev_route_blacklist_check_schedule(self); } /*****************************************************************************/ int -nm_platform_routing_rule_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformRoutingRule *routing_rule) +nm_platform_routing_rule_add(NMPlatform * self, + NMPNlmFlags flags, + const NMPlatformRoutingRule *routing_rule) { - _CHECK_SELF (self, klass, -NME_BUG); + _CHECK_SELF(self, klass, -NME_BUG); - g_return_val_if_fail (routing_rule, -NME_BUG); + g_return_val_if_fail(routing_rule, -NME_BUG); - _LOGD ("routing-rule: adding or updating: %s", nm_platform_routing_rule_to_string (routing_rule, NULL, 0)); - return klass->routing_rule_add (self, flags, routing_rule); + _LOGD("routing-rule: adding or updating: %s", + nm_platform_routing_rule_to_string(routing_rule, NULL, 0)); + return klass->routing_rule_add(self, flags, routing_rule); } /*****************************************************************************/ int -nm_platform_qdisc_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformQdisc *qdisc) +nm_platform_qdisc_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformQdisc *qdisc) { - int ifindex = qdisc->ifindex; - _CHECK_SELF (self, klass, -NME_BUG); + int ifindex = qdisc->ifindex; + _CHECK_SELF(self, klass, -NME_BUG); - /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind - * is undefined. */ + /* Note: @qdisc must not be copied or kept alive because the lifetime of qdisc.kind + * is undefined. */ - _LOG3D ("adding or updating a qdisc: %s", nm_platform_qdisc_to_string (qdisc, NULL, 0)); - return klass->qdisc_add (self, flags, qdisc); + _LOG3D("adding or updating a qdisc: %s", nm_platform_qdisc_to_string(qdisc, NULL, 0)); + return klass->qdisc_add(self, flags, qdisc); } /** @@ -5047,98 +5239,92 @@ nm_platform_qdisc_add (NMPlatform *self, * Returns: %TRUE on success. */ gboolean -nm_platform_qdisc_sync (NMPlatform *self, - int ifindex, - GPtrArray *known_qdiscs) -{ - gs_unref_ptrarray GPtrArray *plat_qdiscs = NULL; - NMPLookup lookup; - guint i; - gboolean success = TRUE; - gs_unref_hashtable GHashTable *known_qdiscs_idx = NULL; - - nm_assert (NM_IS_PLATFORM (self)); - nm_assert (ifindex > 0); - - known_qdiscs_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal); - if (known_qdiscs) { - for (i = 0; i < known_qdiscs->len; i++) { - const NMPObject *q = g_ptr_array_index (known_qdiscs, i); - - if (!g_hash_table_insert (known_qdiscs_idx, (gpointer) q, (gpointer) q)) { - _LOGW ("duplicate qdisc %s", nm_platform_qdisc_to_string (&q->qdisc, NULL, 0)); - return FALSE; - } - - } - } - - plat_qdiscs = nm_platform_lookup_clone (self, - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_QDISC, - ifindex), - NULL, NULL); - if (plat_qdiscs) { - for (i = 0; i < plat_qdiscs->len; i++) { - const NMPObject *p = g_ptr_array_index (plat_qdiscs, i); - const NMPObject *k; - - /* look up known qdisc with same parent */ - k = g_hash_table_lookup (known_qdiscs_idx, p); - - if (k) { - const NMPlatformQdisc *qdisc_k = NMP_OBJECT_CAST_QDISC (k); - const NMPlatformQdisc *qdisc_p = NMP_OBJECT_CAST_QDISC (p); - - /* check other fields */ - if ( nm_platform_qdisc_cmp_full (qdisc_k, qdisc_p, FALSE) != 0 - || ( qdisc_k->handle != qdisc_p->handle - && qdisc_k != 0)) { - k = NULL; - } - } - - if (k) { - g_hash_table_remove (known_qdiscs_idx, k); - } else { - /* can't delete qdisc with zero handle */ - if (TC_H_MAJ (p->qdisc.handle) != 0) { - success &= nm_platform_object_delete (self, p); - } - } - } - } - - if (known_qdiscs) { - for (i = 0; i < known_qdiscs->len; i++) { - const NMPObject *q = g_ptr_array_index (known_qdiscs, i); - - if (g_hash_table_contains (known_qdiscs_idx, q)) { - success &= (nm_platform_qdisc_add (self, NMP_NLM_FLAG_ADD, - NMP_OBJECT_CAST_QDISC (q)) >= 0); - } - } - } - - return success; +nm_platform_qdisc_sync(NMPlatform *self, int ifindex, GPtrArray *known_qdiscs) +{ + gs_unref_ptrarray GPtrArray *plat_qdiscs = NULL; + NMPLookup lookup; + guint i; + gboolean success = TRUE; + gs_unref_hashtable GHashTable *known_qdiscs_idx = NULL; + + nm_assert(NM_IS_PLATFORM(self)); + nm_assert(ifindex > 0); + + known_qdiscs_idx = + g_hash_table_new((GHashFunc) nmp_object_id_hash, (GEqualFunc) nmp_object_id_equal); + if (known_qdiscs) { + for (i = 0; i < known_qdiscs->len; i++) { + const NMPObject *q = g_ptr_array_index(known_qdiscs, i); + + if (!g_hash_table_insert(known_qdiscs_idx, (gpointer) q, (gpointer) q)) { + _LOGW("duplicate qdisc %s", nm_platform_qdisc_to_string(&q->qdisc, NULL, 0)); + return FALSE; + } + } + } + + plat_qdiscs = + nm_platform_lookup_clone(self, + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_QDISC, ifindex), + NULL, + NULL); + if (plat_qdiscs) { + for (i = 0; i < plat_qdiscs->len; i++) { + const NMPObject *p = g_ptr_array_index(plat_qdiscs, i); + const NMPObject *k; + + /* look up known qdisc with same parent */ + k = g_hash_table_lookup(known_qdiscs_idx, p); + + if (k) { + const NMPlatformQdisc *qdisc_k = NMP_OBJECT_CAST_QDISC(k); + const NMPlatformQdisc *qdisc_p = NMP_OBJECT_CAST_QDISC(p); + + /* check other fields */ + if (nm_platform_qdisc_cmp_full(qdisc_k, qdisc_p, FALSE) != 0 + || (qdisc_k->handle != qdisc_p->handle && qdisc_k != 0)) { + k = NULL; + } + } + + if (k) { + g_hash_table_remove(known_qdiscs_idx, k); + } else { + /* can't delete qdisc with zero handle */ + if (TC_H_MAJ(p->qdisc.handle) != 0) { + success &= nm_platform_object_delete(self, p); + } + } + } + } + + if (known_qdiscs) { + for (i = 0; i < known_qdiscs->len; i++) { + const NMPObject *q = g_ptr_array_index(known_qdiscs, i); + + if (g_hash_table_contains(known_qdiscs_idx, q)) { + success &= + (nm_platform_qdisc_add(self, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_QDISC(q)) >= 0); + } + } + } + + return success; } /*****************************************************************************/ int -nm_platform_tfilter_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformTfilter *tfilter) +nm_platform_tfilter_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformTfilter *tfilter) { - int ifindex = tfilter->ifindex; - _CHECK_SELF (self, klass, -NME_BUG); + int ifindex = tfilter->ifindex; + _CHECK_SELF(self, klass, -NME_BUG); - /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind - * and tfilter.action.kind is undefined. */ + /* Note: @tfilter must not be copied or kept alive because the lifetime of tfilter.kind + * and tfilter.action.kind is undefined. */ - _LOG3D ("adding or updating a tfilter: %s", nm_platform_tfilter_to_string (tfilter, NULL, 0)); - return klass->tfilter_add (self, flags, tfilter); + _LOG3D("adding or updating a tfilter: %s", nm_platform_tfilter_to_string(tfilter, NULL, 0)); + return klass->tfilter_add(self, flags, tfilter); } /** @@ -5156,110 +5342,120 @@ nm_platform_tfilter_add (NMPlatform *self, * Returns: %TRUE on success. */ gboolean -nm_platform_tfilter_sync (NMPlatform *self, - int ifindex, - GPtrArray *known_tfilters) +nm_platform_tfilter_sync(NMPlatform *self, int ifindex, GPtrArray *known_tfilters) { - gs_unref_ptrarray GPtrArray *plat_tfilters = NULL; - NMPLookup lookup; - guint i; - gboolean success = TRUE; - gs_unref_hashtable GHashTable *known_tfilters_idx = NULL; + gs_unref_ptrarray GPtrArray *plat_tfilters = NULL; + NMPLookup lookup; + guint i; + gboolean success = TRUE; + gs_unref_hashtable GHashTable *known_tfilters_idx = NULL; - nm_assert (NM_IS_PLATFORM (self)); - nm_assert (ifindex > 0); + nm_assert(NM_IS_PLATFORM(self)); + nm_assert(ifindex > 0); - known_tfilters_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal); + known_tfilters_idx = + g_hash_table_new((GHashFunc) nmp_object_id_hash, (GEqualFunc) nmp_object_id_equal); - if (known_tfilters) { - for (i = 0; i < known_tfilters->len; i++) { - const NMPObject *q = g_ptr_array_index (known_tfilters, i); + if (known_tfilters) { + for (i = 0; i < known_tfilters->len; i++) { + const NMPObject *q = g_ptr_array_index(known_tfilters, i); - g_hash_table_insert (known_tfilters_idx, (gpointer) q, (gpointer) q); - } - } + g_hash_table_insert(known_tfilters_idx, (gpointer) q, (gpointer) q); + } + } - plat_tfilters = nm_platform_lookup_clone (self, - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_TFILTER, - ifindex), - NULL, NULL); + plat_tfilters = + nm_platform_lookup_clone(self, + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_TFILTER, ifindex), + NULL, + NULL); - if (plat_tfilters) { - for (i = 0; i < plat_tfilters->len; i++) { - const NMPObject *q = g_ptr_array_index (plat_tfilters, i); + if (plat_tfilters) { + for (i = 0; i < plat_tfilters->len; i++) { + const NMPObject *q = g_ptr_array_index(plat_tfilters, i); - if (!g_hash_table_lookup (known_tfilters_idx, q)) - success &= nm_platform_object_delete (self, q); - } - } + if (!g_hash_table_lookup(known_tfilters_idx, q)) + success &= nm_platform_object_delete(self, q); + } + } - if (known_tfilters) { - for (i = 0; i < known_tfilters->len; i++) { - const NMPObject *q = g_ptr_array_index (known_tfilters, i); + if (known_tfilters) { + for (i = 0; i < known_tfilters->len; i++) { + const NMPObject *q = g_ptr_array_index(known_tfilters, i); - success &= (nm_platform_tfilter_add (self, NMP_NLM_FLAG_ADD, - NMP_OBJECT_CAST_TFILTER (q)) >= 0); - } - } + success &= + (nm_platform_tfilter_add(self, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_TFILTER(q)) >= 0); + } + } - return success; + return success; } /*****************************************************************************/ const char * -nm_platform_vlan_qos_mapping_to_string (const char *name, - const NMVlanQosMapping *map, - gsize n_map, - char *buf, - gsize len) +nm_platform_vlan_qos_mapping_to_string(const char * name, + const NMVlanQosMapping *map, + gsize n_map, + char * buf, + gsize len) { - gsize i; - char *b; + gsize i; + char *b; - nm_utils_to_string_buffer_init (&buf, &len); + nm_utils_to_string_buffer_init(&buf, &len); - if (!n_map) { - nm_utils_strbuf_append_str (&buf, &len, ""); - return buf; - } + if (!n_map) { + nm_utils_strbuf_append_str(&buf, &len, ""); + return buf; + } - if (!map) - g_return_val_if_reached (""); + if (!map) + g_return_val_if_reached(""); - b = buf; + b = buf; - if (name) { - nm_utils_strbuf_append_str (&b, &len, name); - nm_utils_strbuf_append_str (&b, &len, " {"); - } else - nm_utils_strbuf_append_c (&b, &len, '{'); + if (name) { + nm_utils_strbuf_append_str(&b, &len, name); + nm_utils_strbuf_append_str(&b, &len, " {"); + } else + nm_utils_strbuf_append_c(&b, &len, '{'); - for (i = 0; i < n_map; i++) - nm_utils_strbuf_append (&b, &len, " %u:%u", map[i].from, map[i].to); - nm_utils_strbuf_append_str (&b, &len, " }"); - return buf; + for (i = 0; i < n_map; i++) + nm_utils_strbuf_append(&b, &len, " %u:%u", map[i].from, map[i].to); + nm_utils_strbuf_append_str(&b, &len, " }"); + return buf; } static const char * -_lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size) +_lifetime_to_string(guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size) { - if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT) - return "forever"; + if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT) + return "forever"; - g_snprintf (buf, buf_size, "%usec", - nm_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now)); - return buf; + g_snprintf(buf, + buf_size, + "%usec", + nm_utils_lifetime_rebase_relative_time_on_now(timestamp, lifetime, now)); + return buf; } static const char * -_lifetime_summary_to_string (gint32 now, guint32 timestamp, guint32 preferred, guint32 lifetime, char *buf, size_t buf_size) -{ - g_snprintf (buf, buf_size, " lifetime %d-%u[%u,%u]", - (signed) now, (unsigned) timestamp, (unsigned) preferred, (unsigned) lifetime); - return buf; +_lifetime_summary_to_string(gint32 now, + guint32 timestamp, + guint32 preferred, + guint32 lifetime, + char * buf, + size_t buf_size) +{ + g_snprintf(buf, + buf_size, + " lifetime %d-%u[%u,%u]", + (signed) now, + (unsigned) timestamp, + (unsigned) preferred, + (unsigned) lifetime); + return buf; } /** @@ -5273,575 +5469,720 @@ _lifetime_summary_to_string (gint32 now, guint32 timestamp, guint32 preferred, g * Returns: a string representation of the link. */ const char * -nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) -{ - char master[20]; - char parent[20]; - char str_flags[1 + NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN + 1]; - char str_highlighted_flags[50]; - char *s; - gsize l; - char str_addrmode[30]; - char str_address[NM_UTILS_HWADDR_LEN_MAX * 3]; - char str_broadcast[NM_UTILS_HWADDR_LEN_MAX * 3]; - char str_inet6_token[NM_UTILS_INET_ADDRSTRLEN]; - const char *str_link_type; - - if (!nm_utils_to_string_buffer_init_null (link, &buf, &len)) - return buf; - - s = str_highlighted_flags; - l = sizeof (str_highlighted_flags); - if (NM_FLAGS_HAS (link->n_ifi_flags, IFF_NOARP)) - nm_utils_strbuf_append_str (&s, &l, "NOARP,"); - if (NM_FLAGS_HAS (link->n_ifi_flags, IFF_UP)) - nm_utils_strbuf_append_str (&s, &l, "UP"); - else - nm_utils_strbuf_append_str (&s, &l, "DOWN"); - if (link->connected) - nm_utils_strbuf_append_str (&s, &l, ",LOWER_UP"); - nm_assert (s > str_highlighted_flags && l > 0); - - if (link->n_ifi_flags) { - str_flags[0] = ';'; - nm_platform_link_flags2str (link->n_ifi_flags, &str_flags[1], sizeof (str_flags) - 1); - } else - str_flags[0] = '\0'; - - if (link->master) - g_snprintf (master, sizeof (master), " master %d", link->master); - else - master[0] = 0; - - if (link->parent > 0) - g_snprintf (parent, sizeof (parent), "@%d", link->parent); - else if (link->parent == NM_PLATFORM_LINK_OTHER_NETNS) - g_strlcpy (parent, "@other-netns", sizeof (parent)); - else - parent[0] = 0; - - _nmp_link_address_to_string (&link->l_address, str_address); - _nmp_link_address_to_string (&link->l_broadcast, str_broadcast); - - str_link_type = nm_link_type_to_string (link->type); - - g_snprintf (buf, len, - "%d: " /* ifindex */ - "%s" /* name */ - "%s" /* parent */ - " <%s%s>" /* flags */ - " mtu %d" - "%s" /* master */ - " arp %u" /* arptype */ - " %s" /* link->type */ - "%s%s" /* kind */ - "%s" /* is-in-udev */ - "%s%s" /* addr-gen-mode */ - "%s%s" /* l_address */ - "%s%s" /* l_broadcast */ - "%s%s" /* inet6_token */ - "%s%s" /* driver */ - " rx:%"G_GUINT64_FORMAT",%"G_GUINT64_FORMAT - " tx:%"G_GUINT64_FORMAT",%"G_GUINT64_FORMAT - , - link->ifindex, - link->name, - parent, - str_highlighted_flags, - str_flags, - link->mtu, master, - link->arptype, - str_link_type ?: "???", - link->kind ? (g_strcmp0 (str_link_type, link->kind) ? "/" : "*") : "?", - link->kind && g_strcmp0 (str_link_type, link->kind) ? link->kind : "", - link->initialized ? " init" : " not-init", - link->inet6_addr_gen_mode_inv ? " addrgenmode " : "", - link->inet6_addr_gen_mode_inv ? nm_platform_link_inet6_addrgenmode2str (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv), str_addrmode, sizeof (str_addrmode)) : "", - str_address[0] ? " addr " : "", - str_address[0] ? str_address : "", - str_broadcast[0] ? " brd " : "", - str_broadcast[0] ? str_broadcast : "", - link->inet6_token.id ? " inet6token " : "", - link->inet6_token.id ? nm_utils_inet6_interface_identifier_to_token (link->inet6_token, str_inet6_token) : "", - link->driver ? " driver " : "", - link->driver ?: "", - link->rx_packets, link->rx_bytes, - link->tx_packets, link->tx_bytes); - return buf; +nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len) +{ + char master[20]; + char parent[20]; + char str_flags[1 + NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN + 1]; + char str_highlighted_flags[50]; + char * s; + gsize l; + char str_addrmode[30]; + char str_address[NM_UTILS_HWADDR_LEN_MAX * 3]; + char str_broadcast[NM_UTILS_HWADDR_LEN_MAX * 3]; + char str_inet6_token[NM_UTILS_INET_ADDRSTRLEN]; + const char *str_link_type; + + if (!nm_utils_to_string_buffer_init_null(link, &buf, &len)) + return buf; + + s = str_highlighted_flags; + l = sizeof(str_highlighted_flags); + if (NM_FLAGS_HAS(link->n_ifi_flags, IFF_NOARP)) + nm_utils_strbuf_append_str(&s, &l, "NOARP,"); + if (NM_FLAGS_HAS(link->n_ifi_flags, IFF_UP)) + nm_utils_strbuf_append_str(&s, &l, "UP"); + else + nm_utils_strbuf_append_str(&s, &l, "DOWN"); + if (link->connected) + nm_utils_strbuf_append_str(&s, &l, ",LOWER_UP"); + nm_assert(s > str_highlighted_flags && l > 0); + + if (link->n_ifi_flags) { + str_flags[0] = ';'; + nm_platform_link_flags2str(link->n_ifi_flags, &str_flags[1], sizeof(str_flags) - 1); + } else + str_flags[0] = '\0'; + + if (link->master) + g_snprintf(master, sizeof(master), " master %d", link->master); + else + master[0] = 0; + + if (link->parent > 0) + g_snprintf(parent, sizeof(parent), "@%d", link->parent); + else if (link->parent == NM_PLATFORM_LINK_OTHER_NETNS) + g_strlcpy(parent, "@other-netns", sizeof(parent)); + else + parent[0] = 0; + + _nmp_link_address_to_string(&link->l_address, str_address); + _nmp_link_address_to_string(&link->l_broadcast, str_broadcast); + + str_link_type = nm_link_type_to_string(link->type); + + g_snprintf( + buf, + len, + "%d: " /* ifindex */ + "%s" /* name */ + "%s" /* parent */ + " <%s%s>" /* flags */ + " mtu %d" + "%s" /* master */ + " arp %u" /* arptype */ + " %s" /* link->type */ + "%s%s" /* kind */ + "%s" /* is-in-udev */ + "%s%s" /* addr-gen-mode */ + "%s%s" /* l_address */ + "%s%s" /* l_broadcast */ + "%s%s" /* inet6_token */ + "%s%s" /* driver */ + " rx:%" G_GUINT64_FORMAT ",%" G_GUINT64_FORMAT " tx:%" G_GUINT64_FORMAT + ",%" G_GUINT64_FORMAT, + link->ifindex, + link->name, + parent, + str_highlighted_flags, + str_flags, + link->mtu, + master, + link->arptype, + str_link_type ?: "???", + link->kind ? (g_strcmp0(str_link_type, link->kind) ? "/" : "*") : "?", + link->kind && g_strcmp0(str_link_type, link->kind) ? link->kind : "", + link->initialized ? " init" : " not-init", + link->inet6_addr_gen_mode_inv ? " addrgenmode " : "", + link->inet6_addr_gen_mode_inv ? nm_platform_link_inet6_addrgenmode2str( + _nm_platform_uint8_inv(link->inet6_addr_gen_mode_inv), + str_addrmode, + sizeof(str_addrmode)) + : "", + str_address[0] ? " addr " : "", + str_address[0] ? str_address : "", + str_broadcast[0] ? " brd " : "", + str_broadcast[0] ? str_broadcast : "", + link->inet6_token.id ? " inet6token " : "", + link->inet6_token.id + ? nm_utils_inet6_interface_identifier_to_token(link->inet6_token, str_inet6_token) + : "", + link->driver ? " driver " : "", + link->driver ?: "", + link->rx_packets, + link->rx_bytes, + link->tx_packets, + link->tx_bytes); + return buf; +} + +const NMPlatformLnkBridge nm_platform_lnk_bridge_default = { + .forward_delay = NM_BRIDGE_FORWARD_DELAY_DEF_SYS, + .hello_time = NM_BRIDGE_HELLO_TIME_DEF_SYS, + .max_age = NM_BRIDGE_MAX_AGE_DEF_SYS, + .ageing_time = NM_BRIDGE_AGEING_TIME_DEF_SYS, + .stp_state = FALSE, + .priority = NM_BRIDGE_PRIORITY_DEF, + .vlan_protocol = 0x8100, + .vlan_stats_enabled = NM_BRIDGE_VLAN_STATS_ENABLED_DEF, + .group_fwd_mask = 0, + .group_addr = NM_ETHER_ADDR_INIT(NM_BRIDGE_GROUP_ADDRESS_DEF_BIN), + .mcast_snooping = NM_BRIDGE_MULTICAST_SNOOPING_DEF, + .mcast_router = 1, + .mcast_query_use_ifaddr = NM_BRIDGE_MULTICAST_QUERY_USE_IFADDR_DEF, + .mcast_querier = NM_BRIDGE_MULTICAST_QUERIER_DEF, + .mcast_hash_max = NM_BRIDGE_MULTICAST_HASH_MAX_DEF, + .mcast_last_member_count = NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF, + .mcast_startup_query_count = NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF, + .mcast_last_member_interval = NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF, + .mcast_membership_interval = NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF, + .mcast_querier_interval = NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF, + .mcast_query_interval = NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF, + .mcast_query_response_interval = NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF, + .mcast_startup_query_interval = NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF, +}; + +const char * +nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsize len) +{ + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + g_snprintf(buf, + len, + "forward_delay %u" + " hello_time %u" + " max_age %u" + " ageing_time %u" + " stp_state %d" + " priority %u" + " vlan_protocol %u" + " vlan_stats_enabled %d" + " group_fwd_mask %#x" + " group_address " NM_ETHER_ADDR_FORMAT_STR " mcast_snooping %d" + " mcast_router %u" + " mcast_query_use_ifaddr %d" + " mcast_querier %d" + " mcast_hash_max %u" + " mcast_last_member_count %u" + " mcast_startup_query_count %u" + " mcast_last_member_interval %" G_GUINT64_FORMAT + " mcast_membership_interval %" G_GUINT64_FORMAT + " mcast_querier_interval %" G_GUINT64_FORMAT + " mcast_query_interval %" G_GUINT64_FORMAT + " mcast_query_response_interval %" G_GUINT64_FORMAT + " mcast_startup_query_interval %" G_GUINT64_FORMAT "", + lnk->forward_delay, + lnk->hello_time, + lnk->max_age, + lnk->ageing_time, + (int) lnk->stp_state, + lnk->priority, + lnk->vlan_protocol, + (int) lnk->vlan_stats_enabled, + lnk->group_fwd_mask, + NM_ETHER_ADDR_FORMAT_VAL(lnk->group_addr), + (int) lnk->mcast_snooping, + lnk->mcast_router, + (int) lnk->mcast_query_use_ifaddr, + (int) lnk->mcast_querier, + lnk->mcast_hash_max, + lnk->mcast_last_member_count, + lnk->mcast_startup_query_count, + lnk->mcast_last_member_interval, + lnk->mcast_membership_interval, + lnk->mcast_querier_interval, + lnk->mcast_query_interval, + lnk->mcast_query_response_interval, + lnk->mcast_startup_query_interval); + return buf; } const char * -nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tos[30]; - char str_parent_ifindex[30]; - char str_input_flags[30]; - char str_output_flags[30]; - char str_input_key[30]; - char str_input_key1[NM_UTILS_INET_ADDRSTRLEN]; - char str_output_key[30]; - char str_output_key1[NM_UTILS_INET_ADDRSTRLEN]; - - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - g_snprintf (buf, len, - "gre%s" /* is_tap */ - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tos */ - "%s" /* path_mtu_discovery */ - "%s" /* iflags */ - "%s" /* oflags */ - "%s" /* ikey */ - "%s" /* okey */ - "", - lnk->is_tap ? "tap" : "", - lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", - lnk->local ? nm_sprintf_buf (str_local, " local %s", _nm_utils_inet4_ntop (lnk->local, str_local1)) : "", - lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", - lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", - lnk->path_mtu_discovery ? "" : " nopmtudisc", - lnk->input_flags ? nm_sprintf_buf (str_input_flags, " iflags 0x%x", lnk->input_flags) : "", - lnk->output_flags ? nm_sprintf_buf (str_output_flags, " oflags 0x%x", lnk->output_flags) : "", - NM_FLAGS_HAS (lnk->input_flags, GRE_KEY) || lnk->input_key ? nm_sprintf_buf (str_input_key, " ikey %s", _nm_utils_inet4_ntop (lnk->input_key, str_input_key1)) : "", - NM_FLAGS_HAS (lnk->output_flags, GRE_KEY) || lnk->output_key ? nm_sprintf_buf (str_output_key, " okey %s", _nm_utils_inet4_ntop (lnk->output_key, str_output_key1)) : ""); - return buf; +nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_parent_ifindex[30]; + char str_input_flags[30]; + char str_output_flags[30]; + char str_input_key[30]; + char str_input_key1[NM_UTILS_INET_ADDRSTRLEN]; + char str_output_key[30]; + char str_output_key1[NM_UTILS_INET_ADDRSTRLEN]; + + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + g_snprintf( + buf, + len, + "gre%s" /* is_tap */ + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "%s" /* iflags */ + "%s" /* oflags */ + "%s" /* ikey */ + "%s" /* okey */ + "", + lnk->is_tap ? "tap" : "", + lnk->remote ? nm_sprintf_buf(str_remote, + " remote %s", + _nm_utils_inet4_ntop(lnk->remote, str_remote1)) + : "", + lnk->local + ? nm_sprintf_buf(str_local, " local %s", _nm_utils_inet4_ntop(lnk->local, str_local1)) + : "", + lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) + : "", + lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos)) + : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc", + lnk->input_flags ? nm_sprintf_buf(str_input_flags, " iflags 0x%x", lnk->input_flags) : "", + lnk->output_flags ? nm_sprintf_buf(str_output_flags, " oflags 0x%x", lnk->output_flags) + : "", + NM_FLAGS_HAS(lnk->input_flags, GRE_KEY) || lnk->input_key + ? nm_sprintf_buf(str_input_key, + " ikey %s", + _nm_utils_inet4_ntop(lnk->input_key, str_input_key1)) + : "", + NM_FLAGS_HAS(lnk->output_flags, GRE_KEY) || lnk->output_key + ? nm_sprintf_buf(str_output_key, + " okey %s", + _nm_utils_inet4_ntop(lnk->output_key, str_output_key1)) + : ""); + return buf; } const char * -nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len) +nm_platform_lnk_infiniband_to_string(const NMPlatformLnkInfiniband *lnk, char *buf, gsize len) { - char str_p_key[64]; + char str_p_key[64]; - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; - g_snprintf (buf, len, - "infiniband" - "%s" /* p_key */ - "%s%s" /* mode */ - "", - lnk->p_key ? nm_sprintf_buf (str_p_key, " pkey %d", lnk->p_key) : "", - lnk->mode ? " mode " : "", - lnk->mode ?: ""); - return buf; + g_snprintf(buf, + len, + "infiniband" + "%s" /* p_key */ + "%s%s" /* mode */ + "", + lnk->p_key ? nm_sprintf_buf(str_p_key, " pkey %d", lnk->p_key) : "", + lnk->mode ? " mode " : "", + lnk->mode ?: ""); + return buf; } const char * -nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tclass[30]; - char str_flow[30]; - char str_encap[30]; - char str_proto[30]; - char str_parent_ifindex[30]; - char *str_type; - - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - if (lnk->is_gre) - str_type = lnk->is_tap ? "ip6gretap" : "ip6gre"; - else - str_type = "ip6tnl"; - - g_snprintf (buf, len, - "%s" /* type */ - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tclass */ - "%s" /* encap limit */ - "%s" /* flow label */ - "%s" /* proto */ - " flags 0x%x" - "", - str_type, - nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet6_ntop (&lnk->remote, str_remote1)), - nm_sprintf_buf (str_local, " local %s", _nm_utils_inet6_ntop (&lnk->local, str_local1)), - lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", - lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tclass == 1 ? " tclass inherit" : nm_sprintf_buf (str_tclass, " tclass 0x%x", lnk->tclass), - nm_sprintf_buf (str_encap, " encap-limit %u", lnk->encap_limit), - nm_sprintf_buf (str_flow, " flow-label 0x05%x", lnk->flow_label), - nm_sprintf_buf (str_proto, " proto %u", lnk->proto), - (guint) lnk->flags); - return buf; +nm_platform_lnk_ip6tnl_to_string(const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tclass[30]; + char str_flow[30]; + char str_encap[30]; + char str_proto[30]; + char str_parent_ifindex[30]; + char *str_type; + + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + if (lnk->is_gre) + str_type = lnk->is_tap ? "ip6gretap" : "ip6gre"; + else + str_type = "ip6tnl"; + + g_snprintf( + buf, + len, + "%s" /* type */ + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tclass */ + "%s" /* encap limit */ + "%s" /* flow label */ + "%s" /* proto */ + " flags 0x%x" + "", + str_type, + nm_sprintf_buf(str_remote, " remote %s", _nm_utils_inet6_ntop(&lnk->remote, str_remote1)), + nm_sprintf_buf(str_local, " local %s", _nm_utils_inet6_ntop(&lnk->local, str_local1)), + lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) + : "", + lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tclass == 1 ? " tclass inherit" + : nm_sprintf_buf(str_tclass, " tclass 0x%x", lnk->tclass), + nm_sprintf_buf(str_encap, " encap-limit %u", lnk->encap_limit), + nm_sprintf_buf(str_flow, " flow-label 0x05%x", lnk->flow_label), + nm_sprintf_buf(str_proto, " proto %u", lnk->proto), + (guint) lnk->flags); + return buf; } const char * -nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tos[30]; - char str_parent_ifindex[30]; - - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - g_snprintf (buf, len, - "ipip" - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tos */ - "%s" /* path_mtu_discovery */ - "", - lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", - lnk->local ? nm_sprintf_buf (str_local, " local %s", _nm_utils_inet4_ntop (lnk->local, str_local1)) : "", - lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", - lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", - lnk->path_mtu_discovery ? "" : " nopmtudisc"); - return buf; +nm_platform_lnk_ipip_to_string(const NMPlatformLnkIpIp *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + g_snprintf( + buf, + len, + "ipip" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "", + lnk->remote ? nm_sprintf_buf(str_remote, + " remote %s", + _nm_utils_inet4_ntop(lnk->remote, str_remote1)) + : "", + lnk->local + ? nm_sprintf_buf(str_local, " local %s", _nm_utils_inet4_ntop(lnk->local, str_local1)) + : "", + lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) + : "", + lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos)) + : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc"); + return buf; } const char * -nm_platform_lnk_macsec_to_string (const NMPlatformLnkMacsec *lnk, char *buf, gsize len) -{ - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - g_snprintf (buf, len, - "macsec " - "sci %016llx " - "protect %s " - "cipher %016llx " - "icvlen %u " - "encodingsa %u " - "validate %u " - "encrypt %s " - "send_sci %s " - "end_station %s " - "scb %s " - "replay %s", - (unsigned long long) lnk->sci, - lnk->protect ? "on" : "off", - (unsigned long long) lnk->cipher_suite, - lnk->icv_length, - lnk->encoding_sa, - lnk->validation, - lnk->encrypt ? "on" : "off", - lnk->include_sci ? "on" : "off", - lnk->es ? "on" : "off", - lnk->scb ? "on" : "off", - lnk->replay_protect ? "on" : "off"); - return buf; +nm_platform_lnk_macsec_to_string(const NMPlatformLnkMacsec *lnk, char *buf, gsize len) +{ + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + g_snprintf(buf, + len, + "macsec " + "sci %016llx " + "protect %s " + "cipher %016llx " + "icvlen %u " + "encodingsa %u " + "validate %u " + "encrypt %s " + "send_sci %s " + "end_station %s " + "scb %s " + "replay %s", + (unsigned long long) lnk->sci, + lnk->protect ? "on" : "off", + (unsigned long long) lnk->cipher_suite, + lnk->icv_length, + lnk->encoding_sa, + lnk->validation, + lnk->encrypt ? "on" : "off", + lnk->include_sci ? "on" : "off", + lnk->es ? "on" : "off", + lnk->scb ? "on" : "off", + lnk->replay_protect ? "on" : "off"); + return buf; } const char * -nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len) +nm_platform_lnk_macvlan_to_string(const NMPlatformLnkMacvlan *lnk, char *buf, gsize len) { - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; - g_snprintf (buf, len, - "%s mode %u %s", - lnk->tap ? "macvtap" : "macvlan", - lnk->mode, - lnk->no_promisc ? "not-promisc" : "promisc"); - return buf; + g_snprintf(buf, + len, + "%s mode %u %s", + lnk->tap ? "macvtap" : "macvlan", + lnk->mode, + lnk->no_promisc ? "not-promisc" : "promisc"); + return buf; } const char * -nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len) -{ - char str_local[30]; - char str_local1[NM_UTILS_INET_ADDRSTRLEN]; - char str_remote[30]; - char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; - char str_ttl[30]; - char str_tos[30]; - char str_flags[30]; - char str_proto[30]; - char str_parent_ifindex[30]; - - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - g_snprintf (buf, len, - "sit" - "%s" /* remote */ - "%s" /* local */ - "%s" /* parent_ifindex */ - "%s" /* ttl */ - "%s" /* tos */ - "%s" /* path_mtu_discovery */ - "%s" /* flags */ - "%s" /* proto */ - "", - lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", _nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", - lnk->local ? nm_sprintf_buf (str_local, " local %s", _nm_utils_inet4_ntop (lnk->local, str_local1)) : "", - lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", - lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", - lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", - lnk->path_mtu_discovery ? "" : " nopmtudisc", - lnk->flags ? nm_sprintf_buf (str_flags, " flags 0x%x", lnk->flags) : "", - lnk->proto ? nm_sprintf_buf (str_proto, " proto 0x%x", lnk->proto) : ""); - return buf; +nm_platform_lnk_sit_to_string(const NMPlatformLnkSit *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_flags[30]; + char str_proto[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + g_snprintf( + buf, + len, + "sit" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "%s" /* flags */ + "%s" /* proto */ + "", + lnk->remote ? nm_sprintf_buf(str_remote, + " remote %s", + _nm_utils_inet4_ntop(lnk->remote, str_remote1)) + : "", + lnk->local + ? nm_sprintf_buf(str_local, " local %s", _nm_utils_inet4_ntop(lnk->local, str_local1)) + : "", + lnk->parent_ifindex ? nm_sprintf_buf(str_parent_ifindex, " dev %d", lnk->parent_ifindex) + : "", + lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos)) + : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc", + lnk->flags ? nm_sprintf_buf(str_flags, " flags 0x%x", lnk->flags) : "", + lnk->proto ? nm_sprintf_buf(str_proto, " proto 0x%x", lnk->proto) : ""); + return buf; } const char * -nm_platform_lnk_tun_to_string (const NMPlatformLnkTun *lnk, char *buf, gsize len) -{ - char str_owner[50]; - char str_group[50]; - char str_type[50]; - const char *type; - - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - if (lnk->type == IFF_TUN) - type = "tun"; - else if (lnk->type == IFF_TAP) - type = "tap"; - else - type = nm_sprintf_buf (str_type, "tun type %u", (guint) lnk->type); - - g_snprintf (buf, len, - "%s" /* type */ - "%s" /* pi */ - "%s" /* vnet_hdr */ - "%s" /* multi_queue */ - "%s" /* persist */ - "%s" /* owner */ - "%s" /* group */ - "", - type, - lnk->pi ? " pi" : "", - lnk->vnet_hdr ? " vnet_hdr" : "", - lnk->multi_queue ? " multi_queue" : "", - lnk->persist ? " persist" : "", - lnk->owner_valid ? nm_sprintf_buf (str_owner, " owner %u", (guint) lnk->owner) : "", - lnk->group_valid ? nm_sprintf_buf (str_group, " group %u", (guint) lnk->group) : ""); - return buf; +nm_platform_lnk_tun_to_string(const NMPlatformLnkTun *lnk, char *buf, gsize len) +{ + char str_owner[50]; + char str_group[50]; + char str_type[50]; + const char *type; + + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + if (lnk->type == IFF_TUN) + type = "tun"; + else if (lnk->type == IFF_TAP) + type = "tap"; + else + type = nm_sprintf_buf(str_type, "tun type %u", (guint) lnk->type); + + g_snprintf(buf, + len, + "%s" /* type */ + "%s" /* pi */ + "%s" /* vnet_hdr */ + "%s" /* multi_queue */ + "%s" /* persist */ + "%s" /* owner */ + "%s" /* group */ + "", + type, + lnk->pi ? " pi" : "", + lnk->vnet_hdr ? " vnet_hdr" : "", + lnk->multi_queue ? " multi_queue" : "", + lnk->persist ? " persist" : "", + lnk->owner_valid ? nm_sprintf_buf(str_owner, " owner %u", (guint) lnk->owner) : "", + lnk->group_valid ? nm_sprintf_buf(str_group, " group %u", (guint) lnk->group) : ""); + return buf; } const char * -nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len) +nm_platform_lnk_vlan_to_string(const NMPlatformLnkVlan *lnk, char *buf, gsize len) { - char *b; + char *b; - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; - b = buf; + b = buf; - nm_utils_strbuf_append (&b, &len, "vlan %u", lnk->id); - if (lnk->flags) - nm_utils_strbuf_append (&b, &len, " flags 0x%x", lnk->flags); - return buf; + nm_utils_strbuf_append(&b, &len, "vlan %u", lnk->id); + if (lnk->flags) + nm_utils_strbuf_append(&b, &len, " flags 0x%x", lnk->flags); + return buf; } const char * -nm_platform_lnk_vrf_to_string (const NMPlatformLnkVrf *lnk, char *buf, gsize len) +nm_platform_lnk_vrf_to_string(const NMPlatformLnkVrf *lnk, char *buf, gsize len) { - char *b; + char *b; - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; - b = buf; + b = buf; - nm_utils_strbuf_append (&b, &len, "table %u", lnk->table); - return buf; + nm_utils_strbuf_append(&b, &len, "table %u", lnk->table); + return buf; } const char * -nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len) -{ - char str_group[100]; - char str_group6[100]; - char str_local[100]; - char str_local6[100]; - char str_dev[25]; - char str_limit[25]; - char str_src_port[35]; - char str_dst_port[25]; - char str_tos[25]; - char str_ttl[25]; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; - - if (lnk->group == 0) - str_group[0] = '\0'; - else { - g_snprintf (str_group, sizeof (str_group), - " %s %s", - IN_MULTICAST (ntohl (lnk->group)) ? "group" : "remote", - _nm_utils_inet4_ntop (lnk->group, sbuf)); - } - if (IN6_IS_ADDR_UNSPECIFIED (&lnk->group6)) - str_group6[0] = '\0'; - else { - g_snprintf (str_group6, sizeof (str_group6), - " %s%s %s", - IN6_IS_ADDR_MULTICAST (&lnk->group6) ? "group" : "remote", - str_group[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ - _nm_utils_inet6_ntop (&lnk->group6, sbuf)); - } - - if (lnk->local == 0) - str_local[0] = '\0'; - else { - g_snprintf (str_local, sizeof (str_local), - " local %s", - _nm_utils_inet4_ntop (lnk->local, sbuf)); - } - if (IN6_IS_ADDR_UNSPECIFIED (&lnk->local6)) - str_local6[0] = '\0'; - else { - g_snprintf (str_local6, sizeof (str_local6), - " local%s %s", - str_local[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ - _nm_utils_inet6_ntop (&lnk->local6, sbuf)); - } - - g_snprintf (buf, len, - "vxlan" - " id %u" /* id */ - "%s%s" /* group/group6 */ - "%s%s" /* local/local6 */ - "%s" /* dev */ - "%s" /* src_port_min/src_port_max */ - "%s" /* dst_port */ - "%s" /* learning */ - "%s" /* proxy */ - "%s" /* rsc */ - "%s" /* l2miss */ - "%s" /* l3miss */ - "%s" /* tos */ - "%s" /* ttl */ - " ageing %u" /* ageing */ - "%s" /* limit */ - "", - (guint) lnk->id, - str_group, str_group6, - str_local, str_local6, - lnk->parent_ifindex ? nm_sprintf_buf (str_dev, " dev %d", lnk->parent_ifindex) : "", - lnk->src_port_min || lnk->src_port_max ? nm_sprintf_buf (str_src_port, " srcport %u %u", lnk->src_port_min, lnk->src_port_max) : "", - lnk->dst_port ? nm_sprintf_buf (str_dst_port, " dstport %u", lnk->dst_port) : "", - !lnk->learning ? " nolearning" : "", - lnk->proxy ? " proxy" : "", - lnk->rsc ? " rsc" : "", - lnk->l2miss ? " l2miss" : "", - lnk->l3miss ? " l3miss" : "", - lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos %#x", lnk->tos), - lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : "", - lnk->ageing, - lnk->limit ? nm_sprintf_buf (str_limit, " maxaddr %u", lnk->limit) : ""); - return buf; +nm_platform_lnk_vxlan_to_string(const NMPlatformLnkVxlan *lnk, char *buf, gsize len) +{ + char str_group[100]; + char str_group6[100]; + char str_local[100]; + char str_local6[100]; + char str_dev[25]; + char str_limit[25]; + char str_src_port[35]; + char str_dst_port[25]; + char str_tos[25]; + char str_ttl[25]; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + if (lnk->group == 0) + str_group[0] = '\0'; + else { + g_snprintf(str_group, + sizeof(str_group), + " %s %s", + IN_MULTICAST(ntohl(lnk->group)) ? "group" : "remote", + _nm_utils_inet4_ntop(lnk->group, sbuf)); + } + if (IN6_IS_ADDR_UNSPECIFIED(&lnk->group6)) + str_group6[0] = '\0'; + else { + g_snprintf(str_group6, + sizeof(str_group6), + " %s%s %s", + IN6_IS_ADDR_MULTICAST(&lnk->group6) ? "group" : "remote", + str_group[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ + _nm_utils_inet6_ntop(&lnk->group6, sbuf)); + } + + if (lnk->local == 0) + str_local[0] = '\0'; + else { + g_snprintf(str_local, + sizeof(str_local), + " local %s", + _nm_utils_inet4_ntop(lnk->local, sbuf)); + } + if (IN6_IS_ADDR_UNSPECIFIED(&lnk->local6)) + str_local6[0] = '\0'; + else { + g_snprintf(str_local6, + sizeof(str_local6), + " local%s %s", + str_local[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ + _nm_utils_inet6_ntop(&lnk->local6, sbuf)); + } + + g_snprintf( + buf, + len, + "vxlan" + " id %u" /* id */ + "%s%s" /* group/group6 */ + "%s%s" /* local/local6 */ + "%s" /* dev */ + "%s" /* src_port_min/src_port_max */ + "%s" /* dst_port */ + "%s" /* learning */ + "%s" /* proxy */ + "%s" /* rsc */ + "%s" /* l2miss */ + "%s" /* l3miss */ + "%s" /* tos */ + "%s" /* ttl */ + " ageing %u" /* ageing */ + "%s" /* limit */ + "", + (guint) lnk->id, + str_group, + str_group6, + str_local, + str_local6, + lnk->parent_ifindex ? nm_sprintf_buf(str_dev, " dev %d", lnk->parent_ifindex) : "", + lnk->src_port_min || lnk->src_port_max + ? nm_sprintf_buf(str_src_port, " srcport %u %u", lnk->src_port_min, lnk->src_port_max) + : "", + lnk->dst_port ? nm_sprintf_buf(str_dst_port, " dstport %u", lnk->dst_port) : "", + !lnk->learning ? " nolearning" : "", + lnk->proxy ? " proxy" : "", + lnk->rsc ? " rsc" : "", + lnk->l2miss ? " l2miss" : "", + lnk->l3miss ? " l3miss" : "", + lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos %#x", lnk->tos), + lnk->ttl ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl) : "", + lnk->ageing, + lnk->limit ? nm_sprintf_buf(str_limit, " maxaddr %u", lnk->limit) : ""); + return buf; } const char * -nm_platform_wireguard_peer_to_string (const NMPWireGuardPeer *peer, char *buf, gsize len) -{ - char *buf0 = buf; - gs_free char *public_key_b64 = NULL; - char s_sockaddr[NM_UTILS_INET_ADDRSTRLEN + 100]; - char s_endpoint[20 + sizeof (s_sockaddr)]; - char s_addr[NM_UTILS_INET_ADDRSTRLEN]; - char s_keepalive[100]; - guint i; - - nm_utils_to_string_buffer_init (&buf, &len); - - public_key_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key)); - - if (peer->endpoint.sa.sa_family != AF_UNSPEC) { - nm_sprintf_buf (s_endpoint, - " endpoint %s", - nm_sock_addr_union_to_string (&peer->endpoint, - s_sockaddr, - sizeof (s_sockaddr))); - } else - s_endpoint[0] = '\0'; - - nm_utils_strbuf_append (&buf, &len, - "public-key %s" - "%s" /* preshared-key */ - "%s" /* endpoint */ - " rx %"G_GUINT64_FORMAT - " tx %"G_GUINT64_FORMAT - "%s" /* persistent-keepalive */ - "%s", /* allowed-ips */ - public_key_b64, - nm_utils_memeqzero_secret (peer->preshared_key, sizeof (peer->preshared_key)) - ? "" - : " preshared-key (hidden)", - s_endpoint, - peer->rx_bytes, - peer->tx_bytes, - peer->persistent_keepalive_interval > 0 - ? nm_sprintf_buf (s_keepalive, " keepalive %u", (guint) peer->persistent_keepalive_interval) - : "", - peer->allowed_ips_len > 0 - ? " allowed-ips" - : ""); - - for (i = 0; i < peer->allowed_ips_len; i++) { - const NMPWireGuardAllowedIP *allowed_ip = &peer->allowed_ips[i]; - - nm_utils_strbuf_append (&buf, &len, - " %s/%u", - nm_utils_inet_ntop (allowed_ip->family, &allowed_ip->addr, s_addr), - allowed_ip->mask); - } - - return buf0; +nm_platform_wireguard_peer_to_string(const NMPWireGuardPeer *peer, char *buf, gsize len) +{ + char * buf0 = buf; + gs_free char *public_key_b64 = NULL; + char s_sockaddr[NM_UTILS_INET_ADDRSTRLEN + 100]; + char s_endpoint[20 + sizeof(s_sockaddr)]; + char s_addr[NM_UTILS_INET_ADDRSTRLEN]; + char s_keepalive[100]; + guint i; + + nm_utils_to_string_buffer_init(&buf, &len); + + public_key_b64 = g_base64_encode(peer->public_key, sizeof(peer->public_key)); + + if (peer->endpoint.sa.sa_family != AF_UNSPEC) { + nm_sprintf_buf( + s_endpoint, + " endpoint %s", + nm_sock_addr_union_to_string(&peer->endpoint, s_sockaddr, sizeof(s_sockaddr))); + } else + s_endpoint[0] = '\0'; + + nm_utils_strbuf_append( + &buf, + &len, + "public-key %s" + "%s" /* preshared-key */ + "%s" /* endpoint */ + " rx %" G_GUINT64_FORMAT " tx %" G_GUINT64_FORMAT "%s" /* persistent-keepalive */ + "%s", /* allowed-ips */ + public_key_b64, + nm_utils_memeqzero_secret(peer->preshared_key, sizeof(peer->preshared_key)) + ? "" + : " preshared-key (hidden)", + s_endpoint, + peer->rx_bytes, + peer->tx_bytes, + peer->persistent_keepalive_interval > 0 + ? nm_sprintf_buf(s_keepalive, + " keepalive %u", + (guint) peer->persistent_keepalive_interval) + : "", + peer->allowed_ips_len > 0 ? " allowed-ips" : ""); + + for (i = 0; i < peer->allowed_ips_len; i++) { + const NMPWireGuardAllowedIP *allowed_ip = &peer->allowed_ips[i]; + + nm_utils_strbuf_append(&buf, + &len, + " %s/%u", + nm_utils_inet_ntop(allowed_ip->family, &allowed_ip->addr, s_addr), + allowed_ip->mask); + } + + return buf0; } const char * -nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len) +nm_platform_lnk_wireguard_to_string(const NMPlatformLnkWireGuard *lnk, char *buf, gsize len) { - gs_free char *public_b64 = NULL; + gs_free char *public_b64 = NULL; - if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) - return buf; + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; - if (!nm_utils_memeqzero (lnk->public_key, sizeof (lnk->public_key))) - public_b64 = g_base64_encode (lnk->public_key, sizeof (lnk->public_key)); + if (!nm_utils_memeqzero(lnk->public_key, sizeof(lnk->public_key))) + public_b64 = g_base64_encode(lnk->public_key, sizeof(lnk->public_key)); - g_snprintf (buf, len, - "wireguard" - "%s%s" /* public-key */ - "%s" /* private-key */ - " listen-port %u" - " fwmark 0x%x", - public_b64 - ? " public-key " - : "", - public_b64 ?: "", - nm_utils_memeqzero_secret (lnk->private_key, sizeof (lnk->private_key)) - ? "" - : " private-key (hidden)", - lnk->listen_port, - lnk->fwmark); + g_snprintf(buf, + len, + "wireguard" + "%s%s" /* public-key */ + "%s" /* private-key */ + " listen-port %u" + " fwmark 0x%x", + public_b64 ? " public-key " : "", + public_b64 ?: "", + nm_utils_memeqzero_secret(lnk->private_key, sizeof(lnk->private_key)) + ? "" + : " private-key (hidden)", + lnk->listen_port, + lnk->fwmark); - return buf; + return buf; } /** @@ -5857,126 +6198,140 @@ nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *bu * Returns: a string representation of the address. */ const char * -nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len) -{ - char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; - char s_address[INET_ADDRSTRLEN]; - char s_peer[INET_ADDRSTRLEN]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char str_label[32]; - char str_lft[30], str_pref[30], str_time[50], s_source[50]; - char *str_peer = NULL; - const char *str_lft_p, *str_pref_p, *str_time_p; - gint32 now = nm_utils_get_monotonic_timestamp_sec (); - in_addr_t broadcast_address; - char str_broadcast[INET_ADDRSTRLEN]; - - if (!nm_utils_to_string_buffer_init_null (address, &buf, &len)) - return buf; - - inet_ntop (AF_INET, &address->address, s_address, sizeof (s_address)); - - if (address->peer_address != address->address) { - inet_ntop (AF_INET, &address->peer_address, s_peer, sizeof (s_peer)); - str_peer = g_strconcat (" ptp ", s_peer, NULL); - } - - _to_string_dev (NULL, address->ifindex, str_dev, sizeof (str_dev)); - - if (*address->label) - g_snprintf (str_label, sizeof (str_label), " label %s", address->label); - else - str_label[0] = 0; - - str_lft_p = _lifetime_to_string (address->timestamp, - address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT, - now, str_lft, sizeof (str_lft)), - str_pref_p = (address->lifetime == address->preferred) - ? str_lft_p - : ( _lifetime_to_string (address->timestamp, - address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT, - now, str_pref, sizeof (str_pref)) ); - str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); - - broadcast_address = nm_platform_ip4_broadcast_address_from_addr (address); - - g_snprintf (buf, len, - "%s/%d" - "%s%s" /* broadcast */ - " lft %s" - " pref %s" - "%s" /* time */ - "%s" /* peer */ - "%s" /* dev */ - "%s" /* flags */ - "%s" /* label */ - " src %s" - "%s" /* external */ - "", - s_address, address->plen, - broadcast_address ? " brd " : "", - broadcast_address ? nm_utils_inet4_ntop (broadcast_address, str_broadcast) : "", - str_lft_p, - str_pref_p, - str_time_p, - str_peer ?: "", - str_dev, - _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), - str_label, - nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source)), - address->external ? " ext" : ""); - g_free (str_peer); - return buf; -} - -NM_UTILS_FLAGS2STR_DEFINE (nm_platform_link_flags2str, unsigned, - NM_UTILS_FLAGS2STR (IFF_LOOPBACK, "loopback"), - NM_UTILS_FLAGS2STR (IFF_BROADCAST, "broadcast"), - NM_UTILS_FLAGS2STR (IFF_POINTOPOINT, "pointopoint"), - NM_UTILS_FLAGS2STR (IFF_MULTICAST, "multicast"), - NM_UTILS_FLAGS2STR (IFF_NOARP, "noarp"), - NM_UTILS_FLAGS2STR (IFF_ALLMULTI, "allmulti"), - NM_UTILS_FLAGS2STR (IFF_PROMISC, "promisc"), - NM_UTILS_FLAGS2STR (IFF_MASTER, "master"), - NM_UTILS_FLAGS2STR (IFF_SLAVE, "slave"), - NM_UTILS_FLAGS2STR (IFF_DEBUG, "debug"), - NM_UTILS_FLAGS2STR (IFF_DYNAMIC, "dynamic"), - NM_UTILS_FLAGS2STR (IFF_AUTOMEDIA, "automedia"), - NM_UTILS_FLAGS2STR (IFF_PORTSEL, "portsel"), - NM_UTILS_FLAGS2STR (IFF_NOTRAILERS, "notrailers"), - NM_UTILS_FLAGS2STR (IFF_UP, "up"), - NM_UTILS_FLAGS2STR (IFF_RUNNING, "running"), - NM_UTILS_FLAGS2STR (IFF_LOWER_UP, "lowerup"), - NM_UTILS_FLAGS2STR (IFF_DORMANT, "dormant"), - NM_UTILS_FLAGS2STR (IFF_ECHO, "echo"), -); - -NM_UTILS_ENUM2STR_DEFINE (nm_platform_link_inet6_addrgenmode2str, guint8, - NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_NONE, "none"), - NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"), - NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"), - NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_RANDOM, "random"), -); - -NM_UTILS_FLAGS2STR_DEFINE (nm_platform_addr_flags2str, unsigned, - NM_UTILS_FLAGS2STR (IFA_F_SECONDARY, "secondary"), - NM_UTILS_FLAGS2STR (IFA_F_NODAD, "nodad"), - NM_UTILS_FLAGS2STR (IFA_F_OPTIMISTIC, "optimistic"), - NM_UTILS_FLAGS2STR (IFA_F_HOMEADDRESS, "homeaddress"), - NM_UTILS_FLAGS2STR (IFA_F_DEPRECATED, "deprecated"), - NM_UTILS_FLAGS2STR (IFA_F_PERMANENT, "permanent"), - NM_UTILS_FLAGS2STR (IFA_F_MANAGETEMPADDR, "mngtmpaddr"), - NM_UTILS_FLAGS2STR (IFA_F_NOPREFIXROUTE, "noprefixroute"), - NM_UTILS_FLAGS2STR (IFA_F_TENTATIVE, "tentative"), -); - -NM_UTILS_ENUM2STR_DEFINE (nm_platform_route_scope2str, int, - NM_UTILS_ENUM2STR (RT_SCOPE_NOWHERE, "nowhere"), - NM_UTILS_ENUM2STR (RT_SCOPE_HOST, "host"), - NM_UTILS_ENUM2STR (RT_SCOPE_LINK, "link"), - NM_UTILS_ENUM2STR (RT_SCOPE_SITE, "site"), - NM_UTILS_ENUM2STR (RT_SCOPE_UNIVERSE, "global"), -); +nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len) +{ + char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; + char s_address[INET_ADDRSTRLEN]; + char s_peer[INET_ADDRSTRLEN]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char str_label[32]; + char str_lft[30], str_pref[30], str_time[50], s_source[50]; + char * str_peer = NULL; + const char *str_lft_p, *str_pref_p, *str_time_p; + gint32 now = nm_utils_get_monotonic_timestamp_sec(); + in_addr_t broadcast_address; + char str_broadcast[INET_ADDRSTRLEN]; + + if (!nm_utils_to_string_buffer_init_null(address, &buf, &len)) + return buf; + + inet_ntop(AF_INET, &address->address, s_address, sizeof(s_address)); + + if (address->peer_address != address->address) { + inet_ntop(AF_INET, &address->peer_address, s_peer, sizeof(s_peer)); + str_peer = g_strconcat(" ptp ", s_peer, NULL); + } + + _to_string_dev(NULL, address->ifindex, str_dev, sizeof(str_dev)); + + if (*address->label) + g_snprintf(str_label, sizeof(str_label), " label %s", address->label); + else + str_label[0] = 0; + + str_lft_p = _lifetime_to_string(address->timestamp, + address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT, + now, + str_lft, + sizeof(str_lft)), + str_pref_p = + (address->lifetime == address->preferred) + ? str_lft_p + : (_lifetime_to_string(address->timestamp, + address->lifetime ? MIN(address->preferred, address->lifetime) + : NM_PLATFORM_LIFETIME_PERMANENT, + now, + str_pref, + sizeof(str_pref))); + str_time_p = _lifetime_summary_to_string(now, + address->timestamp, + address->preferred, + address->lifetime, + str_time, + sizeof(str_time)); + + broadcast_address = nm_platform_ip4_broadcast_address_from_addr(address); + + g_snprintf( + buf, + len, + "%s/%d" + "%s%s" /* broadcast */ + " lft %s" + " pref %s" + "%s" /* time */ + "%s" /* peer */ + "%s" /* dev */ + "%s" /* flags */ + "%s" /* label */ + " src %s" + "%s" /* external */ + "", + s_address, + address->plen, + broadcast_address ? " brd " : "", + broadcast_address ? _nm_utils_inet4_ntop(broadcast_address, str_broadcast) : "", + str_lft_p, + str_pref_p, + str_time_p, + str_peer ?: "", + str_dev, + _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)), + str_label, + nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)), + address->external ? " ext" : ""); + g_free(str_peer); + return buf; +} + +NM_UTILS_FLAGS2STR_DEFINE(nm_platform_link_flags2str, + unsigned, + NM_UTILS_FLAGS2STR(IFF_LOOPBACK, "loopback"), + NM_UTILS_FLAGS2STR(IFF_BROADCAST, "broadcast"), + NM_UTILS_FLAGS2STR(IFF_POINTOPOINT, "pointopoint"), + NM_UTILS_FLAGS2STR(IFF_MULTICAST, "multicast"), + NM_UTILS_FLAGS2STR(IFF_NOARP, "noarp"), + NM_UTILS_FLAGS2STR(IFF_ALLMULTI, "allmulti"), + NM_UTILS_FLAGS2STR(IFF_PROMISC, "promisc"), + NM_UTILS_FLAGS2STR(IFF_MASTER, "master"), + NM_UTILS_FLAGS2STR(IFF_SLAVE, "slave"), + NM_UTILS_FLAGS2STR(IFF_DEBUG, "debug"), + NM_UTILS_FLAGS2STR(IFF_DYNAMIC, "dynamic"), + NM_UTILS_FLAGS2STR(IFF_AUTOMEDIA, "automedia"), + NM_UTILS_FLAGS2STR(IFF_PORTSEL, "portsel"), + NM_UTILS_FLAGS2STR(IFF_NOTRAILERS, "notrailers"), + NM_UTILS_FLAGS2STR(IFF_UP, "up"), + NM_UTILS_FLAGS2STR(IFF_RUNNING, "running"), + NM_UTILS_FLAGS2STR(IFF_LOWER_UP, "lowerup"), + NM_UTILS_FLAGS2STR(IFF_DORMANT, "dormant"), + NM_UTILS_FLAGS2STR(IFF_ECHO, "echo"), ); + +NM_UTILS_ENUM2STR_DEFINE(nm_platform_link_inet6_addrgenmode2str, + guint8, + NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_NONE, "none"), + NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"), + NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"), + NM_UTILS_ENUM2STR(NM_IN6_ADDR_GEN_MODE_RANDOM, "random"), ); + +NM_UTILS_FLAGS2STR_DEFINE(nm_platform_addr_flags2str, + unsigned, + NM_UTILS_FLAGS2STR(IFA_F_SECONDARY, "secondary"), + NM_UTILS_FLAGS2STR(IFA_F_NODAD, "nodad"), + NM_UTILS_FLAGS2STR(IFA_F_OPTIMISTIC, "optimistic"), + NM_UTILS_FLAGS2STR(IFA_F_HOMEADDRESS, "homeaddress"), + NM_UTILS_FLAGS2STR(IFA_F_DEPRECATED, "deprecated"), + NM_UTILS_FLAGS2STR(IFA_F_PERMANENT, "permanent"), + NM_UTILS_FLAGS2STR(IFA_F_MANAGETEMPADDR, "mngtmpaddr"), + NM_UTILS_FLAGS2STR(IFA_F_NOPREFIXROUTE, "noprefixroute"), + NM_UTILS_FLAGS2STR(IFA_F_TENTATIVE, "tentative"), ); + +NM_UTILS_ENUM2STR_DEFINE(nm_platform_route_scope2str, + int, + NM_UTILS_ENUM2STR(RT_SCOPE_NOWHERE, "nowhere"), + NM_UTILS_ENUM2STR(RT_SCOPE_HOST, "host"), + NM_UTILS_ENUM2STR(RT_SCOPE_LINK, "link"), + NM_UTILS_ENUM2STR(RT_SCOPE_SITE, "site"), + NM_UTILS_ENUM2STR(RT_SCOPE_UNIVERSE, "global"), ); /** * nm_platform_ip6_address_to_string: @@ -5991,84 +6346,100 @@ NM_UTILS_ENUM2STR_DEFINE (nm_platform_route_scope2str, int, * Returns: a string representation of the address. */ const char * -nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *buf, gsize len) -{ - char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; - char s_address[INET6_ADDRSTRLEN]; - char s_peer[INET6_ADDRSTRLEN]; - char str_lft[30], str_pref[30], str_time[50], s_source[50]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char *str_peer = NULL; - const char *str_lft_p, *str_pref_p, *str_time_p; - gint32 now = nm_utils_get_monotonic_timestamp_sec (); - - if (!nm_utils_to_string_buffer_init_null (address, &buf, &len)) - return buf; - - inet_ntop (AF_INET6, &address->address, s_address, sizeof (s_address)); - - if (!IN6_IS_ADDR_UNSPECIFIED (&address->peer_address)) { - inet_ntop (AF_INET6, &address->peer_address, s_peer, sizeof (s_peer)); - str_peer = g_strconcat (" ptp ", s_peer, NULL); - } - - _to_string_dev (NULL, address->ifindex, str_dev, sizeof (str_dev)); - - str_lft_p = _lifetime_to_string (address->timestamp, - address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT, - now, str_lft, sizeof (str_lft)), - str_pref_p = (address->lifetime == address->preferred) - ? str_lft_p - : ( _lifetime_to_string (address->timestamp, - address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT, - now, str_pref, sizeof (str_pref)) ); - str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); - - g_snprintf (buf, len, - "%s/%d lft %s pref %s%s%s%s%s src %s%s", - s_address, address->plen, str_lft_p, str_pref_p, str_time_p, - str_peer ?: "", - str_dev, - _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), - nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source)), - address->external ? " ext" : ""); - g_free (str_peer); - return buf; -} - -static -NM_UTILS_FLAGS2STR_DEFINE (_rtm_flags_to_string, unsigned, - NM_UTILS_FLAGS2STR (RTNH_F_DEAD, "dead"), - NM_UTILS_FLAGS2STR (RTNH_F_PERVASIVE, "pervasive"), - NM_UTILS_FLAGS2STR (RTNH_F_ONLINK, "onlink"), - NM_UTILS_FLAGS2STR (8 /*RTNH_F_OFFLOAD*/, "offload"), - NM_UTILS_FLAGS2STR (16 /*RTNH_F_LINKDOWN*/, "linkdown"), - NM_UTILS_FLAGS2STR (32 /*RTNH_F_UNRESOLVED*/, "unresolved"), - - NM_UTILS_FLAGS2STR (RTM_F_NOTIFY, "notify"), - NM_UTILS_FLAGS2STR (RTM_F_CLONED, "cloned"), - NM_UTILS_FLAGS2STR (RTM_F_EQUALIZE, "equalize"), - NM_UTILS_FLAGS2STR (RTM_F_PREFIX, "prefix"), - NM_UTILS_FLAGS2STR (0x1000 /*RTM_F_LOOKUP_TABLE*/, "lookup-table"), - NM_UTILS_FLAGS2STR (0x2000 /*RTM_F_FIB_MATCH*/, "fib-match"), -); +nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len) +{ + char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; + char s_address[INET6_ADDRSTRLEN]; + char s_peer[INET6_ADDRSTRLEN]; + char str_lft[30], str_pref[30], str_time[50], s_source[50]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char * str_peer = NULL; + const char *str_lft_p, *str_pref_p, *str_time_p; + gint32 now = nm_utils_get_monotonic_timestamp_sec(); + + if (!nm_utils_to_string_buffer_init_null(address, &buf, &len)) + return buf; + + inet_ntop(AF_INET6, &address->address, s_address, sizeof(s_address)); + + if (!IN6_IS_ADDR_UNSPECIFIED(&address->peer_address)) { + inet_ntop(AF_INET6, &address->peer_address, s_peer, sizeof(s_peer)); + str_peer = g_strconcat(" ptp ", s_peer, NULL); + } + + _to_string_dev(NULL, address->ifindex, str_dev, sizeof(str_dev)); + + str_lft_p = _lifetime_to_string(address->timestamp, + address->lifetime ?: NM_PLATFORM_LIFETIME_PERMANENT, + now, + str_lft, + sizeof(str_lft)), + str_pref_p = + (address->lifetime == address->preferred) + ? str_lft_p + : (_lifetime_to_string(address->timestamp, + address->lifetime ? MIN(address->preferred, address->lifetime) + : NM_PLATFORM_LIFETIME_PERMANENT, + now, + str_pref, + sizeof(str_pref))); + str_time_p = _lifetime_summary_to_string(now, + address->timestamp, + address->preferred, + address->lifetime, + str_time, + sizeof(str_time)); + + g_snprintf( + buf, + len, + "%s/%d lft %s pref %s%s%s%s%s src %s%s", + s_address, + address->plen, + str_lft_p, + str_pref_p, + str_time_p, + str_peer ?: "", + str_dev, + _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)), + nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)), + address->external ? " ext" : ""); + g_free(str_peer); + return buf; +} + +static NM_UTILS_FLAGS2STR_DEFINE(_rtm_flags_to_string, + unsigned, + NM_UTILS_FLAGS2STR(RTNH_F_DEAD, "dead"), + NM_UTILS_FLAGS2STR(RTNH_F_PERVASIVE, "pervasive"), + NM_UTILS_FLAGS2STR(RTNH_F_ONLINK, "onlink"), + NM_UTILS_FLAGS2STR(8 /*RTNH_F_OFFLOAD*/, "offload"), + NM_UTILS_FLAGS2STR(16 /*RTNH_F_LINKDOWN*/, "linkdown"), + NM_UTILS_FLAGS2STR(32 /*RTNH_F_UNRESOLVED*/, "unresolved"), + + NM_UTILS_FLAGS2STR(RTM_F_NOTIFY, "notify"), + NM_UTILS_FLAGS2STR(RTM_F_CLONED, "cloned"), + NM_UTILS_FLAGS2STR(RTM_F_EQUALIZE, "equalize"), + NM_UTILS_FLAGS2STR(RTM_F_PREFIX, "prefix"), + NM_UTILS_FLAGS2STR(0x1000 /*RTM_F_LOOKUP_TABLE*/, "lookup-table"), + NM_UTILS_FLAGS2STR(0x2000 /*RTM_F_FIB_MATCH*/, "fib-match"), ); #define _RTM_FLAGS_TO_STRING_MAXLEN 200 static const char * -_rtm_flags_to_string_full (char *buf, gsize buf_size, unsigned rtm_flags) +_rtm_flags_to_string_full(char *buf, gsize buf_size, unsigned rtm_flags) { - const char *buf0 = buf; + const char *buf0 = buf; - nm_assert (buf_size >= _RTM_FLAGS_TO_STRING_MAXLEN); + nm_assert(buf_size >= _RTM_FLAGS_TO_STRING_MAXLEN); - if (!rtm_flags) - return ""; + if (!rtm_flags) + return ""; - nm_utils_strbuf_append_str (&buf, &buf_size, " rtm_flags "); - _rtm_flags_to_string (rtm_flags, buf, buf_size); - nm_assert (strlen (buf) < buf_size); - return buf0; + nm_utils_strbuf_append_str(&buf, &buf_size, " rtm_flags "); + _rtm_flags_to_string(rtm_flags, buf, buf_size); + nm_assert(strlen(buf) < buf_size); + return buf0; } /** @@ -6084,65 +6455,101 @@ _rtm_flags_to_string_full (char *buf, gsize buf_size, unsigned rtm_flags) * Returns: a string representation of the route. */ const char * -nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsize len) -{ - char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN]; - char s_pref_src[INET_ADDRSTRLEN]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char str_table[30]; - char str_scope[30], s_source[50]; - char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32]; - char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; - char str_type[30]; - - if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) - return buf; - - inet_ntop (AF_INET, &route->network, s_network, sizeof(s_network)); - inet_ntop (AF_INET, &route->gateway, s_gateway, sizeof(s_gateway)); - - _to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev)); - - g_snprintf (buf, len, - "type %s " /* type */ - "%s" /* table */ - "%s/%d" - " via %s" - "%s" - " metric %"G_GUINT32_FORMAT - " mss %"G_GUINT32_FORMAT - " rt-src %s" /* protocol */ - "%s" /* rtm_flags */ - "%s%s" /* scope */ - "%s%s" /* pref-src */ - "%s" /* tos */ - "%s" /* window */ - "%s" /* cwnd */ - "%s" /* initcwnd */ - "%s" /* initrwnd */ - "%s" /* mtu */ - "", - nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), str_type, sizeof (str_type)), - route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "", - s_network, - route->plen, - s_gateway, - str_dev, - route->metric, - route->mss, - nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)), - _rtm_flags_to_string_full (str_rtm_flags, sizeof (str_rtm_flags), route->r_rtm_flags), - route->scope_inv ? " scope " : "", - route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "", - route->pref_src ? " pref-src " : "", - route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "", - route->tos ? nm_sprintf_buf (str_tos, " tos 0x%x", (unsigned) route->tos) : "", - route->window || route->lock_window ? nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window) : "", - route->cwnd || route->lock_cwnd ? nm_sprintf_buf (str_cwnd, " cwnd %s%"G_GUINT32_FORMAT, route->lock_cwnd ? "lock " : "", route->cwnd) : "", - route->initcwnd || route->lock_initcwnd ? nm_sprintf_buf (str_initcwnd, " initcwnd %s%"G_GUINT32_FORMAT, route->lock_initcwnd ? "lock " : "", route->initcwnd) : "", - route->initrwnd || route->lock_initrwnd ? nm_sprintf_buf (str_initrwnd, " initrwnd %s%"G_GUINT32_FORMAT, route->lock_initrwnd ? "lock " : "", route->initrwnd) : "", - route->mtu || route->lock_mtu ? nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu) : ""); - return buf; +nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsize len) +{ + char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN]; + char s_pref_src[INET_ADDRSTRLEN]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char str_table[30]; + char str_scope[30], s_source[50]; + char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32]; + char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; + char str_type[30]; + char str_metric[30]; + + if (!nm_utils_to_string_buffer_init_null(route, &buf, &len)) + return buf; + + inet_ntop(AF_INET, &route->network, s_network, sizeof(s_network)); + inet_ntop(AF_INET, &route->gateway, s_gateway, sizeof(s_gateway)); + + _to_string_dev(NULL, route->ifindex, str_dev, sizeof(str_dev)); + + g_snprintf( + buf, + len, + "type %s " /* type */ + "%s" /* table */ + "%s/%d" + " via %s" + "%s" + " metric %s" + " mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */ + "%s" /* rtm_flags */ + "%s%s" /* scope */ + "%s%s" /* pref-src */ + "%s" /* tos */ + "%s" /* window */ + "%s" /* cwnd */ + "%s" /* initcwnd */ + "%s" /* initrwnd */ + "%s" /* mtu */ + "", + nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced), + str_type, + sizeof(str_type)), + route->table_any + ? "table ?? " + : (route->table_coerced + ? nm_sprintf_buf(str_table, + "table %u ", + nm_platform_route_table_uncoerce(route->table_coerced, FALSE)) + : ""), + s_network, + route->plen, + s_gateway, + str_dev, + route->metric_any ? "??" : nm_sprintf_buf(str_metric, "%u", route->metric), + route->mss, + nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)), + _rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags), + route->scope_inv ? " scope " : "", + route->scope_inv + ? (nm_platform_route_scope2str(nm_platform_route_scope_inv(route->scope_inv), + str_scope, + sizeof(str_scope))) + : "", + route->pref_src ? " pref-src " : "", + route->pref_src ? inet_ntop(AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "", + route->tos ? nm_sprintf_buf(str_tos, " tos 0x%x", (unsigned) route->tos) : "", + route->window || route->lock_window ? nm_sprintf_buf(str_window, + " window %s%" G_GUINT32_FORMAT, + route->lock_window ? "lock " : "", + route->window) + : "", + route->cwnd || route->lock_cwnd ? nm_sprintf_buf(str_cwnd, + " cwnd %s%" G_GUINT32_FORMAT, + route->lock_cwnd ? "lock " : "", + route->cwnd) + : "", + route->initcwnd || route->lock_initcwnd + ? nm_sprintf_buf(str_initcwnd, + " initcwnd %s%" G_GUINT32_FORMAT, + route->lock_initcwnd ? "lock " : "", + route->initcwnd) + : "", + route->initrwnd || route->lock_initrwnd + ? nm_sprintf_buf(str_initrwnd, + " initrwnd %s%" G_GUINT32_FORMAT, + route->lock_initrwnd ? "lock " : "", + route->initrwnd) + : "", + route->mtu || route->lock_mtu ? nm_sprintf_buf(str_mtu, + " mtu %s%" G_GUINT32_FORMAT, + route->lock_mtu ? "lock " : "", + route->mtu) + : ""); + return buf; } /** @@ -6158,1673 +6565,1914 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi * Returns: a string representation of the route. */ const char * -nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len) -{ - char s_network[INET6_ADDRSTRLEN]; - char s_gateway[INET6_ADDRSTRLEN]; - char s_pref_src[INET6_ADDRSTRLEN]; - char s_src_all[INET6_ADDRSTRLEN + 40]; - char s_src[INET6_ADDRSTRLEN]; - char str_type[30]; - char str_table[30]; - char str_pref[40]; - char str_pref2[30]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char s_source[50]; - char str_window[32]; - char str_cwnd[32]; - char str_initcwnd[32]; - char str_initrwnd[32]; - char str_mtu[32]; - char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; - - if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) - return buf; - - inet_ntop (AF_INET6, &route->network, s_network, sizeof (s_network)); - inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof (s_gateway)); - - if (IN6_IS_ADDR_UNSPECIFIED (&route->pref_src)) - s_pref_src[0] = 0; - else - inet_ntop (AF_INET6, &route->pref_src, s_pref_src, sizeof (s_pref_src)); - - _to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev)); - - g_snprintf (buf, len, - "type %s " /* type */ - "%s" /* table */ - "%s/%d" - " via %s" - "%s" - " metric %"G_GUINT32_FORMAT - " mss %"G_GUINT32_FORMAT - " rt-src %s" /* protocol */ - "%s" /* source */ - "%s" /* rtm_flags */ - "%s%s" /* pref-src */ - "%s" /* window */ - "%s" /* cwnd */ - "%s" /* initcwnd */ - "%s" /* initrwnd */ - "%s" /* mtu */ - "%s" /* pref */ - "", - nm_utils_route_type2str (nm_platform_route_type_uncoerce (route->type_coerced), str_type, sizeof (str_type)), - route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "", - s_network, - route->plen, - s_gateway, - str_dev, - route->metric, - route->mss, - nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)), - route->src_plen || !IN6_IS_ADDR_UNSPECIFIED (&route->src) - ? nm_sprintf_buf (s_src_all, " src %s/%u", _nm_utils_inet6_ntop (&route->src, s_src), (unsigned) route->src_plen) - : "", - _rtm_flags_to_string_full (str_rtm_flags, sizeof (str_rtm_flags), route->r_rtm_flags), - s_pref_src[0] ? " pref-src " : "", - s_pref_src[0] ? s_pref_src : "", - route->window || route->lock_window ? nm_sprintf_buf (str_window, " window %s%"G_GUINT32_FORMAT, route->lock_window ? "lock " : "", route->window) : "", - route->cwnd || route->lock_cwnd ? nm_sprintf_buf (str_cwnd, " cwnd %s%"G_GUINT32_FORMAT, route->lock_cwnd ? "lock " : "", route->cwnd) : "", - route->initcwnd || route->lock_initcwnd ? nm_sprintf_buf (str_initcwnd, " initcwnd %s%"G_GUINT32_FORMAT, route->lock_initcwnd ? "lock " : "", route->initcwnd) : "", - route->initrwnd || route->lock_initrwnd ? nm_sprintf_buf (str_initrwnd, " initrwnd %s%"G_GUINT32_FORMAT, route->lock_initrwnd ? "lock " : "", route->initrwnd) : "", - route->mtu || route->lock_mtu ? nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu) : "", - route->rt_pref ? nm_sprintf_buf (str_pref, " pref %s", nm_icmpv6_router_pref_to_string (route->rt_pref, str_pref2, sizeof (str_pref2))) : ""); - - return buf; +nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsize len) +{ + char s_network[INET6_ADDRSTRLEN]; + char s_gateway[INET6_ADDRSTRLEN]; + char s_pref_src[INET6_ADDRSTRLEN]; + char s_src_all[INET6_ADDRSTRLEN + 40]; + char s_src[INET6_ADDRSTRLEN]; + char str_type[30]; + char str_table[30]; + char str_pref[40]; + char str_pref2[30]; + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char s_source[50]; + char str_window[32]; + char str_cwnd[32]; + char str_initcwnd[32]; + char str_initrwnd[32]; + char str_mtu[32]; + char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN]; + char str_metric[30]; + + if (!nm_utils_to_string_buffer_init_null(route, &buf, &len)) + return buf; + + inet_ntop(AF_INET6, &route->network, s_network, sizeof(s_network)); + inet_ntop(AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway)); + + if (IN6_IS_ADDR_UNSPECIFIED(&route->pref_src)) + s_pref_src[0] = 0; + else + inet_ntop(AF_INET6, &route->pref_src, s_pref_src, sizeof(s_pref_src)); + + _to_string_dev(NULL, route->ifindex, str_dev, sizeof(str_dev)); + + g_snprintf( + buf, + len, + "type %s " /* type */ + "%s" /* table */ + "%s/%d" + " via %s" + "%s" + " metric %s" + " mss %" G_GUINT32_FORMAT " rt-src %s" /* protocol */ + "%s" /* source */ + "%s" /* rtm_flags */ + "%s%s" /* pref-src */ + "%s" /* window */ + "%s" /* cwnd */ + "%s" /* initcwnd */ + "%s" /* initrwnd */ + "%s" /* mtu */ + "%s" /* pref */ + "", + nm_utils_route_type2str(nm_platform_route_type_uncoerce(route->type_coerced), + str_type, + sizeof(str_type)), + route->table_any + ? "table ?? " + : (route->table_coerced + ? nm_sprintf_buf(str_table, + "table %u ", + nm_platform_route_table_uncoerce(route->table_coerced, FALSE)) + : ""), + s_network, + route->plen, + s_gateway, + str_dev, + route->metric_any ? "??" : nm_sprintf_buf(str_metric, "%u", route->metric), + route->mss, + nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)), + route->src_plen || !IN6_IS_ADDR_UNSPECIFIED(&route->src) + ? nm_sprintf_buf(s_src_all, + " src %s/%u", + _nm_utils_inet6_ntop(&route->src, s_src), + (unsigned) route->src_plen) + : "", + _rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags), + s_pref_src[0] ? " pref-src " : "", + s_pref_src[0] ? s_pref_src : "", + route->window || route->lock_window ? nm_sprintf_buf(str_window, + " window %s%" G_GUINT32_FORMAT, + route->lock_window ? "lock " : "", + route->window) + : "", + route->cwnd || route->lock_cwnd ? nm_sprintf_buf(str_cwnd, + " cwnd %s%" G_GUINT32_FORMAT, + route->lock_cwnd ? "lock " : "", + route->cwnd) + : "", + route->initcwnd || route->lock_initcwnd + ? nm_sprintf_buf(str_initcwnd, + " initcwnd %s%" G_GUINT32_FORMAT, + route->lock_initcwnd ? "lock " : "", + route->initcwnd) + : "", + route->initrwnd || route->lock_initrwnd + ? nm_sprintf_buf(str_initrwnd, + " initrwnd %s%" G_GUINT32_FORMAT, + route->lock_initrwnd ? "lock " : "", + route->initrwnd) + : "", + route->mtu || route->lock_mtu ? nm_sprintf_buf(str_mtu, + " mtu %s%" G_GUINT32_FORMAT, + route->lock_mtu ? "lock " : "", + route->mtu) + : "", + route->rt_pref ? nm_sprintf_buf( + str_pref, + " pref %s", + nm_icmpv6_router_pref_to_string(route->rt_pref, str_pref2, sizeof(str_pref2))) + : ""); + + return buf; } static void -_routing_rule_addr_to_string (char **buf, - gsize *len, - int addr_family, - const NMIPAddr *addr, - guint8 plen, - gboolean is_src) +_routing_rule_addr_to_string(char ** buf, + gsize * len, + int addr_family, + const NMIPAddr *addr, + guint8 plen, + gboolean is_src) { - char s_addr[NM_UTILS_INET_ADDRSTRLEN]; - gboolean is_zero; - gsize addr_size; + char s_addr[NM_UTILS_INET_ADDRSTRLEN]; + gboolean is_zero; + gsize addr_size; - nm_assert_addr_family (addr_family); - nm_assert (addr); + nm_assert_addr_family(addr_family); + nm_assert(addr); - addr_size = nm_utils_addr_family_to_size (addr_family); + addr_size = nm_utils_addr_family_to_size(addr_family); - is_zero = nm_utils_memeqzero (addr, addr_size); + is_zero = nm_utils_memeqzero(addr, addr_size); - if ( plen == 0 - && is_zero) { - if (is_src) - nm_utils_strbuf_append_str (buf, len, " from all"); - else - nm_utils_strbuf_append_str (buf, len, ""); - return; - } + if (plen == 0 && is_zero) { + if (is_src) + nm_utils_strbuf_append_str(buf, len, " from all"); + else + nm_utils_strbuf_append_str(buf, len, ""); + return; + } - nm_utils_strbuf_append_str (buf, len, is_src ? " from " : " to "); + nm_utils_strbuf_append_str(buf, len, is_src ? " from " : " to "); - nm_utils_strbuf_append_str (buf, len, nm_utils_inet_ntop (addr_family, addr, s_addr)); + nm_utils_strbuf_append_str(buf, len, nm_utils_inet_ntop(addr_family, addr, s_addr)); - if (plen != (addr_size * 8)) - nm_utils_strbuf_append (buf, len, "/%u", plen); + if (plen != (addr_size * 8)) + nm_utils_strbuf_append(buf, len, "/%u", plen); } static void -_routing_rule_port_range_to_string (char **buf, - gsize *len, - const NMFibRulePortRange *port_range, - const char *name) +_routing_rule_port_range_to_string(char ** buf, + gsize * len, + const NMFibRulePortRange *port_range, + const char * name) { - if ( port_range->start == 0 - && port_range->end == 0) - nm_utils_strbuf_append_str (buf, len, ""); - else { - nm_utils_strbuf_append (buf, len, " %s %u", name, port_range->start); - if (port_range->start != port_range->end) - nm_utils_strbuf_append (buf, len, "-%u", port_range->end); - } + if (port_range->start == 0 && port_range->end == 0) + nm_utils_strbuf_append_str(buf, len, ""); + else { + nm_utils_strbuf_append(buf, len, " %s %u", name, port_range->start); + if (port_range->start != port_range->end) + nm_utils_strbuf_append(buf, len, "-%u", port_range->end); + } } const char * -nm_platform_routing_rule_to_string (const NMPlatformRoutingRule *routing_rule, char *buf, gsize len) -{ - const char *buf0; - guint32 rr_flags; - - if (!nm_utils_to_string_buffer_init_null (routing_rule, &buf, &len)) - return buf; - - if (!NM_IN_SET (routing_rule->addr_family, AF_INET, AF_INET6)) { - /* invalid addr-family. The other fields are undefined. */ - if (routing_rule->addr_family == AF_UNSPEC) - g_snprintf (buf, len, "[routing-rule]"); - else - g_snprintf (buf, len, "[routing-rule family:%u]", routing_rule->addr_family); - return buf; - } - - buf0 = buf; - - rr_flags = routing_rule->flags; - - rr_flags = NM_FLAGS_UNSET (rr_flags, FIB_RULE_INVERT); - nm_utils_strbuf_append (&buf, &len, - "[%c] " /* addr-family */ - "%u:" /* priority */ - "%s", /* not/FIB_RULE_INVERT */ - nm_utils_addr_family_to_char (routing_rule->addr_family), - routing_rule->priority, - ( NM_FLAGS_HAS (routing_rule->flags, FIB_RULE_INVERT) - ? " not" - : "")); - - _routing_rule_addr_to_string (&buf, &len, - routing_rule->addr_family, - &routing_rule->src, - routing_rule->src_len, - TRUE); - - _routing_rule_addr_to_string (&buf, &len, - routing_rule->addr_family, - &routing_rule->dst, - routing_rule->dst_len, - FALSE); - - if (routing_rule->tos) - nm_utils_strbuf_append (&buf, &len, " tos 0x%02x", routing_rule->tos); - - if ( routing_rule->fwmark != 0 - || routing_rule->fwmask != 0) { - nm_utils_strbuf_append (&buf, &len, " fwmark %#x", (unsigned) routing_rule->fwmark); - if (routing_rule->fwmark != 0xFFFFFFFFu) - nm_utils_strbuf_append (&buf, &len, "/%#x", (unsigned) routing_rule->fwmask); - } - - if (routing_rule->iifname[0]) { - nm_utils_strbuf_append (&buf, &len, " iif %s", routing_rule->iifname); - rr_flags = NM_FLAGS_UNSET (rr_flags, FIB_RULE_IIF_DETACHED); - if (NM_FLAGS_HAS (routing_rule->flags, FIB_RULE_IIF_DETACHED)) - nm_utils_strbuf_append_str (&buf, &len, " [detached]"); - } - - if (routing_rule->oifname[0]) { - nm_utils_strbuf_append (&buf, &len, " oif %s", routing_rule->oifname); - rr_flags = NM_FLAGS_UNSET (rr_flags, FIB_RULE_OIF_DETACHED); - if (NM_FLAGS_HAS (routing_rule->flags, FIB_RULE_OIF_DETACHED)) - nm_utils_strbuf_append_str (&buf, &len, " [detached]"); - } - - if (routing_rule->l3mdev != 0) { - if (routing_rule->l3mdev == 1) - nm_utils_strbuf_append_str (&buf, &len, " lookup [l3mdev-table]"); - else { - nm_utils_strbuf_append (&buf, &len, " lookup [l3mdev-table/%u]", (unsigned) routing_rule->l3mdev); - } - } - - if ( routing_rule->uid_range_has - || routing_rule->uid_range.start - || routing_rule->uid_range.end) { - nm_utils_strbuf_append (&buf, &len, - " uidrange %u-%u%s", - routing_rule->uid_range.start, - routing_rule->uid_range.end, - routing_rule->uid_range_has ? "" : "(?)"); - } - - if (routing_rule->ip_proto != 0) { - /* we don't call getprotobynumber(), just print the numeric value. - * This differs from what ip-rule prints. */ - nm_utils_strbuf_append (&buf, &len, - " ipproto %u", - routing_rule->ip_proto); - } - - _routing_rule_port_range_to_string (&buf, &len, - &routing_rule->sport_range, - "sport"); - - _routing_rule_port_range_to_string (&buf, &len, - &routing_rule->dport_range, - "dport"); - - if (routing_rule->tun_id != 0) { - nm_utils_strbuf_append (&buf, &len, - " tun_id %"G_GUINT64_FORMAT, - routing_rule->tun_id); - } - - if (routing_rule->table != 0) { - nm_utils_strbuf_append (&buf, &len, - " lookup %u", - routing_rule->table); - } - - if (routing_rule->suppress_prefixlen_inverse != 0) { - nm_utils_strbuf_append (&buf, &len, - " suppress_prefixlen %d", - (int) (~routing_rule->suppress_prefixlen_inverse)); - } - - if (routing_rule->suppress_ifgroup_inverse != 0) { - nm_utils_strbuf_append (&buf, &len, - " suppress_ifgroup %d", - (int) (~routing_rule->suppress_ifgroup_inverse)); - } - - if (routing_rule->flow) { - /* FRA_FLOW is only for IPv4, but we want to print the value for all address-families, - * to see when it is set. In practice, this should not be set except for IPv4. - * - * We don't follow the style how ip-rule prints flow/realms. It's confusing. Just - * print the value hex. */ - nm_utils_strbuf_append (&buf, &len, - " realms 0x%08x", - routing_rule->flow); - } - - if (routing_rule->action == RTN_NAT) { - G_STATIC_ASSERT_EXPR (RTN_NAT == 10); - - /* NAT is deprecated for many years. We don't support RTA_GATEWAY/FRA_UNUSED2 - * for the gateway, and so do recent kernels ignore that parameter. */ - nm_utils_strbuf_append_str (&buf, &len, " masquerade"); - } else if (routing_rule->action == FR_ACT_GOTO) { - if (routing_rule->goto_target != 0) - nm_utils_strbuf_append (&buf, &len, " goto %u", routing_rule->goto_target); - else - nm_utils_strbuf_append_str (&buf, &len, " goto none"); - rr_flags = NM_FLAGS_UNSET (rr_flags, FIB_RULE_UNRESOLVED); - if (NM_FLAGS_HAS (routing_rule->flags, FIB_RULE_UNRESOLVED)) - nm_utils_strbuf_append_str (&buf, &len, " unresolved"); - } else if (routing_rule->action != FR_ACT_TO_TBL) { - const char *ss; - char ss_buf[60]; - -#define _V(v1, v2) ((sizeof (char[(((int) (v1)) == ((int) (v2))) ? 1 : -1]) * 0) + (v1)) - switch (routing_rule->action) { - case _V (FR_ACT_UNSPEC, RTN_UNSPEC) : ss = "none"; break; - case _V (FR_ACT_TO_TBL, RTN_UNICAST) : ss = "unicast"; break; - case _V (FR_ACT_GOTO, RTN_LOCAL) : ss = "local"; break; - case _V (FR_ACT_NOP, RTN_BROADCAST) : ss = "nop"; break; - case _V (FR_ACT_RES3, RTN_ANYCAST) : ss = "anycast"; break; - case _V (FR_ACT_RES4, RTN_MULTICAST) : ss = "multicast"; break; - case _V (FR_ACT_BLACKHOLE, RTN_BLACKHOLE) : ss = "blackhole"; break; - case _V (FR_ACT_UNREACHABLE, RTN_UNREACHABLE) : ss = "unreachable"; break; - case _V (FR_ACT_PROHIBIT, RTN_PROHIBIT) : ss = "prohibit"; break; - case RTN_THROW : ss = "throw"; break; - case RTN_NAT : ss = "nat"; break; - case RTN_XRESOLVE : ss = "xresolve"; break; - default: - ss = nm_sprintf_buf (ss_buf, "action-%u", routing_rule->action); - break; - } +nm_platform_routing_rule_to_string(const NMPlatformRoutingRule *routing_rule, char *buf, gsize len) +{ + const char *buf0; + guint32 rr_flags; + + if (!nm_utils_to_string_buffer_init_null(routing_rule, &buf, &len)) + return buf; + + if (!NM_IN_SET(routing_rule->addr_family, AF_INET, AF_INET6)) { + /* invalid addr-family. The other fields are undefined. */ + if (routing_rule->addr_family == AF_UNSPEC) + g_snprintf(buf, len, "[routing-rule]"); + else + g_snprintf(buf, len, "[routing-rule family:%u]", routing_rule->addr_family); + return buf; + } + + buf0 = buf; + + rr_flags = routing_rule->flags; + + rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_INVERT); + nm_utils_strbuf_append(&buf, + &len, + "[%c] " /* addr-family */ + "%u:" /* priority */ + "%s", /* not/FIB_RULE_INVERT */ + nm_utils_addr_family_to_char(routing_rule->addr_family), + routing_rule->priority, + (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_INVERT) ? " not" : "")); + + _routing_rule_addr_to_string(&buf, + &len, + routing_rule->addr_family, + &routing_rule->src, + routing_rule->src_len, + TRUE); + + _routing_rule_addr_to_string(&buf, + &len, + routing_rule->addr_family, + &routing_rule->dst, + routing_rule->dst_len, + FALSE); + + if (routing_rule->tos) + nm_utils_strbuf_append(&buf, &len, " tos 0x%02x", routing_rule->tos); + + if (routing_rule->fwmark != 0 || routing_rule->fwmask != 0) { + nm_utils_strbuf_append(&buf, &len, " fwmark %#x", (unsigned) routing_rule->fwmark); + if (routing_rule->fwmark != 0xFFFFFFFFu) + nm_utils_strbuf_append(&buf, &len, "/%#x", (unsigned) routing_rule->fwmask); + } + + if (routing_rule->iifname[0]) { + nm_utils_strbuf_append(&buf, &len, " iif %s", routing_rule->iifname); + rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_IIF_DETACHED); + if (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_IIF_DETACHED)) + nm_utils_strbuf_append_str(&buf, &len, " [detached]"); + } + + if (routing_rule->oifname[0]) { + nm_utils_strbuf_append(&buf, &len, " oif %s", routing_rule->oifname); + rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_OIF_DETACHED); + if (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_OIF_DETACHED)) + nm_utils_strbuf_append_str(&buf, &len, " [detached]"); + } + + if (routing_rule->l3mdev != 0) { + if (routing_rule->l3mdev == 1) + nm_utils_strbuf_append_str(&buf, &len, " lookup [l3mdev-table]"); + else { + nm_utils_strbuf_append(&buf, + &len, + " lookup [l3mdev-table/%u]", + (unsigned) routing_rule->l3mdev); + } + } + + if (routing_rule->uid_range_has || routing_rule->uid_range.start + || routing_rule->uid_range.end) { + nm_utils_strbuf_append(&buf, + &len, + " uidrange %u-%u%s", + routing_rule->uid_range.start, + routing_rule->uid_range.end, + routing_rule->uid_range_has ? "" : "(?)"); + } + + if (routing_rule->ip_proto != 0) { + /* we don't call getprotobynumber(), just print the numeric value. + * This differs from what ip-rule prints. */ + nm_utils_strbuf_append(&buf, &len, " ipproto %u", routing_rule->ip_proto); + } + + _routing_rule_port_range_to_string(&buf, &len, &routing_rule->sport_range, "sport"); + + _routing_rule_port_range_to_string(&buf, &len, &routing_rule->dport_range, "dport"); + + if (routing_rule->tun_id != 0) { + nm_utils_strbuf_append(&buf, &len, " tun_id %" G_GUINT64_FORMAT, routing_rule->tun_id); + } + + if (routing_rule->table != 0) { + nm_utils_strbuf_append(&buf, &len, " lookup %u", routing_rule->table); + } + + if (routing_rule->suppress_prefixlen_inverse != 0) { + nm_utils_strbuf_append(&buf, + &len, + " suppress_prefixlen %d", + (int) (~routing_rule->suppress_prefixlen_inverse)); + } + + if (routing_rule->suppress_ifgroup_inverse != 0) { + nm_utils_strbuf_append(&buf, + &len, + " suppress_ifgroup %d", + (int) (~routing_rule->suppress_ifgroup_inverse)); + } + + if (routing_rule->flow) { + /* FRA_FLOW is only for IPv4, but we want to print the value for all address-families, + * to see when it is set. In practice, this should not be set except for IPv4. + * + * We don't follow the style how ip-rule prints flow/realms. It's confusing. Just + * print the value hex. */ + nm_utils_strbuf_append(&buf, &len, " realms 0x%08x", routing_rule->flow); + } + + if (routing_rule->action == RTN_NAT) { + G_STATIC_ASSERT_EXPR(RTN_NAT == 10); + + /* NAT is deprecated for many years. We don't support RTA_GATEWAY/FRA_UNUSED2 + * for the gateway, and so do recent kernels ignore that parameter. */ + nm_utils_strbuf_append_str(&buf, &len, " masquerade"); + } else if (routing_rule->action == FR_ACT_GOTO) { + if (routing_rule->goto_target != 0) + nm_utils_strbuf_append(&buf, &len, " goto %u", routing_rule->goto_target); + else + nm_utils_strbuf_append_str(&buf, &len, " goto none"); + rr_flags = NM_FLAGS_UNSET(rr_flags, FIB_RULE_UNRESOLVED); + if (NM_FLAGS_HAS(routing_rule->flags, FIB_RULE_UNRESOLVED)) + nm_utils_strbuf_append_str(&buf, &len, " unresolved"); + } else if (routing_rule->action != FR_ACT_TO_TBL) { + const char *ss; + char ss_buf[60]; + +#define _V(v1, v2) ((sizeof(char[(((int) (v1)) == ((int) (v2))) ? 1 : -1]) * 0) + (v1)) + switch (routing_rule->action) { + case _V(FR_ACT_UNSPEC, RTN_UNSPEC): + ss = "none"; + break; + case _V(FR_ACT_TO_TBL, RTN_UNICAST): + ss = "unicast"; + break; + case _V(FR_ACT_GOTO, RTN_LOCAL): + ss = "local"; + break; + case _V(FR_ACT_NOP, RTN_BROADCAST): + ss = "nop"; + break; + case _V(FR_ACT_RES3, RTN_ANYCAST): + ss = "anycast"; + break; + case _V(FR_ACT_RES4, RTN_MULTICAST): + ss = "multicast"; + break; + case _V(FR_ACT_BLACKHOLE, RTN_BLACKHOLE): + ss = "blackhole"; + break; + case _V(FR_ACT_UNREACHABLE, RTN_UNREACHABLE): + ss = "unreachable"; + break; + case _V(FR_ACT_PROHIBIT, RTN_PROHIBIT): + ss = "prohibit"; + break; + case RTN_THROW: + ss = "throw"; + break; + case RTN_NAT: + ss = "nat"; + break; + case RTN_XRESOLVE: + ss = "xresolve"; + break; + default: + ss = nm_sprintf_buf(ss_buf, "action-%u", routing_rule->action); + break; + } #undef _V - nm_utils_strbuf_append (&buf, &len, " %s", ss); - } + nm_utils_strbuf_append(&buf, &len, " %s", ss); + } - if (routing_rule->protocol != RTPROT_UNSPEC) - nm_utils_strbuf_append (&buf, &len, " protocol %u", routing_rule->protocol); + if (routing_rule->protocol != RTPROT_UNSPEC) + nm_utils_strbuf_append(&buf, &len, " protocol %u", routing_rule->protocol); - if ( routing_rule->goto_target != 0 - && routing_rule->action != FR_ACT_GOTO) { - /* a trailing target is set for an unexpected action. Print it. */ - nm_utils_strbuf_append (&buf, &len, " goto-target %u", routing_rule->goto_target); - } + if (routing_rule->goto_target != 0 && routing_rule->action != FR_ACT_GOTO) { + /* a trailing target is set for an unexpected action. Print it. */ + nm_utils_strbuf_append(&buf, &len, " goto-target %u", routing_rule->goto_target); + } - if (rr_flags != 0) { - /* we have some flags we didn't print about yet. */ - nm_utils_strbuf_append (&buf, &len, " remaining-flags %x", rr_flags); - } + if (rr_flags != 0) { + /* we have some flags we didn't print about yet. */ + nm_utils_strbuf_append(&buf, &len, " remaining-flags %x", rr_flags); + } - return buf0; + return buf0; } const char * -nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len) -{ - char str_dev[TO_STRING_DEV_BUF_SIZE]; - const char *buf0; - - if (!nm_utils_to_string_buffer_init_null (qdisc, &buf, &len)) - return buf; - - buf0 = buf; - - nm_utils_strbuf_append (&buf, &len, "%s%s family %u handle %x parent %x info %x", - qdisc->kind, - _to_string_dev (NULL, qdisc->ifindex, str_dev, sizeof (str_dev)), - qdisc->addr_family, - qdisc->handle, - qdisc->parent, - qdisc->info); - - if (nm_streq0 (qdisc->kind, "fq_codel")) { - if (qdisc->fq_codel.limit) - nm_utils_strbuf_append (&buf, &len, " limit %u", qdisc->fq_codel.limit); - if (qdisc->fq_codel.flows) - nm_utils_strbuf_append (&buf, &len, " flows %u", qdisc->fq_codel.flows); - if (qdisc->fq_codel.target) - nm_utils_strbuf_append (&buf, &len, " target %u", qdisc->fq_codel.target); - if (qdisc->fq_codel.interval) - nm_utils_strbuf_append (&buf, &len, " interval %u", qdisc->fq_codel.interval); - if (qdisc->fq_codel.quantum) - nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->fq_codel.quantum); - if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) - nm_utils_strbuf_append (&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold); - if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) - nm_utils_strbuf_append (&buf, &len, " memory_limit %u", qdisc->fq_codel.memory_limit); - if (qdisc->fq_codel.ecn) - nm_utils_strbuf_append (&buf, &len, " ecn"); - } else if (nm_streq0 (qdisc->kind, "sfq")) { - if (qdisc->sfq.quantum) - nm_utils_strbuf_append (&buf, &len, " quantum %u", qdisc->sfq.quantum); - if (qdisc->sfq.perturb_period) - nm_utils_strbuf_append (&buf, &len, " perturb %d", qdisc->sfq.perturb_period); - if (qdisc->sfq.limit) - nm_utils_strbuf_append (&buf, &len, " limit %u", (guint) qdisc->sfq.limit); - if (qdisc->sfq.divisor) - nm_utils_strbuf_append (&buf, &len, " divisor %u", qdisc->sfq.divisor); - if (qdisc->sfq.flows) - nm_utils_strbuf_append (&buf, &len, " flows %u", qdisc->sfq.flows); - if (qdisc->sfq.depth) - nm_utils_strbuf_append (&buf, &len, " depth %u", qdisc->sfq.depth); - } else if (nm_streq0 (qdisc->kind, "tbf")) { - nm_utils_strbuf_append (&buf, &len, " rate %"G_GUINT64_FORMAT, qdisc->tbf.rate); - nm_utils_strbuf_append (&buf, &len, " burst %u", qdisc->tbf.burst); - if (qdisc->tbf.limit) - nm_utils_strbuf_append (&buf, &len, " limit %u", qdisc->tbf.limit); - if (qdisc->tbf.latency) - nm_utils_strbuf_append (&buf, &len, " latency %uns", qdisc->tbf.latency); - } - - return buf0; +nm_platform_qdisc_to_string(const NMPlatformQdisc *qdisc, char *buf, gsize len) +{ + char str_dev[TO_STRING_DEV_BUF_SIZE]; + const char *buf0; + + if (!nm_utils_to_string_buffer_init_null(qdisc, &buf, &len)) + return buf; + + buf0 = buf; + + nm_utils_strbuf_append(&buf, + &len, + "%s%s family %u handle %x parent %x info %x", + qdisc->kind, + _to_string_dev(NULL, qdisc->ifindex, str_dev, sizeof(str_dev)), + qdisc->addr_family, + qdisc->handle, + qdisc->parent, + qdisc->info); + + if (nm_streq0(qdisc->kind, "fq_codel")) { + if (qdisc->fq_codel.limit) + nm_utils_strbuf_append(&buf, &len, " limit %u", qdisc->fq_codel.limit); + if (qdisc->fq_codel.flows) + nm_utils_strbuf_append(&buf, &len, " flows %u", qdisc->fq_codel.flows); + if (qdisc->fq_codel.target) + nm_utils_strbuf_append(&buf, &len, " target %u", qdisc->fq_codel.target); + if (qdisc->fq_codel.interval) + nm_utils_strbuf_append(&buf, &len, " interval %u", qdisc->fq_codel.interval); + if (qdisc->fq_codel.quantum) + nm_utils_strbuf_append(&buf, &len, " quantum %u", qdisc->fq_codel.quantum); + if (qdisc->fq_codel.ce_threshold != NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) + nm_utils_strbuf_append(&buf, &len, " ce_threshold %u", qdisc->fq_codel.ce_threshold); + if (qdisc->fq_codel.memory_limit != NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET) + nm_utils_strbuf_append(&buf, &len, " memory_limit %u", qdisc->fq_codel.memory_limit); + if (qdisc->fq_codel.ecn) + nm_utils_strbuf_append(&buf, &len, " ecn"); + } else if (nm_streq0(qdisc->kind, "sfq")) { + if (qdisc->sfq.quantum) + nm_utils_strbuf_append(&buf, &len, " quantum %u", qdisc->sfq.quantum); + if (qdisc->sfq.perturb_period) + nm_utils_strbuf_append(&buf, &len, " perturb %d", qdisc->sfq.perturb_period); + if (qdisc->sfq.limit) + nm_utils_strbuf_append(&buf, &len, " limit %u", (guint) qdisc->sfq.limit); + if (qdisc->sfq.divisor) + nm_utils_strbuf_append(&buf, &len, " divisor %u", qdisc->sfq.divisor); + if (qdisc->sfq.flows) + nm_utils_strbuf_append(&buf, &len, " flows %u", qdisc->sfq.flows); + if (qdisc->sfq.depth) + nm_utils_strbuf_append(&buf, &len, " depth %u", qdisc->sfq.depth); + } else if (nm_streq0(qdisc->kind, "tbf")) { + nm_utils_strbuf_append(&buf, &len, " rate %" G_GUINT64_FORMAT, qdisc->tbf.rate); + nm_utils_strbuf_append(&buf, &len, " burst %u", qdisc->tbf.burst); + if (qdisc->tbf.limit) + nm_utils_strbuf_append(&buf, &len, " limit %u", qdisc->tbf.limit); + if (qdisc->tbf.latency) + nm_utils_strbuf_append(&buf, &len, " latency %uns", qdisc->tbf.latency); + } + + return buf0; } void -nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h) -{ - nm_hash_update_str0 (h, obj->kind); - nm_hash_update_vals (h, - obj->ifindex, - obj->addr_family, - obj->handle, - obj->parent, - obj->info); - if (nm_streq0 (obj->kind, "fq_codel")) { - nm_hash_update_vals (h, - obj->fq_codel.limit, - obj->fq_codel.flows, - obj->fq_codel.target, - obj->fq_codel.interval, - obj->fq_codel.quantum, - obj->fq_codel.ce_threshold, - obj->fq_codel.memory_limit, - NM_HASH_COMBINE_BOOLS (guint8, - obj->fq_codel.ecn)); - } else if (nm_streq0 (obj->kind, "sfq")) { - nm_hash_update_vals (h, - obj->sfq.quantum, - obj->sfq.perturb_period, - obj->sfq.limit, - obj->sfq.divisor, - obj->sfq.flows, - obj->sfq.depth); - } else if (nm_streq0 (obj->kind, "tbf")) { - nm_hash_update_vals (h, - obj->tbf.rate, - obj->tbf.burst, - obj->tbf.limit, - obj->tbf.latency); - } +nm_platform_qdisc_hash_update(const NMPlatformQdisc *obj, NMHashState *h) +{ + nm_hash_update_str0(h, obj->kind); + nm_hash_update_vals(h, obj->ifindex, obj->addr_family, obj->handle, obj->parent, obj->info); + if (nm_streq0(obj->kind, "fq_codel")) { + nm_hash_update_vals(h, + obj->fq_codel.limit, + obj->fq_codel.flows, + obj->fq_codel.target, + obj->fq_codel.interval, + obj->fq_codel.quantum, + obj->fq_codel.ce_threshold, + obj->fq_codel.memory_limit, + NM_HASH_COMBINE_BOOLS(guint8, obj->fq_codel.ecn)); + } else if (nm_streq0(obj->kind, "sfq")) { + nm_hash_update_vals(h, + obj->sfq.quantum, + obj->sfq.perturb_period, + obj->sfq.limit, + obj->sfq.divisor, + obj->sfq.flows, + obj->sfq.depth); + } else if (nm_streq0(obj->kind, "tbf")) { + nm_hash_update_vals(h, obj->tbf.rate, obj->tbf.burst, obj->tbf.limit, obj->tbf.latency); + } } int -nm_platform_qdisc_cmp_full (const NMPlatformQdisc *a, - const NMPlatformQdisc *b, - gboolean compare_handle) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, ifindex); - NM_CMP_FIELD (a, b, parent); - NM_CMP_FIELD_STR_INTERNED (a, b, kind); - NM_CMP_FIELD (a, b, addr_family); - if (compare_handle) - NM_CMP_FIELD (a, b, handle); - NM_CMP_FIELD (a, b, info); - - if (nm_streq0 (a->kind, "fq_codel")) { - NM_CMP_FIELD (a, b, fq_codel.limit); - NM_CMP_FIELD (a, b, fq_codel.flows); - NM_CMP_FIELD (a, b, fq_codel.target); - NM_CMP_FIELD (a, b, fq_codel.interval); - NM_CMP_FIELD (a, b, fq_codel.quantum); - NM_CMP_FIELD (a, b, fq_codel.ce_threshold); - NM_CMP_FIELD (a, b, fq_codel.memory_limit); - NM_CMP_FIELD_UNSAFE (a, b, fq_codel.ecn); - } else if (nm_streq0 (a->kind, "sfq")) { - NM_CMP_FIELD (a, b, sfq.quantum); - NM_CMP_FIELD (a, b, sfq.perturb_period); - NM_CMP_FIELD (a, b, sfq.limit); - NM_CMP_FIELD (a, b, sfq.flows); - NM_CMP_FIELD (a, b, sfq.divisor); - NM_CMP_FIELD (a, b, sfq.depth); - } else if (nm_streq0 (a->kind, "tbf")) { - NM_CMP_FIELD (a, b, tbf.rate); - NM_CMP_FIELD (a, b, tbf.burst); - NM_CMP_FIELD (a, b, tbf.limit); - NM_CMP_FIELD (a, b, tbf.latency); - } - - return 0; +nm_platform_qdisc_cmp_full(const NMPlatformQdisc *a, + const NMPlatformQdisc *b, + gboolean compare_handle) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, ifindex); + NM_CMP_FIELD(a, b, parent); + NM_CMP_FIELD_STR_INTERNED(a, b, kind); + NM_CMP_FIELD(a, b, addr_family); + if (compare_handle) + NM_CMP_FIELD(a, b, handle); + NM_CMP_FIELD(a, b, info); + + if (nm_streq0(a->kind, "fq_codel")) { + NM_CMP_FIELD(a, b, fq_codel.limit); + NM_CMP_FIELD(a, b, fq_codel.flows); + NM_CMP_FIELD(a, b, fq_codel.target); + NM_CMP_FIELD(a, b, fq_codel.interval); + NM_CMP_FIELD(a, b, fq_codel.quantum); + NM_CMP_FIELD(a, b, fq_codel.ce_threshold); + NM_CMP_FIELD(a, b, fq_codel.memory_limit); + NM_CMP_FIELD_UNSAFE(a, b, fq_codel.ecn); + } else if (nm_streq0(a->kind, "sfq")) { + NM_CMP_FIELD(a, b, sfq.quantum); + NM_CMP_FIELD(a, b, sfq.perturb_period); + NM_CMP_FIELD(a, b, sfq.limit); + NM_CMP_FIELD(a, b, sfq.flows); + NM_CMP_FIELD(a, b, sfq.divisor); + NM_CMP_FIELD(a, b, sfq.depth); + } else if (nm_streq0(a->kind, "tbf")) { + NM_CMP_FIELD(a, b, tbf.rate); + NM_CMP_FIELD(a, b, tbf.burst); + NM_CMP_FIELD(a, b, tbf.limit); + NM_CMP_FIELD(a, b, tbf.latency); + } + + return 0; } int -nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b) +nm_platform_qdisc_cmp(const NMPlatformQdisc *a, const NMPlatformQdisc *b) { - return nm_platform_qdisc_cmp_full (a, b, TRUE); + return nm_platform_qdisc_cmp_full(a, b, TRUE); } const char * -nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsize len) -{ - char str_dev[TO_STRING_DEV_BUF_SIZE]; - char act_buf[300]; - char *p; - gsize l; - - if (!nm_utils_to_string_buffer_init_null (tfilter, &buf, &len)) - return buf; - - if (tfilter->action.kind) { - p = act_buf; - l = sizeof (act_buf); - - nm_utils_strbuf_append (&p, &l, " \"%s\"", tfilter->action.kind); - if (nm_streq (tfilter->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - gs_free char *t = NULL; - - nm_utils_strbuf_append (&p, &l, - " (\"%s\")", - nm_utils_str_utf8safe_escape (tfilter->action.kind, - NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL - | NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII, - &t)); - } else if (nm_streq (tfilter->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - nm_utils_strbuf_append (&p, &l, "%s%s%s%s dev %d", - tfilter->action.mirred.ingress ? " ingress" : "", - tfilter->action.mirred.egress ? " egress" : "", - tfilter->action.mirred.mirror ? " mirror" : "", - tfilter->action.mirred.redirect ? " redirect" : "", - tfilter->action.mirred.ifindex); - } - } else - act_buf[0] = '\0'; - - g_snprintf (buf, len, "%s%s family %u handle %x parent %x info %x%s", - tfilter->kind, - _to_string_dev (NULL, tfilter->ifindex, str_dev, sizeof (str_dev)), - tfilter->addr_family, - tfilter->handle, - tfilter->parent, - tfilter->info, - act_buf); - - return buf; +nm_platform_tfilter_to_string(const NMPlatformTfilter *tfilter, char *buf, gsize len) +{ + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char act_buf[300]; + char *p; + gsize l; + + if (!nm_utils_to_string_buffer_init_null(tfilter, &buf, &len)) + return buf; + + if (tfilter->action.kind) { + p = act_buf; + l = sizeof(act_buf); + + nm_utils_strbuf_append(&p, &l, " \"%s\"", tfilter->action.kind); + if (nm_streq(tfilter->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { + gs_free char *t = NULL; + + nm_utils_strbuf_append( + &p, + &l, + " (\"%s\")", + nm_utils_str_utf8safe_escape(tfilter->action.kind, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL + | NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII, + &t)); + } else if (nm_streq(tfilter->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { + nm_utils_strbuf_append(&p, + &l, + "%s%s%s%s dev %d", + tfilter->action.mirred.ingress ? " ingress" : "", + tfilter->action.mirred.egress ? " egress" : "", + tfilter->action.mirred.mirror ? " mirror" : "", + tfilter->action.mirred.redirect ? " redirect" : "", + tfilter->action.mirred.ifindex); + } + } else + act_buf[0] = '\0'; + + g_snprintf(buf, + len, + "%s%s family %u handle %x parent %x info %x%s", + tfilter->kind, + _to_string_dev(NULL, tfilter->ifindex, str_dev, sizeof(str_dev)), + tfilter->addr_family, + tfilter->handle, + tfilter->parent, + tfilter->info, + act_buf); + + return buf; } void -nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h) -{ - nm_hash_update_str0 (h, obj->kind); - nm_hash_update_vals (h, - obj->ifindex, - obj->addr_family, - obj->handle, - obj->parent, - obj->info); - if (obj->action.kind) { - nm_hash_update_str (h, obj->action.kind); - if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - nm_hash_update_strarr (h, obj->action.simple.sdata); - } else if (nm_streq (obj->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - nm_hash_update_vals (h, - obj->action.mirred.ifindex, - NM_HASH_COMBINE_BOOLS (guint8, - obj->action.mirred.ingress, - obj->action.mirred.egress, - obj->action.mirred.mirror, - obj->action.mirred.redirect)); - } - } +nm_platform_tfilter_hash_update(const NMPlatformTfilter *obj, NMHashState *h) +{ + nm_hash_update_str0(h, obj->kind); + nm_hash_update_vals(h, obj->ifindex, obj->addr_family, obj->handle, obj->parent, obj->info); + if (obj->action.kind) { + nm_hash_update_str(h, obj->action.kind); + if (nm_streq(obj->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { + nm_hash_update_strarr(h, obj->action.simple.sdata); + } else if (nm_streq(obj->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { + nm_hash_update_vals(h, + obj->action.mirred.ifindex, + NM_HASH_COMBINE_BOOLS(guint8, + obj->action.mirred.ingress, + obj->action.mirred.egress, + obj->action.mirred.mirror, + obj->action.mirred.redirect)); + } + } } int -nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, ifindex); - NM_CMP_FIELD (a, b, parent); - NM_CMP_FIELD_STR_INTERNED (a, b, kind); - NM_CMP_FIELD (a, b, addr_family); - NM_CMP_FIELD (a, b, handle); - NM_CMP_FIELD (a, b, info); - - NM_CMP_FIELD_STR_INTERNED (a, b, action.kind); - if (a->action.kind) { - if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { - NM_CMP_FIELD_STR (a, b, action.simple.sdata); - } else if (nm_streq (a->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { - NM_CMP_FIELD (a, b, action.mirred.ifindex); - NM_CMP_FIELD_UNSAFE (a, b, action.mirred.ingress); - NM_CMP_FIELD_UNSAFE (a, b, action.mirred.egress); - NM_CMP_FIELD_UNSAFE (a, b, action.mirred.mirror); - NM_CMP_FIELD_UNSAFE (a, b, action.mirred.redirect); - } - } - - return 0; +nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, ifindex); + NM_CMP_FIELD(a, b, parent); + NM_CMP_FIELD_STR_INTERNED(a, b, kind); + NM_CMP_FIELD(a, b, addr_family); + NM_CMP_FIELD(a, b, handle); + NM_CMP_FIELD(a, b, info); + + NM_CMP_FIELD_STR_INTERNED(a, b, action.kind); + if (a->action.kind) { + if (nm_streq(a->action.kind, NM_PLATFORM_ACTION_KIND_SIMPLE)) { + NM_CMP_FIELD_STR(a, b, action.simple.sdata); + } else if (nm_streq(a->action.kind, NM_PLATFORM_ACTION_KIND_MIRRED)) { + NM_CMP_FIELD(a, b, action.mirred.ifindex); + NM_CMP_FIELD_UNSAFE(a, b, action.mirred.ingress); + NM_CMP_FIELD_UNSAFE(a, b, action.mirred.egress); + NM_CMP_FIELD_UNSAFE(a, b, action.mirred.mirror); + NM_CMP_FIELD_UNSAFE(a, b, action.mirred.redirect); + } + } + + return 0; } const char * -nm_platform_vf_to_string (const NMPlatformVF *vf, char *buf, gsize len) -{ - char str_mac[128], mac[128]; - char str_spoof_check[64]; - char str_trust[64]; - char str_min_tx_rate[64]; - char str_max_tx_rate[64]; - nm_auto_free_gstring GString *gstr_vlans = NULL; - guint i; - - if (!nm_utils_to_string_buffer_init_null (vf, &buf, &len)) - return buf; - - if (vf->mac.len) { - nm_utils_hwaddr_ntoa_buf (vf->mac.data, vf->mac.len, TRUE, mac, sizeof (mac)); - nm_sprintf_buf (str_mac, " mac %s", mac); - } else - str_mac[0] = '\0'; - - if (vf->num_vlans) { - gstr_vlans = g_string_new (""); - for (i = 0; i < vf->num_vlans; i++) { - g_string_append_printf (gstr_vlans, " vlan %u", (unsigned) vf->vlans[i].id); - if (vf->vlans[i].qos) - g_string_append_printf (gstr_vlans, " qos %u", (unsigned) vf->vlans[i].qos); - if (vf->vlans[i].proto_ad) - g_string_append (gstr_vlans, " proto 802.1ad"); - } - } - - g_snprintf (buf, len, - "%u" /* index */ - "%s" /* MAC */ - "%s" /* spoof check */ - "%s" /* trust */ - "%s" /* min tx rate */ - "%s" /* max tx rate */ - "%s", /* VLANs */ - vf->index, - str_mac, - vf->spoofchk >= 0 ? nm_sprintf_buf (str_spoof_check, " spoofchk %d", vf->spoofchk) : "", - vf->trust >= 0 ? nm_sprintf_buf (str_trust, " trust %d", vf->trust) : "", - vf->min_tx_rate ? nm_sprintf_buf (str_min_tx_rate, " min_tx_rate %u", (unsigned) vf->min_tx_rate) : "", - vf->max_tx_rate ? nm_sprintf_buf (str_max_tx_rate, " max_tx_rate %u", (unsigned) vf->max_tx_rate) : "", - gstr_vlans ? gstr_vlans->str : ""); - - return buf; +nm_platform_vf_to_string(const NMPlatformVF *vf, char *buf, gsize len) +{ + char str_mac[128], mac[128]; + char str_spoof_check[64]; + char str_trust[64]; + char str_min_tx_rate[64]; + char str_max_tx_rate[64]; + nm_auto_free_gstring GString *gstr_vlans = NULL; + guint i; + + if (!nm_utils_to_string_buffer_init_null(vf, &buf, &len)) + return buf; + + if (vf->mac.len) { + _nm_utils_hwaddr_ntoa(vf->mac.data, vf->mac.len, TRUE, mac, sizeof(mac)); + nm_sprintf_buf(str_mac, " mac %s", mac); + } else + str_mac[0] = '\0'; + + if (vf->num_vlans) { + gstr_vlans = g_string_new(""); + for (i = 0; i < vf->num_vlans; i++) { + g_string_append_printf(gstr_vlans, " vlan %u", (unsigned) vf->vlans[i].id); + if (vf->vlans[i].qos) + g_string_append_printf(gstr_vlans, " qos %u", (unsigned) vf->vlans[i].qos); + if (vf->vlans[i].proto_ad) + g_string_append(gstr_vlans, " proto 802.1ad"); + } + } + + g_snprintf(buf, + len, + "%u" /* index */ + "%s" /* MAC */ + "%s" /* spoof check */ + "%s" /* trust */ + "%s" /* min tx rate */ + "%s" /* max tx rate */ + "%s", /* VLANs */ + vf->index, + str_mac, + vf->spoofchk >= 0 ? nm_sprintf_buf(str_spoof_check, " spoofchk %d", vf->spoofchk) + : "", + vf->trust >= 0 ? nm_sprintf_buf(str_trust, " trust %d", vf->trust) : "", + vf->min_tx_rate + ? nm_sprintf_buf(str_min_tx_rate, " min_tx_rate %u", (unsigned) vf->min_tx_rate) + : "", + vf->max_tx_rate + ? nm_sprintf_buf(str_max_tx_rate, " max_tx_rate %u", (unsigned) vf->max_tx_rate) + : "", + gstr_vlans ? gstr_vlans->str : ""); + + return buf; } - const char * -nm_platform_bridge_vlan_to_string (const NMPlatformBridgeVlan *vlan, char *buf, gsize len) +nm_platform_bridge_vlan_to_string(const NMPlatformBridgeVlan *vlan, char *buf, gsize len) { - char str_vid_end[64]; + char str_vid_end[64]; - if (!nm_utils_to_string_buffer_init_null (vlan, &buf, &len)) - return buf; + if (!nm_utils_to_string_buffer_init_null(vlan, &buf, &len)) + return buf; - g_snprintf (buf, len, - "%u" - "%s" - "%s" - "%s", - vlan->vid_start, - vlan->vid_start != vlan->vid_end ? nm_sprintf_buf (str_vid_end, "-%u", vlan->vid_end) : "", - vlan->pvid ? " PVID" : "", - vlan->untagged ? " untagged" : ""); + g_snprintf(buf, + len, + "%u" + "%s" + "%s" + "%s", + vlan->vid_start, + vlan->vid_start != vlan->vid_end ? nm_sprintf_buf(str_vid_end, "-%u", vlan->vid_end) + : "", + vlan->pvid ? " PVID" : "", + vlan->untagged ? " untagged" : ""); - return buf; + return buf; } void -nm_platform_link_hash_update (const NMPlatformLink *obj, NMHashState *h) -{ - nm_hash_update_vals (h, - obj->ifindex, - obj->master, - obj->parent, - obj->n_ifi_flags, - obj->mtu, - obj->type, - obj->arptype, - obj->inet6_addr_gen_mode_inv, - obj->inet6_token, - obj->rx_packets, - obj->rx_bytes, - obj->tx_packets, - obj->tx_bytes, - NM_HASH_COMBINE_BOOLS (guint8, - obj->connected, - obj->initialized)); - nm_hash_update_strarr (h, obj->name); - nm_hash_update_str0 (h, obj->kind); - nm_hash_update_str0 (h, obj->driver); - /* nm_hash_update_mem() also hashes the length obj->addr.len */ - nm_hash_update_mem (h, obj->l_address.data, NM_MIN (obj->l_address.len, sizeof (obj->l_address.data))); - nm_hash_update_mem (h, obj->l_broadcast.data, NM_MIN (obj->l_broadcast.len, sizeof (obj->l_broadcast.data))); +nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->ifindex, + obj->master, + obj->parent, + obj->n_ifi_flags, + obj->mtu, + obj->type, + obj->arptype, + obj->inet6_addr_gen_mode_inv, + obj->inet6_token, + obj->rx_packets, + obj->rx_bytes, + obj->tx_packets, + obj->tx_bytes, + NM_HASH_COMBINE_BOOLS(guint8, obj->connected, obj->initialized)); + nm_hash_update_strarr(h, obj->name); + nm_hash_update_str0(h, obj->kind); + nm_hash_update_str0(h, obj->driver); + /* nm_hash_update_mem() also hashes the length obj->addr.len */ + nm_hash_update_mem(h, + obj->l_address.data, + NM_MIN(obj->l_address.len, sizeof(obj->l_address.data))); + nm_hash_update_mem(h, + obj->l_broadcast.data, + NM_MIN(obj->l_broadcast.len, sizeof(obj->l_broadcast.data))); } int -nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, ifindex); - NM_CMP_FIELD (a, b, type); - NM_CMP_FIELD_STR (a, b, name); - NM_CMP_FIELD (a, b, master); - NM_CMP_FIELD (a, b, parent); - NM_CMP_FIELD (a, b, n_ifi_flags); - NM_CMP_FIELD_UNSAFE (a, b, connected); - NM_CMP_FIELD (a, b, mtu); - NM_CMP_FIELD_BOOL (a, b, initialized); - NM_CMP_FIELD (a, b, arptype); - NM_CMP_FIELD (a, b, l_address.len); - NM_CMP_FIELD (a, b, l_broadcast.len); - NM_CMP_FIELD (a, b, inet6_addr_gen_mode_inv); - NM_CMP_FIELD_STR_INTERNED (a, b, kind); - NM_CMP_FIELD_STR_INTERNED (a, b, driver); - if (a->l_address.len) - NM_CMP_FIELD_MEMCMP_LEN (a, b, l_address.data, a->l_address.len); - if (a->l_broadcast.len) - NM_CMP_FIELD_MEMCMP_LEN (a, b, l_broadcast.data, a->l_broadcast.len); - NM_CMP_FIELD_MEMCMP (a, b, inet6_token); - NM_CMP_FIELD (a, b, rx_packets); - NM_CMP_FIELD (a, b, rx_bytes); - NM_CMP_FIELD (a, b, tx_packets); - NM_CMP_FIELD (a, b, tx_bytes); - return 0; +nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, ifindex); + NM_CMP_FIELD(a, b, type); + NM_CMP_FIELD_STR(a, b, name); + NM_CMP_FIELD(a, b, master); + NM_CMP_FIELD(a, b, parent); + NM_CMP_FIELD(a, b, n_ifi_flags); + NM_CMP_FIELD_UNSAFE(a, b, connected); + NM_CMP_FIELD(a, b, mtu); + NM_CMP_FIELD_BOOL(a, b, initialized); + NM_CMP_FIELD(a, b, arptype); + NM_CMP_FIELD(a, b, l_address.len); + NM_CMP_FIELD(a, b, l_broadcast.len); + NM_CMP_FIELD(a, b, inet6_addr_gen_mode_inv); + NM_CMP_FIELD_STR_INTERNED(a, b, kind); + NM_CMP_FIELD_STR_INTERNED(a, b, driver); + if (a->l_address.len) + NM_CMP_FIELD_MEMCMP_LEN(a, b, l_address.data, a->l_address.len); + if (a->l_broadcast.len) + NM_CMP_FIELD_MEMCMP_LEN(a, b, l_broadcast.data, a->l_broadcast.len); + NM_CMP_FIELD_MEMCMP(a, b, inet6_token); + NM_CMP_FIELD(a, b, rx_packets); + NM_CMP_FIELD(a, b, rx_bytes); + NM_CMP_FIELD(a, b, tx_packets); + NM_CMP_FIELD(a, b, tx_bytes); + return 0; } void -nm_platform_lnk_gre_hash_update (const NMPlatformLnkGre *obj, NMHashState *h) -{ - nm_hash_update_vals (h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->input_flags, - obj->output_flags, - obj->input_key, - obj->output_key, - obj->ttl, - obj->tos, - (bool) obj->path_mtu_discovery, - (bool) obj->is_tap); +nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->forward_delay, + obj->hello_time, + obj->max_age, + obj->ageing_time, + obj->priority, + obj->vlan_protocol, + obj->group_fwd_mask, + obj->group_addr, + obj->mcast_hash_max, + obj->mcast_last_member_count, + obj->mcast_startup_query_count, + obj->mcast_last_member_interval, + obj->mcast_membership_interval, + obj->mcast_querier_interval, + obj->mcast_query_interval, + obj->mcast_router, + obj->mcast_query_response_interval, + obj->mcast_startup_query_interval, + NM_HASH_COMBINE_BOOLS(guint8, + obj->stp_state, + obj->mcast_querier, + obj->mcast_query_use_ifaddr, + obj->mcast_snooping, + obj->vlan_stats_enabled)); } int -nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, parent_ifindex); - NM_CMP_FIELD (a, b, input_flags); - NM_CMP_FIELD (a, b, output_flags); - NM_CMP_FIELD (a, b, input_key); - NM_CMP_FIELD (a, b, output_key); - NM_CMP_FIELD (a, b, local); - NM_CMP_FIELD (a, b, remote); - NM_CMP_FIELD (a, b, ttl); - NM_CMP_FIELD (a, b, tos); - NM_CMP_FIELD_BOOL (a, b, path_mtu_discovery); - NM_CMP_FIELD_BOOL (a, b, is_tap); - return 0; +nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, forward_delay); + NM_CMP_FIELD(a, b, hello_time); + NM_CMP_FIELD(a, b, max_age); + NM_CMP_FIELD(a, b, ageing_time); + NM_CMP_FIELD_BOOL(a, b, stp_state); + NM_CMP_FIELD(a, b, priority); + NM_CMP_FIELD(a, b, vlan_protocol); + NM_CMP_FIELD_BOOL(a, b, vlan_stats_enabled); + NM_CMP_FIELD(a, b, group_fwd_mask); + NM_CMP_FIELD_MEMCMP(a, b, group_addr); + NM_CMP_FIELD_BOOL(a, b, mcast_snooping); + NM_CMP_FIELD(a, b, mcast_router); + NM_CMP_FIELD_BOOL(a, b, mcast_query_use_ifaddr); + NM_CMP_FIELD_BOOL(a, b, mcast_querier); + NM_CMP_FIELD(a, b, mcast_hash_max); + NM_CMP_FIELD(a, b, mcast_last_member_count); + NM_CMP_FIELD(a, b, mcast_startup_query_count); + NM_CMP_FIELD(a, b, mcast_last_member_interval); + NM_CMP_FIELD(a, b, mcast_membership_interval); + NM_CMP_FIELD(a, b, mcast_querier_interval); + NM_CMP_FIELD(a, b, mcast_query_interval); + NM_CMP_FIELD(a, b, mcast_query_response_interval); + NM_CMP_FIELD(a, b, mcast_startup_query_interval); + + return 0; } void -nm_platform_lnk_infiniband_hash_update (const NMPlatformLnkInfiniband *obj, NMHashState *h) +nm_platform_lnk_gre_hash_update(const NMPlatformLnkGre *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->local, + obj->remote, + obj->parent_ifindex, + obj->input_flags, + obj->output_flags, + obj->input_key, + obj->output_key, + obj->ttl, + obj->tos, + (bool) obj->path_mtu_discovery, + (bool) obj->is_tap); +} + +int +nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, parent_ifindex); + NM_CMP_FIELD(a, b, input_flags); + NM_CMP_FIELD(a, b, output_flags); + NM_CMP_FIELD(a, b, input_key); + NM_CMP_FIELD(a, b, output_key); + NM_CMP_FIELD(a, b, local); + NM_CMP_FIELD(a, b, remote); + NM_CMP_FIELD(a, b, ttl); + NM_CMP_FIELD(a, b, tos); + NM_CMP_FIELD_BOOL(a, b, path_mtu_discovery); + NM_CMP_FIELD_BOOL(a, b, is_tap); + return 0; +} + +void +nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h) { - nm_hash_update_val (h, obj->p_key); - nm_hash_update_str0 (h, obj->mode); + nm_hash_update_val(h, obj->p_key); + nm_hash_update_str0(h, obj->mode); } int -nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b) +nm_platform_lnk_infiniband_cmp(const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, p_key); - NM_CMP_FIELD_STR_INTERNED (a, b, mode); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, p_key); + NM_CMP_FIELD_STR_INTERNED(a, b, mode); + return 0; } void -nm_platform_lnk_ip6tnl_hash_update (const NMPlatformLnkIp6Tnl *obj, NMHashState *h) -{ - nm_hash_update_vals (h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->ttl, - obj->tclass, - obj->encap_limit, - obj->proto, - obj->flow_label, - obj->flags, - obj->input_flags, - obj->output_flags, - obj->input_key, - obj->output_key, - (bool) obj->is_gre, - (bool) obj->is_tap); +nm_platform_lnk_ip6tnl_hash_update(const NMPlatformLnkIp6Tnl *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->local, + obj->remote, + obj->parent_ifindex, + obj->ttl, + obj->tclass, + obj->encap_limit, + obj->proto, + obj->flow_label, + obj->flags, + obj->input_flags, + obj->output_flags, + obj->input_key, + obj->output_key, + (bool) obj->is_gre, + (bool) obj->is_tap); } int -nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, parent_ifindex); - NM_CMP_FIELD_MEMCMP (a, b, local); - NM_CMP_FIELD_MEMCMP (a, b, remote); - NM_CMP_FIELD (a, b, ttl); - NM_CMP_FIELD (a, b, tclass); - NM_CMP_FIELD (a, b, encap_limit); - NM_CMP_FIELD (a, b, flow_label); - NM_CMP_FIELD (a, b, proto); - NM_CMP_FIELD (a, b, flags); - NM_CMP_FIELD (a, b, input_flags); - NM_CMP_FIELD (a, b, output_flags); - NM_CMP_FIELD (a, b, input_key); - NM_CMP_FIELD (a, b, output_key); - NM_CMP_FIELD_BOOL (a, b, is_gre); - NM_CMP_FIELD_BOOL (a, b, is_tap); - return 0; +nm_platform_lnk_ip6tnl_cmp(const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, parent_ifindex); + NM_CMP_FIELD_MEMCMP(a, b, local); + NM_CMP_FIELD_MEMCMP(a, b, remote); + NM_CMP_FIELD(a, b, ttl); + NM_CMP_FIELD(a, b, tclass); + NM_CMP_FIELD(a, b, encap_limit); + NM_CMP_FIELD(a, b, flow_label); + NM_CMP_FIELD(a, b, proto); + NM_CMP_FIELD(a, b, flags); + NM_CMP_FIELD(a, b, input_flags); + NM_CMP_FIELD(a, b, output_flags); + NM_CMP_FIELD(a, b, input_key); + NM_CMP_FIELD(a, b, output_key); + NM_CMP_FIELD_BOOL(a, b, is_gre); + NM_CMP_FIELD_BOOL(a, b, is_tap); + return 0; } void -nm_platform_lnk_ipip_hash_update (const NMPlatformLnkIpIp *obj, NMHashState *h) +nm_platform_lnk_ipip_hash_update(const NMPlatformLnkIpIp *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->ttl, - obj->tos, - (bool) obj->path_mtu_discovery); + nm_hash_update_vals(h, + obj->local, + obj->remote, + obj->parent_ifindex, + obj->ttl, + obj->tos, + (bool) obj->path_mtu_discovery); } int -nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b) +nm_platform_lnk_ipip_cmp(const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, parent_ifindex); - NM_CMP_FIELD (a, b, local); - NM_CMP_FIELD (a, b, remote); - NM_CMP_FIELD (a, b, ttl); - NM_CMP_FIELD (a, b, tos); - NM_CMP_FIELD_BOOL (a, b, path_mtu_discovery); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, parent_ifindex); + NM_CMP_FIELD(a, b, local); + NM_CMP_FIELD(a, b, remote); + NM_CMP_FIELD(a, b, ttl); + NM_CMP_FIELD(a, b, tos); + NM_CMP_FIELD_BOOL(a, b, path_mtu_discovery); + return 0; } void -nm_platform_lnk_macsec_hash_update (const NMPlatformLnkMacsec *obj, NMHashState *h) -{ - nm_hash_update_vals (h, - obj->parent_ifindex, - obj->sci, - obj->cipher_suite, - obj->window, - obj->icv_length, - obj->encoding_sa, - obj->validation, - NM_HASH_COMBINE_BOOLS (guint8, - obj->encrypt, - obj->protect, - obj->include_sci, - obj->es, - obj->scb, - obj->replay_protect)); +nm_platform_lnk_macsec_hash_update(const NMPlatformLnkMacsec *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->parent_ifindex, + obj->sci, + obj->cipher_suite, + obj->window, + obj->icv_length, + obj->encoding_sa, + obj->validation, + NM_HASH_COMBINE_BOOLS(guint8, + obj->encrypt, + obj->protect, + obj->include_sci, + obj->es, + obj->scb, + obj->replay_protect)); } int -nm_platform_lnk_macsec_cmp (const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, parent_ifindex); - NM_CMP_FIELD (a, b, sci); - NM_CMP_FIELD (a, b, icv_length); - NM_CMP_FIELD (a, b, cipher_suite); - NM_CMP_FIELD (a, b, window); - NM_CMP_FIELD (a, b, encoding_sa); - NM_CMP_FIELD (a, b, validation); - NM_CMP_FIELD_UNSAFE (a, b, encrypt); - NM_CMP_FIELD_UNSAFE (a, b, protect); - NM_CMP_FIELD_UNSAFE (a, b, include_sci); - NM_CMP_FIELD_UNSAFE (a, b, es); - NM_CMP_FIELD_UNSAFE (a, b, scb); - NM_CMP_FIELD_UNSAFE (a, b, replay_protect); - return 0; +nm_platform_lnk_macsec_cmp(const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, parent_ifindex); + NM_CMP_FIELD(a, b, sci); + NM_CMP_FIELD(a, b, icv_length); + NM_CMP_FIELD(a, b, cipher_suite); + NM_CMP_FIELD(a, b, window); + NM_CMP_FIELD(a, b, encoding_sa); + NM_CMP_FIELD(a, b, validation); + NM_CMP_FIELD_UNSAFE(a, b, encrypt); + NM_CMP_FIELD_UNSAFE(a, b, protect); + NM_CMP_FIELD_UNSAFE(a, b, include_sci); + NM_CMP_FIELD_UNSAFE(a, b, es); + NM_CMP_FIELD_UNSAFE(a, b, scb); + NM_CMP_FIELD_UNSAFE(a, b, replay_protect); + return 0; } void -nm_platform_lnk_macvlan_hash_update (const NMPlatformLnkMacvlan *obj, NMHashState *h ) +nm_platform_lnk_macvlan_hash_update(const NMPlatformLnkMacvlan *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->mode, - NM_HASH_COMBINE_BOOLS (guint8, - obj->no_promisc, - obj->tap)); + nm_hash_update_vals(h, obj->mode, NM_HASH_COMBINE_BOOLS(guint8, obj->no_promisc, obj->tap)); } int -nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b) +nm_platform_lnk_macvlan_cmp(const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, mode); - NM_CMP_FIELD_UNSAFE (a, b, no_promisc); - NM_CMP_FIELD_UNSAFE (a, b, tap); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, mode); + NM_CMP_FIELD_UNSAFE(a, b, no_promisc); + NM_CMP_FIELD_UNSAFE(a, b, tap); + return 0; } void -nm_platform_lnk_sit_hash_update (const NMPlatformLnkSit *obj, NMHashState *h) +nm_platform_lnk_sit_hash_update(const NMPlatformLnkSit *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->local, - obj->remote, - obj->parent_ifindex, - obj->flags, - obj->ttl, - obj->tos, - obj->proto, - (bool) obj->path_mtu_discovery); + nm_hash_update_vals(h, + obj->local, + obj->remote, + obj->parent_ifindex, + obj->flags, + obj->ttl, + obj->tos, + obj->proto, + (bool) obj->path_mtu_discovery); } int -nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b) +nm_platform_lnk_sit_cmp(const NMPlatformLnkSit *a, const NMPlatformLnkSit *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, parent_ifindex); - NM_CMP_FIELD (a, b, local); - NM_CMP_FIELD (a, b, remote); - NM_CMP_FIELD (a, b, ttl); - NM_CMP_FIELD (a, b, tos); - NM_CMP_FIELD_BOOL (a, b, path_mtu_discovery); - NM_CMP_FIELD (a, b, flags); - NM_CMP_FIELD (a, b, proto); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, parent_ifindex); + NM_CMP_FIELD(a, b, local); + NM_CMP_FIELD(a, b, remote); + NM_CMP_FIELD(a, b, ttl); + NM_CMP_FIELD(a, b, tos); + NM_CMP_FIELD_BOOL(a, b, path_mtu_discovery); + NM_CMP_FIELD(a, b, flags); + NM_CMP_FIELD(a, b, proto); + return 0; } void -nm_platform_lnk_tun_hash_update (const NMPlatformLnkTun *obj, NMHashState *h) +nm_platform_lnk_tun_hash_update(const NMPlatformLnkTun *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->type, - obj->owner, - obj->group, - NM_HASH_COMBINE_BOOLS (guint8, - obj->owner_valid, - obj->group_valid, - obj->pi, - obj->vnet_hdr, - obj->multi_queue, - obj->persist)); + nm_hash_update_vals(h, + obj->type, + obj->owner, + obj->group, + NM_HASH_COMBINE_BOOLS(guint8, + obj->owner_valid, + obj->group_valid, + obj->pi, + obj->vnet_hdr, + obj->multi_queue, + obj->persist)); } int -nm_platform_lnk_tun_cmp (const NMPlatformLnkTun *a, const NMPlatformLnkTun *b) +nm_platform_lnk_tun_cmp(const NMPlatformLnkTun *a, const NMPlatformLnkTun *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, type); - NM_CMP_FIELD (a, b, owner); - NM_CMP_FIELD (a, b, group); - NM_CMP_FIELD_BOOL (a, b, owner_valid); - NM_CMP_FIELD_BOOL (a, b, group_valid); - NM_CMP_FIELD_BOOL (a, b, pi); - NM_CMP_FIELD_BOOL (a, b, vnet_hdr); - NM_CMP_FIELD_BOOL (a, b, multi_queue); - NM_CMP_FIELD_BOOL (a, b, persist); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, type); + NM_CMP_FIELD(a, b, owner); + NM_CMP_FIELD(a, b, group); + NM_CMP_FIELD_BOOL(a, b, owner_valid); + NM_CMP_FIELD_BOOL(a, b, group_valid); + NM_CMP_FIELD_BOOL(a, b, pi); + NM_CMP_FIELD_BOOL(a, b, vnet_hdr); + NM_CMP_FIELD_BOOL(a, b, multi_queue); + NM_CMP_FIELD_BOOL(a, b, persist); + return 0; } void -nm_platform_lnk_vlan_hash_update (const NMPlatformLnkVlan *obj, NMHashState *h) +nm_platform_lnk_vlan_hash_update(const NMPlatformLnkVlan *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->id, - obj->flags); + nm_hash_update_vals(h, obj->id, obj->flags); } int -nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b) +nm_platform_lnk_vlan_cmp(const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, id); - NM_CMP_FIELD (a, b, flags); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, id); + NM_CMP_FIELD(a, b, flags); + return 0; } void -nm_platform_lnk_vrf_hash_update (const NMPlatformLnkVrf *obj, NMHashState *h) +nm_platform_lnk_vrf_hash_update(const NMPlatformLnkVrf *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->table); + nm_hash_update_vals(h, obj->table); } int -nm_platform_lnk_vrf_cmp (const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b) +nm_platform_lnk_vrf_cmp(const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, table); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, table); + return 0; } void -nm_platform_lnk_vxlan_hash_update (const NMPlatformLnkVxlan *obj, NMHashState *h) -{ - nm_hash_update_vals (h, - obj->group6, - obj->local6, - obj->group, - obj->local, - obj->parent_ifindex, - obj->id, - obj->ageing, - obj->limit, - obj->dst_port, - obj->src_port_min, - obj->src_port_max, - obj->tos, - obj->ttl, - NM_HASH_COMBINE_BOOLS (guint8, - obj->learning, - obj->proxy, - obj->rsc, - obj->l2miss, - obj->l3miss)); +nm_platform_lnk_vxlan_hash_update(const NMPlatformLnkVxlan *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->group6, + obj->local6, + obj->group, + obj->local, + obj->parent_ifindex, + obj->id, + obj->ageing, + obj->limit, + obj->dst_port, + obj->src_port_min, + obj->src_port_max, + obj->tos, + obj->ttl, + NM_HASH_COMBINE_BOOLS(guint8, + obj->learning, + obj->proxy, + obj->rsc, + obj->l2miss, + obj->l3miss)); } int -nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, parent_ifindex); - NM_CMP_FIELD (a, b, id); - NM_CMP_FIELD (a, b, group); - NM_CMP_FIELD (a, b, local); - NM_CMP_FIELD_MEMCMP (a, b, group6); - NM_CMP_FIELD_MEMCMP (a, b, local6); - NM_CMP_FIELD (a, b, tos); - NM_CMP_FIELD (a, b, ttl); - NM_CMP_FIELD_BOOL (a, b, learning); - NM_CMP_FIELD (a, b, ageing); - NM_CMP_FIELD (a, b, limit); - NM_CMP_FIELD (a, b, dst_port); - NM_CMP_FIELD (a, b, src_port_min); - NM_CMP_FIELD (a, b, src_port_max); - NM_CMP_FIELD_BOOL (a, b, proxy); - NM_CMP_FIELD_BOOL (a, b, rsc); - NM_CMP_FIELD_BOOL (a, b, l2miss); - NM_CMP_FIELD_BOOL (a, b, l3miss); - return 0; +nm_platform_lnk_vxlan_cmp(const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, parent_ifindex); + NM_CMP_FIELD(a, b, id); + NM_CMP_FIELD(a, b, group); + NM_CMP_FIELD(a, b, local); + NM_CMP_FIELD_MEMCMP(a, b, group6); + NM_CMP_FIELD_MEMCMP(a, b, local6); + NM_CMP_FIELD(a, b, tos); + NM_CMP_FIELD(a, b, ttl); + NM_CMP_FIELD_BOOL(a, b, learning); + NM_CMP_FIELD(a, b, ageing); + NM_CMP_FIELD(a, b, limit); + NM_CMP_FIELD(a, b, dst_port); + NM_CMP_FIELD(a, b, src_port_min); + NM_CMP_FIELD(a, b, src_port_max); + NM_CMP_FIELD_BOOL(a, b, proxy); + NM_CMP_FIELD_BOOL(a, b, rsc); + NM_CMP_FIELD_BOOL(a, b, l2miss); + NM_CMP_FIELD_BOOL(a, b, l3miss); + return 0; } void -nm_platform_lnk_wireguard_hash_update (const NMPlatformLnkWireGuard *obj, NMHashState *h) +nm_platform_lnk_wireguard_hash_update(const NMPlatformLnkWireGuard *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->listen_port, - obj->fwmark); - nm_hash_update (h, obj->private_key, sizeof (obj->private_key)); - nm_hash_update (h, obj->public_key, sizeof (obj->public_key)); + nm_hash_update_vals(h, obj->listen_port, obj->fwmark); + nm_hash_update(h, obj->private_key, sizeof(obj->private_key)); + nm_hash_update(h, obj->public_key, sizeof(obj->public_key)); } int -nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b) +nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b) { - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, listen_port); - NM_CMP_FIELD (a, b, fwmark); - NM_CMP_FIELD_MEMCMP (a, b, private_key); - NM_CMP_FIELD_MEMCMP (a, b, public_key); - return 0; + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, listen_port); + NM_CMP_FIELD(a, b, fwmark); + NM_CMP_FIELD_MEMCMP(a, b, private_key); + NM_CMP_FIELD_MEMCMP(a, b, public_key); + return 0; +} + +static int +_address_pretty_sort_get_prio_4(in_addr_t addr) +{ + if (nm_utils_ip4_address_is_link_local(addr)) + return 0; + return 1; +} + +int +nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1, + const NMPlatformIP4Address *a2) +{ + in_addr_t n1; + in_addr_t n2; + + nm_assert(a1); + nm_assert(a2); + + /* Sort by address type. For example link local will + * be sorted *after* a global address. */ + NM_CMP_DIRECT(_address_pretty_sort_get_prio_4(a2->address), + _address_pretty_sort_get_prio_4(a1->address)); + + /* Sort the addresses based on their source. */ + NM_CMP_DIRECT(a2->addr_source, a1->addr_source); + + NM_CMP_DIRECT((a2->label[0] == '\0'), (a1->label[0] == '\0')); + + /* Finally, sort addresses lexically. We compare only the + * network part so that the order of addresses in the same + * subnet (and thus also the primary/secondary role) is + * preserved. + */ + n1 = a1->address & _nm_utils_ip4_prefix_to_netmask(a1->plen); + n2 = a2->address & _nm_utils_ip4_prefix_to_netmask(a2->plen); + NM_CMP_DIRECT_MEMCMP(&n1, &n2, sizeof(guint32)); + return 0; +} + +static int +_address_pretty_sort_get_prio_6(const struct in6_addr *addr) +{ + if (IN6_IS_ADDR_V4MAPPED(addr)) + return 0; + if (IN6_IS_ADDR_V4COMPAT(addr)) + return 1; + if (IN6_IS_ADDR_UNSPECIFIED(addr)) + return 2; + if (IN6_IS_ADDR_LOOPBACK(addr)) + return 3; + if (IN6_IS_ADDR_LINKLOCAL(addr)) + return 4; + if (IN6_IS_ADDR_SITELOCAL(addr)) + return 5; + return 6; +} + +int +nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1, + const NMPlatformIP6Address *a2, + gboolean prefer_temp) +{ + gboolean ipv6_privacy1; + gboolean ipv6_privacy2; + + nm_assert(a1); + nm_assert(a2); + + /* tentative addresses are always sorted back... */ + /* sort tentative addresses after non-tentative. */ + NM_CMP_DIRECT(NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_TENTATIVE), + NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_TENTATIVE)); + + /* Sort by address type. For example link local will + * be sorted *after* site local or global. */ + NM_CMP_DIRECT(_address_pretty_sort_get_prio_6(&a2->address), + _address_pretty_sort_get_prio_6(&a1->address)); + + ipv6_privacy1 = NM_FLAGS_ANY(a1->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY); + ipv6_privacy2 = NM_FLAGS_ANY(a2->n_ifa_flags, IFA_F_MANAGETEMPADDR | IFA_F_TEMPORARY); + if (ipv6_privacy1 || ipv6_privacy2) { + gboolean public1 = TRUE; + gboolean public2 = TRUE; + + if (ipv6_privacy1) { + if (a1->n_ifa_flags & IFA_F_TEMPORARY) + public1 = prefer_temp; + else + public1 = !prefer_temp; + } + if (ipv6_privacy2) { + if (a2->n_ifa_flags & IFA_F_TEMPORARY) + public2 = prefer_temp; + else + public2 = !prefer_temp; + } + + NM_CMP_DIRECT(public2, public1); + } + + /* Sort the addresses based on their source. */ + NM_CMP_DIRECT(a2->addr_source, a1->addr_source); + + /* sort permanent addresses before non-permanent. */ + NM_CMP_DIRECT(NM_FLAGS_HAS(a2->n_ifa_flags, IFA_F_PERMANENT), + NM_FLAGS_HAS(a1->n_ifa_flags, IFA_F_PERMANENT)); + + /* finally sort addresses lexically */ + NM_CMP_DIRECT_IN6ADDR(&a1->address, &a2->address); + NM_CMP_DIRECT_MEMCMP(a1, a2, sizeof(*a1)); + return 0; } void -nm_platform_ip4_address_hash_update (const NMPlatformIP4Address *obj, NMHashState *h) -{ - nm_hash_update_vals (h, - obj->ifindex, - obj->addr_source, - nm_platform_ip4_broadcast_address_from_addr (obj), - obj->timestamp, - obj->lifetime, - obj->preferred, - obj->n_ifa_flags, - obj->plen, - obj->address, - obj->peer_address, - NM_HASH_COMBINE_BOOLS (guint8, obj->external)); - nm_hash_update_strarr (h, obj->label); +nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->ifindex, + obj->addr_source, + nm_platform_ip4_broadcast_address_from_addr(obj), + obj->timestamp, + obj->lifetime, + obj->preferred, + obj->n_ifa_flags, + obj->plen, + obj->address, + obj->peer_address, + NM_HASH_COMBINE_BOOLS(guint8, obj->external)); + nm_hash_update_strarr(h, obj->label); } int -nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) -{ - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, ifindex); - NM_CMP_FIELD (a, b, address); - NM_CMP_FIELD (a, b, plen); - NM_CMP_FIELD (a, b, peer_address); - NM_CMP_DIRECT (nm_platform_ip4_broadcast_address_from_addr (a), nm_platform_ip4_broadcast_address_from_addr (b)); - NM_CMP_FIELD (a, b, addr_source); - NM_CMP_FIELD (a, b, timestamp); - NM_CMP_FIELD (a, b, lifetime); - NM_CMP_FIELD (a, b, preferred); - NM_CMP_FIELD (a, b, n_ifa_flags); - NM_CMP_FIELD_STR (a, b, label); - NM_CMP_FIELD_UNSAFE (a, b, external); - return 0; +nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, ifindex); + NM_CMP_FIELD(a, b, address); + NM_CMP_FIELD(a, b, plen); + NM_CMP_FIELD(a, b, peer_address); + NM_CMP_DIRECT(nm_platform_ip4_broadcast_address_from_addr(a), + nm_platform_ip4_broadcast_address_from_addr(b)); + NM_CMP_FIELD(a, b, addr_source); + NM_CMP_FIELD(a, b, timestamp); + NM_CMP_FIELD(a, b, lifetime); + NM_CMP_FIELD(a, b, preferred); + NM_CMP_FIELD(a, b, n_ifa_flags); + NM_CMP_FIELD_STR(a, b, label); + NM_CMP_FIELD_UNSAFE(a, b, external); + return 0; } void -nm_platform_ip6_address_hash_update (const NMPlatformIP6Address *obj, NMHashState *h) +nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h) { - nm_hash_update_vals (h, - obj->ifindex, - obj->addr_source, - obj->timestamp, - obj->lifetime, - obj->preferred, - obj->n_ifa_flags, - obj->plen, - obj->address, - obj->peer_address, - NM_HASH_COMBINE_BOOLS (guint8, obj->external)); + nm_hash_update_vals(h, + obj->ifindex, + obj->addr_source, + obj->timestamp, + obj->lifetime, + obj->preferred, + obj->n_ifa_flags, + obj->plen, + obj->address, + obj->peer_address, + NM_HASH_COMBINE_BOOLS(guint8, obj->external)); } int -nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b) -{ - const struct in6_addr *p_a, *p_b; - - NM_CMP_SELF (a, b); - NM_CMP_FIELD (a, b, ifindex); - NM_CMP_FIELD_MEMCMP (a, b, address); - NM_CMP_FIELD (a, b, plen); - p_a = nm_platform_ip6_address_get_peer (a); - p_b = nm_platform_ip6_address_get_peer (b); - NM_CMP_DIRECT_MEMCMP (p_a, p_b, sizeof (*p_a)); - NM_CMP_FIELD (a, b, addr_source); - NM_CMP_FIELD (a, b, timestamp); - NM_CMP_FIELD (a, b, lifetime); - NM_CMP_FIELD (a, b, preferred); - NM_CMP_FIELD (a, b, n_ifa_flags); - NM_CMP_FIELD_UNSAFE (a, b, external); - return 0; +nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b) +{ + const struct in6_addr *p_a, *p_b; + + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, ifindex); + NM_CMP_FIELD_MEMCMP(a, b, address); + NM_CMP_FIELD(a, b, plen); + p_a = nm_platform_ip6_address_get_peer(a); + p_b = nm_platform_ip6_address_get_peer(b); + NM_CMP_DIRECT_MEMCMP(p_a, p_b, sizeof(*p_a)); + NM_CMP_FIELD(a, b, addr_source); + NM_CMP_FIELD(a, b, timestamp); + NM_CMP_FIELD(a, b, lifetime); + NM_CMP_FIELD(a, b, preferred); + NM_CMP_FIELD(a, b, n_ifa_flags); + NM_CMP_FIELD_UNSAFE(a, b, external); + return 0; } void -nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h) -{ - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - nm_hash_update_vals (h, - nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), - nm_utils_ip4_address_clear_host_address (obj->network, obj->plen), - obj->plen, - obj->metric, - obj->tos); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - nm_hash_update_vals (h, - obj->type_coerced, - nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), - nm_utils_ip4_address_clear_host_address (obj->network, obj->plen), - obj->plen, - obj->metric, - obj->tos, - /* on top of WEAK_ID: */ - obj->ifindex, - nmp_utils_ip_config_source_round_trip_rtprot (obj->rt_source), - _ip_route_scope_inv_get_normalized (obj), - obj->gateway, - obj->mss, - obj->pref_src, - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->r_rtm_flags & RTNH_F_ONLINK, - NM_HASH_COMBINE_BOOLS (guint8, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - nm_hash_update_vals (h, - obj->type_coerced, - nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), - obj->ifindex, - nm_utils_ip4_address_clear_host_address (obj->network, obj->plen), - obj->plen, - obj->metric, - obj->gateway, - nmp_utils_ip_config_source_round_trip_rtprot (obj->rt_source), - _ip_route_scope_inv_get_normalized (obj), - obj->tos, - obj->mss, - obj->pref_src, - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), - NM_HASH_COMBINE_BOOLS (guint8, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - nm_hash_update_vals (h, - obj->type_coerced, - obj->table_coerced, - obj->ifindex, - obj->network, - obj->plen, - obj->metric, - obj->gateway, - obj->rt_source, - obj->scope_inv, - obj->tos, - obj->mss, - obj->pref_src, - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->r_rtm_flags, - NM_HASH_COMBINE_BOOLS (guint8, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu)); - break; - } +nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, + NMPlatformIPRouteCmpType cmp_type, + NMHashState * h) +{ + switch (cmp_type) { + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: + nm_hash_update_vals( + h, + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), + nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), + obj->plen, + nm_platform_ip4_route_get_effective_metric(obj), + obj->tos, + NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any)); + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: + nm_hash_update_vals( + h, + obj->type_coerced, + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), + nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), + obj->plen, + nm_platform_ip4_route_get_effective_metric(obj), + obj->tos, + /* on top of WEAK_ID: */ + obj->ifindex, + nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), + _ip_route_scope_inv_get_normalized(obj), + obj->gateway, + obj->mss, + obj->pref_src, + obj->window, + obj->cwnd, + obj->initcwnd, + obj->initrwnd, + obj->mtu, + obj->r_rtm_flags & RTNH_F_ONLINK, + NM_HASH_COMBINE_BOOLS(guint8, + obj->metric_any, + obj->table_any, + obj->lock_window, + obj->lock_cwnd, + obj->lock_initcwnd, + obj->lock_initrwnd, + obj->lock_mtu)); + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: + nm_hash_update_vals( + h, + obj->type_coerced, + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), + obj->ifindex, + nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), + obj->plen, + nm_platform_ip4_route_get_effective_metric(obj), + obj->gateway, + nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), + _ip_route_scope_inv_get_normalized(obj), + obj->tos, + obj->mss, + obj->pref_src, + obj->window, + obj->cwnd, + obj->initcwnd, + obj->initrwnd, + obj->mtu, + obj->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), + NM_HASH_COMBINE_BOOLS(guint8, + obj->metric_any, + obj->table_any, + obj->lock_window, + obj->lock_cwnd, + obj->lock_initcwnd, + obj->lock_initrwnd, + obj->lock_mtu)); + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: + nm_hash_update_vals(h, + obj->type_coerced, + obj->table_coerced, + obj->ifindex, + obj->network, + obj->plen, + nm_platform_ip4_route_get_effective_metric(obj), + obj->gateway, + obj->rt_source, + obj->scope_inv, + obj->tos, + obj->mss, + obj->pref_src, + obj->window, + obj->cwnd, + obj->initcwnd, + obj->initrwnd, + obj->mtu, + obj->r_rtm_flags, + NM_HASH_COMBINE_BOOLS(guint8, + obj->metric_any, + obj->table_any, + obj->lock_window, + obj->lock_cwnd, + obj->lock_initcwnd, + obj->lock_initrwnd, + obj->lock_mtu)); + break; + } } int -nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteCmpType cmp_type) -{ - NM_CMP_SELF (a, b); - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE), - nm_platform_route_table_uncoerce (b->table_coerced, TRUE)); - NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (a->network, b->network, MIN (a->plen, b->plen)); - NM_CMP_FIELD (a, b, plen); - NM_CMP_FIELD (a, b, metric); - NM_CMP_FIELD (a, b, tos); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { - NM_CMP_FIELD (a, b, ifindex); - NM_CMP_FIELD (a, b, type_coerced); - NM_CMP_DIRECT (nmp_utils_ip_config_source_round_trip_rtprot (a->rt_source), - nmp_utils_ip_config_source_round_trip_rtprot (b->rt_source)); - NM_CMP_DIRECT (_ip_route_scope_inv_get_normalized (a), - _ip_route_scope_inv_get_normalized (b)); - NM_CMP_FIELD (a, b, gateway); - NM_CMP_FIELD (a, b, mss); - NM_CMP_FIELD (a, b, pref_src); - NM_CMP_FIELD (a, b, window); - NM_CMP_FIELD (a, b, cwnd); - NM_CMP_FIELD (a, b, initcwnd); - NM_CMP_FIELD (a, b, initrwnd); - NM_CMP_FIELD (a, b, mtu); - NM_CMP_DIRECT (a->r_rtm_flags & RTNH_F_ONLINK, - b->r_rtm_flags & RTNH_F_ONLINK); - NM_CMP_FIELD_UNSAFE (a, b, lock_window); - NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_initcwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_initrwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_mtu); - } - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - NM_CMP_FIELD (a, b, type_coerced); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE), - nm_platform_route_table_uncoerce (b->table_coerced, TRUE)); - } else - NM_CMP_FIELD (a, b, table_coerced); - NM_CMP_FIELD (a, b, ifindex); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (a->network, b->network, MIN (a->plen, b->plen)); - else - NM_CMP_FIELD (a, b, network); - NM_CMP_FIELD (a, b, plen); - NM_CMP_FIELD (a, b, metric); - NM_CMP_FIELD (a, b, gateway); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT (nmp_utils_ip_config_source_round_trip_rtprot (a->rt_source), - nmp_utils_ip_config_source_round_trip_rtprot (b->rt_source)); - NM_CMP_DIRECT (_ip_route_scope_inv_get_normalized (a), - _ip_route_scope_inv_get_normalized (b)); - } else { - NM_CMP_FIELD (a, b, rt_source); - NM_CMP_FIELD (a, b, scope_inv); - } - NM_CMP_FIELD (a, b, mss); - NM_CMP_FIELD (a, b, pref_src); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT (a->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), - b->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK)); - } else - NM_CMP_FIELD (a, b, r_rtm_flags); - NM_CMP_FIELD (a, b, tos); - NM_CMP_FIELD_UNSAFE (a, b, lock_window); - NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_initcwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_initrwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_mtu); - NM_CMP_FIELD (a, b, window); - NM_CMP_FIELD (a, b, cwnd); - NM_CMP_FIELD (a, b, initcwnd); - NM_CMP_FIELD (a, b, initrwnd); - NM_CMP_FIELD (a, b, mtu); - break; - } - return 0; +nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, + const NMPlatformIP4Route *b, + NMPlatformIPRouteCmpType cmp_type) +{ + NM_CMP_SELF(a, b); + switch (cmp_type) { + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: + NM_CMP_FIELD_UNSAFE(a, b, table_any); + NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); + NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen)); + NM_CMP_FIELD(a, b, plen); + NM_CMP_FIELD_UNSAFE(a, b, metric_any); + if (!a->metric_any) + NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD(a, b, tos); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { + NM_CMP_FIELD(a, b, ifindex); + NM_CMP_FIELD(a, b, type_coerced); + NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), + nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); + NM_CMP_DIRECT(_ip_route_scope_inv_get_normalized(a), + _ip_route_scope_inv_get_normalized(b)); + NM_CMP_FIELD(a, b, gateway); + NM_CMP_FIELD(a, b, mss); + NM_CMP_FIELD(a, b, pref_src); + NM_CMP_FIELD(a, b, window); + NM_CMP_FIELD(a, b, cwnd); + NM_CMP_FIELD(a, b, initcwnd); + NM_CMP_FIELD(a, b, initrwnd); + NM_CMP_FIELD(a, b, mtu); + NM_CMP_DIRECT(a->r_rtm_flags & RTNH_F_ONLINK, b->r_rtm_flags & RTNH_F_ONLINK); + NM_CMP_FIELD_UNSAFE(a, b, lock_window); + NM_CMP_FIELD_UNSAFE(a, b, lock_cwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_initcwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_initrwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_mtu); + } + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: + NM_CMP_FIELD(a, b, type_coerced); + NM_CMP_FIELD_UNSAFE(a, b, table_any); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); + } else + NM_CMP_FIELD(a, b, table_coerced); + NM_CMP_FIELD(a, b, ifindex); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen)); + else + NM_CMP_FIELD(a, b, network); + NM_CMP_FIELD(a, b, plen); + NM_CMP_FIELD_UNSAFE(a, b, metric_any); + if (!a->metric_any) + NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD(a, b, gateway); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), + nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); + NM_CMP_DIRECT(_ip_route_scope_inv_get_normalized(a), + _ip_route_scope_inv_get_normalized(b)); + } else { + NM_CMP_FIELD(a, b, rt_source); + NM_CMP_FIELD(a, b, scope_inv); + } + NM_CMP_FIELD(a, b, mss); + NM_CMP_FIELD(a, b, pref_src); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT(a->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK), + b->r_rtm_flags & (RTM_F_CLONED | RTNH_F_ONLINK)); + } else + NM_CMP_FIELD(a, b, r_rtm_flags); + NM_CMP_FIELD(a, b, tos); + NM_CMP_FIELD_UNSAFE(a, b, lock_window); + NM_CMP_FIELD_UNSAFE(a, b, lock_cwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_initcwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_initrwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_mtu); + NM_CMP_FIELD(a, b, window); + NM_CMP_FIELD(a, b, cwnd); + NM_CMP_FIELD(a, b, initcwnd); + NM_CMP_FIELD(a, b, initrwnd); + NM_CMP_FIELD(a, b, mtu); + break; + } + return 0; } void -nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h) -{ - struct in6_addr a1, a2; - - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - nm_hash_update_vals (h, - nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), - *nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen), - obj->plen, - obj->metric, - *nm_utils_ip6_address_clear_host_address (&a2, &obj->src, obj->src_plen), - obj->src_plen); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - nm_hash_update_vals (h, - obj->type_coerced, - nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), - *nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen), - obj->plen, - obj->metric, - *nm_utils_ip6_address_clear_host_address (&a2, &obj->src, obj->src_plen), - obj->src_plen, - /* on top of WEAK_ID: */ - obj->ifindex, - obj->gateway); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - nm_hash_update_vals (h, - obj->type_coerced, - nm_platform_route_table_uncoerce (obj->table_coerced, TRUE), - obj->ifindex, - *nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen), - obj->plen, - obj->metric, - obj->gateway, - obj->pref_src, - *nm_utils_ip6_address_clear_host_address (&a2, &obj->src, obj->src_plen), - obj->src_plen, - nmp_utils_ip_config_source_round_trip_rtprot (obj->rt_source), - obj->mss, - obj->r_rtm_flags & RTM_F_CLONED, - NM_HASH_COMBINE_BOOLS (guint8, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu), - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - _route_pref_normalize (obj->rt_pref)); - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - nm_hash_update_vals (h, - obj->type_coerced, - obj->table_coerced, - obj->ifindex, - obj->network, - obj->plen, - obj->metric, - obj->gateway, - obj->pref_src, - obj->src, - obj->src_plen, - obj->rt_source, - obj->mss, - obj->r_rtm_flags, - NM_HASH_COMBINE_BOOLS (guint8, - obj->lock_window, - obj->lock_cwnd, - obj->lock_initcwnd, - obj->lock_initrwnd, - obj->lock_mtu), - obj->window, - obj->cwnd, - obj->initcwnd, - obj->initrwnd, - obj->mtu, - obj->rt_pref); - break; - } +nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, + NMPlatformIPRouteCmpType cmp_type, + NMHashState * h) +{ + struct in6_addr a1, a2; + + switch (cmp_type) { + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: + nm_hash_update_vals( + h, + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), + *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), + obj->plen, + nm_platform_ip6_route_get_effective_metric(obj), + *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), + obj->src_plen, + NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any)); + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: + nm_hash_update_vals( + h, + obj->type_coerced, + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), + *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), + obj->plen, + nm_platform_ip6_route_get_effective_metric(obj), + *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), + obj->src_plen, + NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any), + /* on top of WEAK_ID: */ + obj->ifindex, + obj->gateway); + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: + nm_hash_update_vals( + h, + obj->type_coerced, + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), + obj->ifindex, + *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), + obj->plen, + nm_platform_ip6_route_get_effective_metric(obj), + obj->gateway, + obj->pref_src, + *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), + obj->src_plen, + nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), + obj->mss, + obj->r_rtm_flags & RTM_F_CLONED, + NM_HASH_COMBINE_BOOLS(guint8, + obj->metric_any, + obj->table_any, + obj->lock_window, + obj->lock_cwnd, + obj->lock_initcwnd, + obj->lock_initrwnd, + obj->lock_mtu), + obj->window, + obj->cwnd, + obj->initcwnd, + obj->initrwnd, + obj->mtu, + _route_pref_normalize(obj->rt_pref)); + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: + nm_hash_update_vals(h, + obj->type_coerced, + obj->table_coerced, + obj->ifindex, + obj->network, + nm_platform_ip6_route_get_effective_metric(obj), + obj->gateway, + obj->pref_src, + obj->src, + obj->src_plen, + obj->rt_source, + obj->mss, + obj->r_rtm_flags, + NM_HASH_COMBINE_BOOLS(guint8, + obj->metric_any, + obj->table_any, + obj->lock_window, + obj->lock_cwnd, + obj->lock_initcwnd, + obj->lock_initrwnd, + obj->lock_mtu), + obj->window, + obj->cwnd, + obj->initcwnd, + obj->initrwnd, + obj->mtu, + obj->rt_pref); + break; + } } int -nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, NMPlatformIPRouteCmpType cmp_type) -{ - NM_CMP_SELF (a, b); - switch (cmp_type) { - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: - NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE), - nm_platform_route_table_uncoerce (b->table_coerced, TRUE)); - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->network, &b->network, MIN (a->plen, b->plen)); - NM_CMP_FIELD (a, b, plen); - NM_CMP_FIELD (a, b, metric); - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->src, &b->src, MIN (a->src_plen, b->src_plen)); - NM_CMP_FIELD (a, b, src_plen); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { - NM_CMP_FIELD (a, b, ifindex); - NM_CMP_FIELD (a, b, type_coerced); - NM_CMP_FIELD_IN6ADDR (a, b, gateway); - } - break; - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: - case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: - NM_CMP_FIELD (a, b, type_coerced); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT (nm_platform_route_table_uncoerce (a->table_coerced, TRUE), - nm_platform_route_table_uncoerce (b->table_coerced, TRUE)); - } else - NM_CMP_FIELD (a, b, table_coerced); - NM_CMP_FIELD (a, b, ifindex); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->network, &b->network, MIN (a->plen, b->plen)); - else - NM_CMP_FIELD_IN6ADDR (a, b, network); - NM_CMP_FIELD (a, b, plen); - NM_CMP_FIELD (a, b, metric); - NM_CMP_FIELD_IN6ADDR (a, b, gateway); - NM_CMP_FIELD_IN6ADDR (a, b, pref_src); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->src, &b->src, MIN (a->src_plen, b->src_plen)); - NM_CMP_FIELD (a, b, src_plen); - NM_CMP_DIRECT (nmp_utils_ip_config_source_round_trip_rtprot (a->rt_source), - nmp_utils_ip_config_source_round_trip_rtprot (b->rt_source)); - } else { - NM_CMP_FIELD_IN6ADDR (a, b, src); - NM_CMP_FIELD (a, b, src_plen); - NM_CMP_FIELD (a, b, rt_source); - } - NM_CMP_FIELD (a, b, mss); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT (a->r_rtm_flags & RTM_F_CLONED, - b->r_rtm_flags & RTM_F_CLONED); - } else - NM_CMP_FIELD (a, b, r_rtm_flags); - NM_CMP_FIELD_UNSAFE (a, b, lock_window); - NM_CMP_FIELD_UNSAFE (a, b, lock_cwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_initcwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_initrwnd); - NM_CMP_FIELD_UNSAFE (a, b, lock_mtu); - NM_CMP_FIELD (a, b, window); - NM_CMP_FIELD (a, b, cwnd); - NM_CMP_FIELD (a, b, initcwnd); - NM_CMP_FIELD (a, b, initrwnd); - NM_CMP_FIELD (a, b, mtu); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT (_route_pref_normalize (a->rt_pref), _route_pref_normalize (b->rt_pref)); - else - NM_CMP_FIELD (a, b, rt_pref); - break; - } - return 0; -} - -#define _ROUTING_RULE_FLAGS_IGNORE ( FIB_RULE_UNRESOLVED \ - | FIB_RULE_IIF_DETACHED \ - | FIB_RULE_OIF_DETACHED) +nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, + const NMPlatformIP6Route *b, + NMPlatformIPRouteCmpType cmp_type) +{ + NM_CMP_SELF(a, b); + switch (cmp_type) { + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID: + NM_CMP_FIELD_UNSAFE(a, b, table_any); + NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); + NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen)); + NM_CMP_FIELD(a, b, plen); + NM_CMP_FIELD_UNSAFE(a, b, metric_any); + if (!a->metric_any) + NM_CMP_FIELD(a, b, metric); + NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen)); + NM_CMP_FIELD(a, b, src_plen); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { + NM_CMP_FIELD(a, b, ifindex); + NM_CMP_FIELD(a, b, type_coerced); + NM_CMP_FIELD_IN6ADDR(a, b, gateway); + } + break; + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: + case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL: + NM_CMP_FIELD(a, b, type_coerced); + NM_CMP_FIELD_UNSAFE(a, b, table_any); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), + nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); + } else + NM_CMP_FIELD(a, b, table_coerced); + NM_CMP_FIELD(a, b, ifindex); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen)); + else + NM_CMP_FIELD_IN6ADDR(a, b, network); + NM_CMP_FIELD(a, b, plen); + NM_CMP_FIELD_UNSAFE(a, b, metric_any); + if (!a->metric_any) + NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD_IN6ADDR(a, b, gateway); + NM_CMP_FIELD_IN6ADDR(a, b, pref_src); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen)); + NM_CMP_FIELD(a, b, src_plen); + NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), + nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); + } else { + NM_CMP_FIELD_IN6ADDR(a, b, src); + NM_CMP_FIELD(a, b, src_plen); + NM_CMP_FIELD(a, b, rt_source); + } + NM_CMP_FIELD(a, b, mss); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { + NM_CMP_DIRECT(a->r_rtm_flags & RTM_F_CLONED, b->r_rtm_flags & RTM_F_CLONED); + } else + NM_CMP_FIELD(a, b, r_rtm_flags); + NM_CMP_FIELD_UNSAFE(a, b, lock_window); + NM_CMP_FIELD_UNSAFE(a, b, lock_cwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_initcwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_initrwnd); + NM_CMP_FIELD_UNSAFE(a, b, lock_mtu); + NM_CMP_FIELD(a, b, window); + NM_CMP_FIELD(a, b, cwnd); + NM_CMP_FIELD(a, b, initcwnd); + NM_CMP_FIELD(a, b, initrwnd); + NM_CMP_FIELD(a, b, mtu); + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + NM_CMP_DIRECT(_route_pref_normalize(a->rt_pref), _route_pref_normalize(b->rt_pref)); + else + NM_CMP_FIELD(a, b, rt_pref); + break; + } + return 0; +} + +#define _ROUTING_RULE_FLAGS_IGNORE \ + (FIB_RULE_UNRESOLVED | FIB_RULE_IIF_DETACHED | FIB_RULE_OIF_DETACHED) #define _routing_rule_compare(cmp_type, kernel_support_type) \ - ( (cmp_type) == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL \ - || nm_platform_kernel_support_get (kernel_support_type)) + ((cmp_type) == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL \ + || nm_platform_kernel_support_get(kernel_support_type)) void -nm_platform_routing_rule_hash_update (const NMPlatformRoutingRule *obj, - NMPlatformRoutingRuleCmpType cmp_type, - NMHashState *h) -{ - gboolean cmp_full = TRUE; - gsize addr_size; - guint32 flags_mask = G_MAXUINT32; - - if (G_UNLIKELY (!NM_IN_SET (obj->addr_family, AF_INET, AF_INET6))) { - /* the address family is not one of the supported ones. That means, the - * instance will only compare equal to itself (pointer-equality). */ - nm_hash_update_val (h, (gconstpointer) obj); - return; - } - - switch (cmp_type) { - - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID: - - flags_mask &= ~_ROUTING_RULE_FLAGS_IGNORE; - - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY: - - cmp_full = FALSE; - - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL: - - nm_hash_update_vals (h, - obj->addr_family, - obj->tun_id, - obj->table, - obj->flags & flags_mask, - obj->priority, - obj->fwmark, - obj->fwmask, - ( ( cmp_full - || ( cmp_type == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY - && obj->action == FR_ACT_GOTO)) - ? obj->goto_target - : (guint32) 0u), - ( ( cmp_full - || obj->addr_family == AF_INET) - ? obj->flow - : (guint32) 0u), - NM_HASH_COMBINE_BOOLS (guint8, - ( _routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE) - ? obj->uid_range_has - : FALSE)), - obj->suppress_prefixlen_inverse, - obj->suppress_ifgroup_inverse, - ( _routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV) - ? ( cmp_full - ? (guint16) obj->l3mdev - : (guint16) !!obj->l3mdev) - : G_MAXUINT16), - obj->action, - obj->tos, - obj->src_len, - obj->dst_len, - ( _routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL) - ? (guint16) obj->protocol - : G_MAXUINT16)); - addr_size = nm_utils_addr_family_to_size (obj->addr_family); - if (cmp_full || obj->src_len > 0) - nm_hash_update (h, &obj->src, addr_size); - if (cmp_full || obj->dst_len > 0) - nm_hash_update (h, &obj->dst, addr_size); - if (_routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { - if (cmp_full || obj->uid_range_has) - nm_hash_update_valp (h, &obj->uid_range); - } - if (_routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { - nm_hash_update_val (h, obj->ip_proto); - nm_hash_update_valp (h, &obj->sport_range); - nm_hash_update_valp (h, &obj->dport_range); - } - nm_hash_update_str (h, obj->iifname); - nm_hash_update_str (h, obj->oifname); - return; - } - - nm_assert_not_reached (); +nm_platform_routing_rule_hash_update(const NMPlatformRoutingRule *obj, + NMPlatformRoutingRuleCmpType cmp_type, + NMHashState * h) +{ + gboolean cmp_full = TRUE; + gsize addr_size; + guint32 flags_mask = G_MAXUINT32; + + if (G_UNLIKELY(!NM_IN_SET(obj->addr_family, AF_INET, AF_INET6))) { + /* the address family is not one of the supported ones. That means, the + * instance will only compare equal to itself (pointer-equality). */ + nm_hash_update_val(h, (gconstpointer) obj); + return; + } + + switch (cmp_type) { + case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID: + + flags_mask &= ~_ROUTING_RULE_FLAGS_IGNORE; + + /* fall-through */ + case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY: + + cmp_full = FALSE; + + /* fall-through */ + case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL: + + nm_hash_update_vals( + h, + obj->addr_family, + obj->tun_id, + obj->table, + obj->flags & flags_mask, + obj->priority, + obj->fwmark, + obj->fwmask, + ((cmp_full + || (cmp_type == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY + && obj->action == FR_ACT_GOTO)) + ? obj->goto_target + : (guint32) 0u), + ((cmp_full || obj->addr_family == AF_INET) ? obj->flow : (guint32) 0u), + NM_HASH_COMBINE_BOOLS( + guint8, + (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE) + ? obj->uid_range_has + : FALSE)), + obj->suppress_prefixlen_inverse, + obj->suppress_ifgroup_inverse, + (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV) + ? (cmp_full ? (guint16) obj->l3mdev : (guint16) !!obj->l3mdev) + : G_MAXUINT16), + obj->action, + obj->tos, + obj->src_len, + obj->dst_len, + (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL) + ? (guint16) obj->protocol + : G_MAXUINT16)); + addr_size = nm_utils_addr_family_to_size(obj->addr_family); + if (cmp_full || obj->src_len > 0) + nm_hash_update(h, &obj->src, addr_size); + if (cmp_full || obj->dst_len > 0) + nm_hash_update(h, &obj->dst, addr_size); + if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { + if (cmp_full || obj->uid_range_has) + nm_hash_update_valp(h, &obj->uid_range); + } + if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { + nm_hash_update_val(h, obj->ip_proto); + nm_hash_update_valp(h, &obj->sport_range); + nm_hash_update_valp(h, &obj->dport_range); + } + nm_hash_update_str(h, obj->iifname); + nm_hash_update_str(h, obj->oifname); + return; + } + + nm_assert_not_reached(); } int -nm_platform_routing_rule_cmp (const NMPlatformRoutingRule *a, - const NMPlatformRoutingRule *b, - NMPlatformRoutingRuleCmpType cmp_type) -{ - gboolean cmp_full = TRUE; - gsize addr_size; - bool valid; - guint32 flags_mask = G_MAXUINT32; - - NM_CMP_SELF (a, b); +nm_platform_routing_rule_cmp(const NMPlatformRoutingRule *a, + const NMPlatformRoutingRule *b, + NMPlatformRoutingRuleCmpType cmp_type) +{ + gboolean cmp_full = TRUE; + gsize addr_size; + bool valid; + guint32 flags_mask = G_MAXUINT32; - valid = NM_IN_SET (a->addr_family, AF_INET, AF_INET6); - NM_CMP_DIRECT (valid, - (bool) NM_IN_SET (b->addr_family, AF_INET, AF_INET6)); + NM_CMP_SELF(a, b); - if (G_UNLIKELY (!valid)) { - /* the address family is not one of the supported ones. That means, the - * instance will only compare equal to itself. */ - NM_CMP_DIRECT ((uintptr_t) a, (uintptr_t) b); - nm_assert_not_reached (); - return 0; - } + valid = NM_IN_SET(a->addr_family, AF_INET, AF_INET6); + NM_CMP_DIRECT(valid, (bool) NM_IN_SET(b->addr_family, AF_INET, AF_INET6)); - switch (cmp_type) { + if (G_UNLIKELY(!valid)) { + /* the address family is not one of the supported ones. That means, the + * instance will only compare equal to itself. */ + NM_CMP_DIRECT((uintptr_t) a, (uintptr_t) b); + nm_assert_not_reached(); + return 0; + } - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID: + switch (cmp_type) { + case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID: - flags_mask &= ~_ROUTING_RULE_FLAGS_IGNORE; + flags_mask &= ~_ROUTING_RULE_FLAGS_IGNORE; - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY: + /* fall-through */ + case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY: - cmp_full = FALSE; + cmp_full = FALSE; - /* fall-through */ - case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL: - NM_CMP_FIELD (a, b, addr_family); - NM_CMP_FIELD (a, b, action); - NM_CMP_FIELD (a, b, priority); - NM_CMP_FIELD (a, b, tun_id); + /* fall-through */ + case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL: + NM_CMP_FIELD(a, b, addr_family); + NM_CMP_FIELD(a, b, action); + NM_CMP_FIELD(a, b, priority); + NM_CMP_FIELD(a, b, tun_id); - if (_routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV)) { - if (cmp_full) - NM_CMP_FIELD (a, b, l3mdev); - else - NM_CMP_FIELD_BOOL (a, b, l3mdev); - } + if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV)) { + if (cmp_full) + NM_CMP_FIELD(a, b, l3mdev); + else + NM_CMP_FIELD_BOOL(a, b, l3mdev); + } - NM_CMP_FIELD (a, b, table); + NM_CMP_FIELD(a, b, table); - NM_CMP_DIRECT (a->flags & flags_mask, b->flags & flags_mask); + NM_CMP_DIRECT(a->flags & flags_mask, b->flags & flags_mask); - NM_CMP_FIELD (a, b, fwmark); - NM_CMP_FIELD (a, b, fwmask); + NM_CMP_FIELD(a, b, fwmark); + NM_CMP_FIELD(a, b, fwmask); - if ( cmp_full - || ( cmp_type == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY - && a->action == FR_ACT_GOTO)) - NM_CMP_FIELD (a, b, goto_target); + if (cmp_full + || (cmp_type == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY + && a->action == FR_ACT_GOTO)) + NM_CMP_FIELD(a, b, goto_target); - NM_CMP_FIELD (a, b, suppress_prefixlen_inverse); - NM_CMP_FIELD (a, b, suppress_ifgroup_inverse); - NM_CMP_FIELD (a, b, tos); + NM_CMP_FIELD(a, b, suppress_prefixlen_inverse); + NM_CMP_FIELD(a, b, suppress_ifgroup_inverse); + NM_CMP_FIELD(a, b, tos); - if (cmp_full || a->addr_family == AF_INET) - NM_CMP_FIELD (a, b, flow); + if (cmp_full || a->addr_family == AF_INET) + NM_CMP_FIELD(a, b, flow); - if (_routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL)) - NM_CMP_FIELD (a, b, protocol); + if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL)) + NM_CMP_FIELD(a, b, protocol); - if (_routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { - NM_CMP_FIELD (a, b, ip_proto); - NM_CMP_FIELD (a, b, sport_range.start); - NM_CMP_FIELD (a, b, sport_range.end); - NM_CMP_FIELD (a, b, dport_range.start); - NM_CMP_FIELD (a, b, dport_range.end); - } + if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO)) { + NM_CMP_FIELD(a, b, ip_proto); + NM_CMP_FIELD(a, b, sport_range.start); + NM_CMP_FIELD(a, b, sport_range.end); + NM_CMP_FIELD(a, b, dport_range.start); + NM_CMP_FIELD(a, b, dport_range.end); + } - addr_size = nm_utils_addr_family_to_size (a->addr_family); + addr_size = nm_utils_addr_family_to_size(a->addr_family); - NM_CMP_FIELD (a, b, src_len); - if (cmp_full || a->src_len > 0) - NM_CMP_FIELD_MEMCMP_LEN (a, b, src, addr_size); + NM_CMP_FIELD(a, b, src_len); + if (cmp_full || a->src_len > 0) + NM_CMP_FIELD_MEMCMP_LEN(a, b, src, addr_size); - NM_CMP_FIELD (a, b, dst_len); - if (cmp_full || a->dst_len > 0) - NM_CMP_FIELD_MEMCMP_LEN (a, b, dst, addr_size); + NM_CMP_FIELD(a, b, dst_len); + if (cmp_full || a->dst_len > 0) + NM_CMP_FIELD_MEMCMP_LEN(a, b, dst, addr_size); - if (_routing_rule_compare (cmp_type, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { - NM_CMP_FIELD_UNSAFE (a, b, uid_range_has); - if (cmp_full || a->uid_range_has) { - NM_CMP_FIELD (a, b, uid_range.start); - NM_CMP_FIELD (a, b, uid_range.end); - } - } + if (_routing_rule_compare(cmp_type, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE)) { + NM_CMP_FIELD_UNSAFE(a, b, uid_range_has); + if (cmp_full || a->uid_range_has) { + NM_CMP_FIELD(a, b, uid_range.start); + NM_CMP_FIELD(a, b, uid_range.end); + } + } - NM_CMP_FIELD_STR (a, b, iifname); - NM_CMP_FIELD_STR (a, b, oifname); - return 0; - } + NM_CMP_FIELD_STR(a, b, iifname); + NM_CMP_FIELD_STR(a, b, oifname); + return 0; + } - nm_assert_not_reached (); - return 0; + nm_assert_not_reached(); + return 0; } /** @@ -7841,378 +8489,488 @@ nm_platform_routing_rule_cmp (const NMPlatformRoutingRule *a, * Returns: -1, 0, or 1 according to the comparison **/ int -nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b) +nm_platform_ip_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b) { - gint64 ta = 0, tb = 0; + gint64 ta = 0, tb = 0; - NM_CMP_SELF (a, b); + NM_CMP_SELF(a, b); - if (a->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0) - ta = G_MAXINT64; - else if (a->timestamp) - ta = ((gint64) a->timestamp) + a->lifetime; + if (a->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0) + ta = G_MAXINT64; + else if (a->timestamp) + ta = ((gint64) a->timestamp) + a->lifetime; - if (b->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || b->lifetime == 0) - tb = G_MAXINT64; - else if (b->timestamp) - tb = ((gint64) b->timestamp) + b->lifetime; + if (b->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || b->lifetime == 0) + tb = G_MAXINT64; + else if (b->timestamp) + tb = ((gint64) b->timestamp) + b->lifetime; - if (ta == tb) { - /* if the lifetime is equal, compare the preferred time. */ - ta = tb = 0; + if (ta == tb) { + /* if the lifetime is equal, compare the preferred time. */ + ta = tb = 0; - if (a->preferred == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0 /* lifetime==0 means permanent! */) - ta = G_MAXINT64; - else if (a->timestamp) - ta = ((gint64) a->timestamp) + a->preferred; + if (a->preferred == NM_PLATFORM_LIFETIME_PERMANENT + || a->lifetime == 0 /* lifetime==0 means permanent! */) + ta = G_MAXINT64; + else if (a->timestamp) + ta = ((gint64) a->timestamp) + a->preferred; - if (b->preferred == NM_PLATFORM_LIFETIME_PERMANENT|| b->lifetime == 0) - tb = G_MAXINT64; - else if (b->timestamp) - tb = ((gint64) b->timestamp) + b->preferred; + if (b->preferred == NM_PLATFORM_LIFETIME_PERMANENT || b->lifetime == 0) + tb = G_MAXINT64; + else if (b->timestamp) + tb = ((gint64) b->timestamp) + b->preferred; - if (ta == tb) - return 0; - } + if (ta == tb) + return 0; + } - return ta < tb ? -1 : 1; + return ta < tb ? -1 : 1; } +/*****************************************************************************/ + +GHashTable * +nm_platform_ip4_address_addr_to_hash(NMPlatform *self, int ifindex) +{ + const NMDedupMultiHeadEntry *head_entry; + NMDedupMultiIter iter; + const NMPObject * obj; + NMPLookup lookup; + GHashTable * hash; + + g_return_val_if_fail(NM_IS_PLATFORM(self), NULL); + g_return_val_if_fail(ifindex > 0, NULL); + + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex); + + head_entry = nmp_cache_lookup(NM_PLATFORM_GET_PRIVATE(self)->cache, &lookup); + + if (!head_entry) + return NULL; + + hash = g_hash_table_new(nm_direct_hash, NULL); + + nmp_cache_iter_for_each (&iter, head_entry, &obj) { + const NMPlatformIP4Address *a = NMP_OBJECT_CAST_IP4_ADDRESS(obj); + + g_hash_table_add(hash, GUINT_TO_POINTER(a->address)); + } + + return hash; +} + +/*****************************************************************************/ + const char * -nm_platform_signal_change_type_to_string (NMPlatformSignalChangeType change_type) +nm_platform_signal_change_type_to_string(NMPlatformSignalChangeType change_type) { - switch (change_type) { - case NM_PLATFORM_SIGNAL_ADDED: - return "added"; - case NM_PLATFORM_SIGNAL_CHANGED: - return "changed"; - case NM_PLATFORM_SIGNAL_REMOVED: - return "removed"; - default: - g_return_val_if_reached ("UNKNOWN"); - } + switch (change_type) { + case NM_PLATFORM_SIGNAL_ADDED: + return "added"; + case NM_PLATFORM_SIGNAL_CHANGED: + return "changed"; + case NM_PLATFORM_SIGNAL_REMOVED: + return "removed"; + default: + g_return_val_if_reached("UNKNOWN"); + } } static void -log_link (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformLink *device, NMPlatformSignalChangeType change_type, gpointer user_data) +log_link(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformLink * device, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - _LOG3D ("signal: link %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_link_to_string (device, NULL, 0)); + _LOG3D("signal: link %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_link_to_string(device, NULL, 0)); } static void -log_ip4_address (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP4Address *address, NMPlatformSignalChangeType change_type, gpointer user_data) +log_ip4_address(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformIP4Address * address, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - _LOG3D ("signal: address 4 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip4_address_to_string (address, NULL, 0)); + _LOG3D("signal: address 4 %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_ip4_address_to_string(address, NULL, 0)); } static void -log_ip6_address (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP6Address *address, NMPlatformSignalChangeType change_type, gpointer user_data) +log_ip6_address(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformIP6Address * address, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - _LOG3D ("signal: address 6 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip6_address_to_string (address, NULL, 0)); + _LOG3D("signal: address 6 %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_ip6_address_to_string(address, NULL, 0)); } static void -log_ip4_route (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP4Route *route, NMPlatformSignalChangeType change_type, gpointer user_data) +log_ip4_route(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformIP4Route * route, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - _LOG3D ("signal: route 4 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip4_route_to_string (route, NULL, 0)); + _LOG3D("signal: route 4 %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_ip4_route_to_string(route, NULL, 0)); } static void -log_ip6_route (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP6Route *route, NMPlatformSignalChangeType change_type, gpointer user_data) +log_ip6_route(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformIP6Route * route, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - _LOG3D ("signal: route 6 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip6_route_to_string (route, NULL, 0)); + _LOG3D("signal: route 6 %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_ip6_route_to_string(route, NULL, 0)); } static void -log_routing_rule (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformRoutingRule *routing_rule, NMPlatformSignalChangeType change_type, gpointer user_data) +log_routing_rule(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformRoutingRule * routing_rule, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - /* routing rules don't have an ifindex. We probably should refactor the signals that are emitted for platform changes. */ - _LOG3D ("signal: rt-rule %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_routing_rule_to_string (routing_rule, NULL, 0)); + /* routing rules don't have an ifindex. We probably should refactor the signals that are emitted for platform changes. */ + _LOG3D("signal: rt-rule %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_routing_rule_to_string(routing_rule, NULL, 0)); } static void -log_qdisc (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformQdisc *qdisc, NMPlatformSignalChangeType change_type, gpointer user_data) +log_qdisc(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformQdisc * qdisc, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - _LOG3D ("signal: qdisc %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_qdisc_to_string (qdisc, NULL, 0)); + _LOG3D("signal: qdisc %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_qdisc_to_string(qdisc, NULL, 0)); } static void -log_tfilter (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformTfilter *tfilter, NMPlatformSignalChangeType change_type, gpointer user_data) +log_tfilter(NMPlatform * self, + NMPObjectType obj_type, + int ifindex, + NMPlatformTfilter * tfilter, + NMPlatformSignalChangeType change_type, + gpointer user_data) { - _LOG3D ("signal: tfilter %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_tfilter_to_string (tfilter, NULL, 0)); + _LOG3D("signal: tfilter %7s: %s", + nm_platform_signal_change_type_to_string(change_type), + nm_platform_tfilter_to_string(tfilter, NULL, 0)); } /*****************************************************************************/ void -nm_platform_cache_update_emit_signal (NMPlatform *self, - NMPCacheOpsType cache_op, - const NMPObject *obj_old, - const NMPObject *obj_new) -{ - gboolean visible_new; - gboolean visible_old; - const NMPObject *o; - const NMPClass *klass; - int ifindex; - - nm_assert (NM_IN_SET ((NMPlatformSignalChangeType) cache_op, NM_PLATFORM_SIGNAL_NONE, - NM_PLATFORM_SIGNAL_ADDED, - NM_PLATFORM_SIGNAL_CHANGED, - NM_PLATFORM_SIGNAL_REMOVED)); - - ASSERT_nmp_cache_ops (nm_platform_get_cache (self), cache_op, obj_old, obj_new); - - NMTST_ASSERT_PLATFORM_NETNS_CURRENT (self); - - switch (cache_op) { - case NMP_CACHE_OPS_ADDED: - if (!nmp_object_is_visible (obj_new)) - return; - o = obj_new; - break; - case NMP_CACHE_OPS_UPDATED: - visible_old = nmp_object_is_visible (obj_old); - visible_new = nmp_object_is_visible (obj_new); - if (!visible_old && visible_new) { - o = obj_new; - cache_op = NMP_CACHE_OPS_ADDED; - } else if (visible_old && !visible_new) { - o = obj_old; - cache_op = NMP_CACHE_OPS_REMOVED; - } else if (!visible_new) { - /* it was invisible and stayed invisible. Nothing to do. */ - return; - } else - o = obj_new; - break; - case NMP_CACHE_OPS_REMOVED: - if (!nmp_object_is_visible (obj_old)) - return; - o = obj_old; - break; - default: - nm_assert (cache_op == NMP_CACHE_OPS_UNCHANGED); - return; - } - - klass = NMP_OBJECT_GET_CLASS (o); - - if (klass->obj_type == NMP_OBJECT_TYPE_ROUTING_RULE) - ifindex = 0; - else - ifindex = NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (o)->ifindex; - - if ( klass->obj_type == NMP_OBJECT_TYPE_IP4_ROUTE - && NM_PLATFORM_GET_PRIVATE (self)->ip4_dev_route_blacklist_gc_timeout_id - && NM_IN_SET (cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED)) - _ip4_dev_route_blacklist_notify_route (self, o); - - _LOG3t ("emit signal %s %s: %s", - klass->signal_type, - nm_platform_signal_change_type_to_string ((NMPlatformSignalChangeType) cache_op), - nmp_object_to_string (o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - - nmp_object_ref (o); - g_signal_emit (self, - _nm_platform_signal_id_get (klass->signal_type_id), - 0, - (int) klass->obj_type, - ifindex, - &o->object, - (int) cache_op); - nmp_object_unref (o); +nm_platform_cache_update_emit_signal(NMPlatform * self, + NMPCacheOpsType cache_op, + const NMPObject *obj_old, + const NMPObject *obj_new) +{ + gboolean visible_new; + gboolean visible_old; + const NMPObject *o; + const NMPClass * klass; + int ifindex; + + nm_assert(NM_IN_SET((NMPlatformSignalChangeType) cache_op, + NM_PLATFORM_SIGNAL_NONE, + NM_PLATFORM_SIGNAL_ADDED, + NM_PLATFORM_SIGNAL_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED)); + + ASSERT_nmp_cache_ops(nm_platform_get_cache(self), cache_op, obj_old, obj_new); + + NMTST_ASSERT_PLATFORM_NETNS_CURRENT(self); + + switch (cache_op) { + case NMP_CACHE_OPS_ADDED: + if (!nmp_object_is_visible(obj_new)) + return; + o = obj_new; + break; + case NMP_CACHE_OPS_UPDATED: + visible_old = nmp_object_is_visible(obj_old); + visible_new = nmp_object_is_visible(obj_new); + if (!visible_old && visible_new) { + o = obj_new; + cache_op = NMP_CACHE_OPS_ADDED; + } else if (visible_old && !visible_new) { + o = obj_old; + cache_op = NMP_CACHE_OPS_REMOVED; + } else if (!visible_new) { + /* it was invisible and stayed invisible. Nothing to do. */ + return; + } else + o = obj_new; + break; + case NMP_CACHE_OPS_REMOVED: + if (!nmp_object_is_visible(obj_old)) + return; + o = obj_old; + break; + default: + nm_assert(cache_op == NMP_CACHE_OPS_UNCHANGED); + return; + } + + klass = NMP_OBJECT_GET_CLASS(o); + + if (klass->obj_type == NMP_OBJECT_TYPE_ROUTING_RULE) + ifindex = 0; + else + ifindex = NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(o)->ifindex; + + if (klass->obj_type == NMP_OBJECT_TYPE_IP4_ROUTE + && NM_PLATFORM_GET_PRIVATE(self)->ip4_dev_route_blacklist_gc_timeout_id + && NM_IN_SET(cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED)) + _ip4_dev_route_blacklist_notify_route(self, o); + + _LOG3t("emit signal %s %s: %s", + klass->signal_type, + nm_platform_signal_change_type_to_string((NMPlatformSignalChangeType) cache_op), + nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + + nmp_object_ref(o); + g_signal_emit(self, + _nm_platform_signal_id_get(klass->signal_type_id), + 0, + (int) klass->obj_type, + ifindex, + &o->object, + (int) cache_op); + nmp_object_unref(o); } /*****************************************************************************/ NMPCache * -nm_platform_get_cache (NMPlatform *self) +nm_platform_get_cache(NMPlatform *self) { - return NM_PLATFORM_GET_PRIVATE (self)->cache; + return NM_PLATFORM_GET_PRIVATE(self)->cache; } NMPNetns * -nm_platform_netns_get (NMPlatform *self) +nm_platform_netns_get(NMPlatform *self) { - _CHECK_SELF (self, klass, NULL); + _CHECK_SELF(self, klass, NULL); - return self->_netns; + return self->_netns; } gboolean -nm_platform_netns_push (NMPlatform *self, NMPNetns **netns) +nm_platform_netns_push(NMPlatform *self, NMPNetns **netns) { - g_return_val_if_fail (NM_IS_PLATFORM (self), FALSE); + g_return_val_if_fail(NM_IS_PLATFORM(self), FALSE); - if ( self->_netns - && !nmp_netns_push (self->_netns)) { - NM_SET_OUT (netns, NULL); - return FALSE; - } + if (self->_netns && !nmp_netns_push(self->_netns)) { + NM_SET_OUT(netns, NULL); + return FALSE; + } - NM_SET_OUT (netns, self->_netns); - return TRUE; + NM_SET_OUT(netns, self->_netns); + return TRUE; } /*****************************************************************************/ const _NMPlatformVTableRouteUnion nm_platform_vtable_route = { - .v4 = { - .is_ip4 = TRUE, - .obj_type = NMP_OBJECT_TYPE_IP4_ROUTE, - .addr_family = AF_INET, - .sizeof_route = sizeof (NMPlatformIP4Route), - .route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip4_route_cmp, - .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip4_route_to_string, - }, - .v6 = { - .is_ip4 = FALSE, - .obj_type = NMP_OBJECT_TYPE_IP6_ROUTE, - .addr_family = AF_INET6, - .sizeof_route = sizeof (NMPlatformIP6Route), - .route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip6_route_cmp, - .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip6_route_to_string, - }, + .v4 = + { + .is_ip4 = TRUE, + .obj_type = NMP_OBJECT_TYPE_IP4_ROUTE, + .addr_family = AF_INET, + .sizeof_route = sizeof(NMPlatformIP4Route), + .route_cmp = (int (*)(const NMPlatformIPXRoute *a, + const NMPlatformIPXRoute *b, + NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip4_route_cmp, + .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, + char * buf, + gsize len)) nm_platform_ip4_route_to_string, + }, + .v6 = + { + .is_ip4 = FALSE, + .obj_type = NMP_OBJECT_TYPE_IP6_ROUTE, + .addr_family = AF_INET6, + .sizeof_route = sizeof(NMPlatformIP6Route), + .route_cmp = (int (*)(const NMPlatformIPXRoute *a, + const NMPlatformIPXRoute *b, + NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip6_route_cmp, + .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, + char * buf, + gsize len)) nm_platform_ip6_route_to_string, + }, }; /*****************************************************************************/ static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMPlatform *self = NM_PLATFORM (object); - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self); - - switch (prop_id) { - case PROP_NETNS_SUPPORT: - /* construct-only */ - if (g_value_get_boolean (value)) { - NMPNetns *netns; - - netns = nmp_netns_get_current (); - if (netns) - self->_netns = g_object_ref (netns); - } - break; - case PROP_USE_UDEV: - /* construct-only */ - priv->use_udev = g_value_get_boolean (value); - break; - case PROP_LOG_WITH_PTR: - /* construct-only */ - priv->log_with_ptr = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMPlatform * self = NM_PLATFORM(object); + NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); + + switch (prop_id) { + case PROP_NETNS_SUPPORT: + /* construct-only */ + if (g_value_get_boolean(value)) { + NMPNetns *netns; + + netns = nmp_netns_get_current(); + if (netns) + self->_netns = g_object_ref(netns); + } + break; + case PROP_USE_UDEV: + /* construct-only */ + priv->use_udev = g_value_get_boolean(value); + break; + case PROP_LOG_WITH_PTR: + /* construct-only */ + priv->log_with_ptr = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } static void -nm_platform_init (NMPlatform *self) +nm_platform_init(NMPlatform *self) { - self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_PLATFORM, NMPlatformPrivate); + self->_priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_PLATFORM, NMPlatformPrivate); } static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +constructor(GType type, guint n_construct_params, GObjectConstructParam *construct_params) { - GObject *object; - NMPlatform *self; - NMPlatformPrivate *priv; + GObject * object; + NMPlatform * self; + NMPlatformPrivate *priv; - object = G_OBJECT_CLASS (nm_platform_parent_class)->constructor (type, - n_construct_params, - construct_params); - self = NM_PLATFORM (object); - priv = NM_PLATFORM_GET_PRIVATE (self); + object = G_OBJECT_CLASS(nm_platform_parent_class) + ->constructor(type, n_construct_params, construct_params); + self = NM_PLATFORM(object); + priv = NM_PLATFORM_GET_PRIVATE(self); - priv->multi_idx = nm_dedup_multi_index_new (); + priv->multi_idx = nm_dedup_multi_index_new(); - priv->cache = nmp_cache_new (priv->multi_idx, - priv->use_udev); + priv->cache = nmp_cache_new(priv->multi_idx, priv->use_udev); - return object; + return object; } static void -finalize (GObject *object) +finalize(GObject *object) { - NMPlatform *self = NM_PLATFORM (object); - NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self); + NMPlatform * self = NM_PLATFORM(object); + NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE(self); - nm_clear_g_source (&priv->ip4_dev_route_blacklist_check_id); - nm_clear_g_source (&priv->ip4_dev_route_blacklist_gc_timeout_id); - nm_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); - g_clear_object (&self->_netns); - nm_dedup_multi_index_unref (priv->multi_idx); - nmp_cache_free (priv->cache); + nm_clear_g_source(&priv->ip4_dev_route_blacklist_check_id); + nm_clear_g_source(&priv->ip4_dev_route_blacklist_gc_timeout_id); + nm_clear_pointer(&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref); + g_clear_object(&self->_netns); + nm_dedup_multi_index_unref(priv->multi_idx); + nmp_cache_free(priv->cache); } static void -nm_platform_class_init (NMPlatformClass *platform_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (platform_class); - - g_type_class_add_private (object_class, sizeof (NMPlatformPrivate)); - - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->finalize = finalize; - - platform_class->wifi_set_powersave = wifi_set_powersave; - - g_object_class_install_property - (object_class, PROP_NETNS_SUPPORT, - g_param_spec_boolean (NM_PLATFORM_NETNS_SUPPORT, "", "", - NM_PLATFORM_NETNS_SUPPORT_DEFAULT, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_USE_UDEV, - g_param_spec_boolean (NM_PLATFORM_USE_UDEV, "", "", - FALSE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_LOG_WITH_PTR, - g_param_spec_boolean (NM_PLATFORM_LOG_WITH_PTR, "", "", - TRUE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - -#define SIGNAL(signal, signal_id, method) \ - G_STMT_START { \ - signals[signal] = \ - g_signal_new_class_handler (""signal_id"", \ - G_OBJECT_CLASS_TYPE (object_class), \ - G_SIGNAL_RUN_FIRST, \ - G_CALLBACK (method), \ - NULL, NULL, NULL, \ - G_TYPE_NONE, 4, \ - G_TYPE_INT, /* (int) NMPObjectType */ \ - G_TYPE_INT, /* ifindex */ \ - G_TYPE_POINTER /* const NMPObject * */, \ - G_TYPE_INT /* (int) NMPlatformSignalChangeType */ \ - ); \ - } G_STMT_END - - /* Signals */ - SIGNAL (NM_PLATFORM_SIGNAL_ID_LINK, NM_PLATFORM_SIGNAL_LINK_CHANGED, log_link); - SIGNAL (NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address); - SIGNAL (NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, log_ip6_address); - SIGNAL (NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route); - SIGNAL (NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route); - SIGNAL (NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED, log_routing_rule); - SIGNAL (NM_PLATFORM_SIGNAL_ID_QDISC, NM_PLATFORM_SIGNAL_QDISC_CHANGED, log_qdisc); - SIGNAL (NM_PLATFORM_SIGNAL_ID_TFILTER, NM_PLATFORM_SIGNAL_TFILTER_CHANGED, log_tfilter); +nm_platform_class_init(NMPlatformClass *platform_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(platform_class); + + g_type_class_add_private(object_class, sizeof(NMPlatformPrivate)); + + object_class->constructor = constructor; + object_class->set_property = set_property; + object_class->finalize = finalize; + + platform_class->wifi_set_powersave = wifi_set_powersave; + + g_object_class_install_property( + object_class, + PROP_NETNS_SUPPORT, + g_param_spec_boolean(NM_PLATFORM_NETNS_SUPPORT, + "", + "", + NM_PLATFORM_NETNS_SUPPORT_DEFAULT, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property( + object_class, + PROP_USE_UDEV, + g_param_spec_boolean(NM_PLATFORM_USE_UDEV, + "", + "", + FALSE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property( + object_class, + PROP_LOG_WITH_PTR, + g_param_spec_boolean(NM_PLATFORM_LOG_WITH_PTR, + "", + "", + TRUE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + +#define SIGNAL(signal, signal_id, method) \ + G_STMT_START \ + { \ + signals[signal] = \ + g_signal_new_class_handler("" signal_id "", \ + G_OBJECT_CLASS_TYPE(object_class), \ + G_SIGNAL_RUN_FIRST, \ + G_CALLBACK(method), \ + NULL, \ + NULL, \ + NULL, \ + G_TYPE_NONE, \ + 4, \ + G_TYPE_INT, /* (int) NMPObjectType */ \ + G_TYPE_INT, /* ifindex */ \ + G_TYPE_POINTER /* const NMPObject * */, \ + G_TYPE_INT /* (int) NMPlatformSignalChangeType */ \ + ); \ + } \ + G_STMT_END + + /* Signals */ + SIGNAL(NM_PLATFORM_SIGNAL_ID_LINK, NM_PLATFORM_SIGNAL_LINK_CHANGED, log_link); + SIGNAL(NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, + NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + log_ip4_address); + SIGNAL(NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, + NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + log_ip6_address); + SIGNAL(NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route); + SIGNAL(NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route); + SIGNAL(NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, + NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED, + log_routing_rule); + SIGNAL(NM_PLATFORM_SIGNAL_ID_QDISC, NM_PLATFORM_SIGNAL_QDISC_CHANGED, log_qdisc); + SIGNAL(NM_PLATFORM_SIGNAL_ID_TFILTER, NM_PLATFORM_SIGNAL_TFILTER_CHANGED, log_tfilter); } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 2b5d4914..c7b8017a 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2009 - 2018 Red Hat, Inc. */ @@ -15,20 +15,22 @@ #include "nm-setting-wireless.h" #include "nm-setting-ip-tunnel.h" -#define NM_TYPE_PLATFORM (nm_platform_get_type ()) -#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform)) -#define NM_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PLATFORM, NMPlatformClass)) -#define NM_IS_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_PLATFORM)) -#define NM_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PLATFORM)) -#define NM_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PLATFORM, NMPlatformClass)) +#define NM_TYPE_PLATFORM (nm_platform_get_type()) +#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_PLATFORM, NMPlatform)) +#define NM_PLATFORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_PLATFORM, NMPlatformClass)) +#define NM_IS_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_PLATFORM)) +#define NM_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_PLATFORM)) +#define NM_PLATFORM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_PLATFORM, NMPlatformClass)) -#define NM_PLATFORM_NETNS_SUPPORT_DEFAULT FALSE +#define NM_PLATFORM_NETNS_SUPPORT_DEFAULT FALSE /*****************************************************************************/ -#define NM_PLATFORM_NETNS_SUPPORT "netns-support" -#define NM_PLATFORM_USE_UDEV "use-udev" -#define NM_PLATFORM_LOG_WITH_PTR "log-with-ptr" +#define NM_PLATFORM_NETNS_SUPPORT "netns-support" +#define NM_PLATFORM_USE_UDEV "use-udev" +#define NM_PLATFORM_LOG_WITH_PTR "log-with-ptr" /*****************************************************************************/ @@ -42,277 +44,289 @@ struct _NMPWireGuardPeer; struct udev_device; -typedef gboolean (*NMPObjectPredicateFunc) (const NMPObject *obj, - gpointer user_data); +typedef gboolean (*NMPObjectPredicateFunc)(const NMPObject *obj, gpointer user_data); /* workaround for older libnl version, that does not define these flags. */ #ifndef IFA_F_MANAGETEMPADDR -#define IFA_F_MANAGETEMPADDR 0x100 + #define IFA_F_MANAGETEMPADDR 0x100 #endif #ifndef IFA_F_NOPREFIXROUTE -#define IFA_F_NOPREFIXROUTE 0x200 + #define IFA_F_NOPREFIXROUTE 0x200 #endif -#define NM_RT_SCOPE_LINK 253 /* RT_SCOPE_LINK */ +#define NM_RT_SCOPE_LINK 253 /* RT_SCOPE_LINK */ /* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers * that don't define it. */ -#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */ -#define NM_IN6_ADDR_GEN_MODE_EUI64 0 /* IN6_ADDR_GEN_MODE_EUI64 */ -#define NM_IN6_ADDR_GEN_MODE_NONE 1 /* IN6_ADDR_GEN_MODE_NONE */ -#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */ -#define NM_IN6_ADDR_GEN_MODE_RANDOM 3 /* IN6_ADDR_GEN_MODE_RANDOM */ +#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */ +#define NM_IN6_ADDR_GEN_MODE_EUI64 0 /* IN6_ADDR_GEN_MODE_EUI64 */ +#define NM_IN6_ADDR_GEN_MODE_NONE 1 /* IN6_ADDR_GEN_MODE_NONE */ +#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */ +#define NM_IN6_ADDR_GEN_MODE_RANDOM 3 /* IN6_ADDR_GEN_MODE_RANDOM */ -#define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */ +#define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */ /* Redefine this in host's endianness */ -#define NM_GRE_KEY 0x2000 +#define NM_GRE_KEY 0x2000 typedef enum { - NMP_NLM_FLAG_F_ECHO = 0x08, /* NLM_F_ECHO, Echo this request */ - - /* use our own platform enum for the nlmsg-flags. Otherwise, we'd have - * to include <linux/netlink.h> */ - NMP_NLM_FLAG_F_REPLACE = 0x100, /* NLM_F_REPLACE, Override existing */ - NMP_NLM_FLAG_F_EXCL = 0x200, /* NLM_F_EXCL, Do not touch, if it exists */ - NMP_NLM_FLAG_F_CREATE = 0x400, /* NLM_F_CREATE, Create, if it does not exist */ - NMP_NLM_FLAG_F_APPEND = 0x800, /* NLM_F_APPEND, Add to end of list */ - - NMP_NLM_FLAG_FMASK = 0xFFFF, /* a mask for all NMP_NLM_FLAG_F_* flags */ - - /* instructs NM to suppress logging an error message for any failures - * received from kernel. - * - * It will still log with debug-level, and it will still log - * other failures aside the kernel response. */ - NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE = 0x10000, - - /* the following aliases correspond to iproute2's `ip route CMD` for - * RTM_NEWROUTE, with CMD being one of add, change, replace, prepend, - * append and test. */ - NMP_NLM_FLAG_ADD = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_EXCL, - NMP_NLM_FLAG_CHANGE = NMP_NLM_FLAG_F_REPLACE, - NMP_NLM_FLAG_REPLACE = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_REPLACE, - NMP_NLM_FLAG_PREPEND = NMP_NLM_FLAG_F_CREATE, - NMP_NLM_FLAG_APPEND = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_APPEND, - NMP_NLM_FLAG_TEST = NMP_NLM_FLAG_F_EXCL, + NMP_NLM_FLAG_F_ECHO = 0x08, /* NLM_F_ECHO, Echo this request */ + + /* use our own platform enum for the nlmsg-flags. Otherwise, we'd have + * to include <linux/netlink.h> */ + NMP_NLM_FLAG_F_REPLACE = 0x100, /* NLM_F_REPLACE, Override existing */ + NMP_NLM_FLAG_F_EXCL = 0x200, /* NLM_F_EXCL, Do not touch, if it exists */ + NMP_NLM_FLAG_F_CREATE = 0x400, /* NLM_F_CREATE, Create, if it does not exist */ + NMP_NLM_FLAG_F_APPEND = 0x800, /* NLM_F_APPEND, Add to end of list */ + + NMP_NLM_FLAG_FMASK = 0xFFFF, /* a mask for all NMP_NLM_FLAG_F_* flags */ + + /* instructs NM to suppress logging an error message for any failures + * received from kernel. + * + * It will still log with debug-level, and it will still log + * other failures aside the kernel response. */ + NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE = 0x10000, + + /* the following aliases correspond to iproute2's `ip route CMD` for + * RTM_NEWROUTE, with CMD being one of add, change, replace, prepend, + * append and test. */ + NMP_NLM_FLAG_ADD = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_EXCL, + NMP_NLM_FLAG_CHANGE = NMP_NLM_FLAG_F_REPLACE, + NMP_NLM_FLAG_REPLACE = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_REPLACE, + NMP_NLM_FLAG_PREPEND = NMP_NLM_FLAG_F_CREATE, + NMP_NLM_FLAG_APPEND = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_APPEND, + NMP_NLM_FLAG_TEST = NMP_NLM_FLAG_F_EXCL, } NMPNlmFlags; typedef enum { - /* compare fields which kernel considers as similar routes. - * It is a looser comparisong then NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID - * and means that `ip route add` would fail to add two routes - * that have the same NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID. - * On the other hand, `ip route append` would allow that, as - * long as NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID differs. */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, - - /* compare two routes as kernel would allow to add them with - * `ip route append`. In other words, kernel does not allow you to - * add two routes (at the same time) which compare equal according - * to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID. - * - * For the ID we can only recognize route fields that we actually implement. - * However, kernel supports more routing options, some of them also part of - * the ID. NetworkManager is oblivious to these options and will wrongly think - * that two routes are idential, while they are not. That can lead to an - * inconsistent platform cache. Not much what we can do about that, except - * implementing all options that kernel supports *sigh*. See rh#1337860. - */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, - - /* compare all fields as they make sense for kernel. For example, - * a route destination 192.168.1.5/24 is not accepted by kernel and - * we treat it identical to 192.168.1.0/24. Semantically these - * routes are identical, but NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL will - * report them as different. - * - * The result shall be identical to call first nm_platform_ip_route_normalize() - * on both routes and then doing a full comparison. */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY, - - /* compare all fields. This should have the same effect as memcmp(), - * except allowing for undefined data in holes between field alignment. - */ - NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, + /* compare fields which kernel considers as similar routes. + * It is a looser comparisong then NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID + * and means that `ip route add` would fail to add two routes + * that have the same NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID. + * On the other hand, `ip route append` would allow that, as + * long as NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID differs. */ + NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, + + /* compare two routes as kernel would allow to add them with + * `ip route append`. In other words, kernel does not allow you to + * add two routes (at the same time) which compare equal according + * to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID. + * + * For the ID we can only recognize route fields that we actually implement. + * However, kernel supports more routing options, some of them also part of + * the ID. NetworkManager is oblivious to these options and will wrongly think + * that two routes are identical, while they are not. That can lead to an + * inconsistent platform cache. Not much what we can do about that, except + * implementing all options that kernel supports *sigh*. See rh#1337860. + */ + NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, + + /* compare all fields as they make sense for kernel. For example, + * a route destination 192.168.1.5/24 is not accepted by kernel and + * we treat it identical to 192.168.1.0/24. Semantically these + * routes are identical, but NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL will + * report them as different. + * + * The result shall be identical to call first nm_platform_ip_route_normalize() + * on both routes and then doing a full comparison. */ + NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY, + + /* compare all fields. This should have the same effect as memcmp(), + * except allowing for undefined data in holes between field alignment. + */ + NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, } NMPlatformIPRouteCmpType; typedef enum { - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY, + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY, - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL, + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL, } NMPlatformRoutingRuleCmpType; typedef struct { - guint8 data[20 /* NM_UTILS_HWADDR_LEN_MAX */ ]; - guint8 len; + union { + guint8 data[20 /* NM_UTILS_HWADDR_LEN_MAX */]; + NMEtherAddr ether_addr; + }; + guint8 len; } NMPLinkAddress; -gconstpointer nmp_link_address_get (const NMPLinkAddress *addr, size_t *length); -GBytes *nmp_link_address_get_as_bytes (const NMPLinkAddress *addr); +/* assert that NMEtherAddr does not affect the alignment of NMPLinkAddress struct. */ +G_STATIC_ASSERT(_nm_alignof(NMEtherAddr) == 1); +G_STATIC_ASSERT(_nm_alignof(NMPLinkAddress) == 1); + +gconstpointer nmp_link_address_get(const NMPLinkAddress *addr, size_t *length); +GBytes * nmp_link_address_get_as_bytes(const NMPLinkAddress *addr); typedef enum { - /* match-flags are strictly inclusive. That means, - * by default nothing is matched, but if you enable a particular - * flag, a candidate that matches passes the check. - * - * In other words: adding more flags can only extend the result - * set of matching objects. - * - * Also, the flags form partitions. Like, an address can be either of - * ADDRTYPE_NORMAL or ADDRTYPE_LINKLOCAL, but never both. Same for - * the ADDRSTATE match types. - */ - NM_PLATFORM_MATCH_WITH_NONE = 0, - - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL = (1LL << 0), - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL = (1LL << 1), - NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY = NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL, - - NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL = (1LL << 2), - NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE = (1LL << 3), - NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED = (1LL << 4), - NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY = NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED, + /* match-flags are strictly inclusive. That means, + * by default nothing is matched, but if you enable a particular + * flag, a candidate that matches passes the check. + * + * In other words: adding more flags can only extend the result + * set of matching objects. + * + * Also, the flags form partitions. Like, an address can be either of + * ADDRTYPE_NORMAL or ADDRTYPE_LINKLOCAL, but never both. Same for + * the ADDRSTATE match types. + */ + NM_PLATFORM_MATCH_WITH_NONE = 0, + + NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL = (1LL << 0), + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL = (1LL << 1), + NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY = + NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL | NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL, + + NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL = (1LL << 2), + NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE = (1LL << 3), + NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED = (1LL << 4), + NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY = NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED, } NMPlatformMatchFlags; -#define NM_PLATFORM_LINK_OTHER_NETNS (-1) +#define NM_PLATFORM_LINK_OTHER_NETNS (-1) struct _NMPlatformObject { - /* the object type has no fields of its own, it is only used to having - * a special pointer type that can be used to indicate "any" type. */ - char _dummy_don_t_use_me; + /* the object type has no fields of its own, it is only used to having + * a special pointer type that can be used to indicate "any" type. */ + char _dummy_don_t_use_me; }; #define __NMPlatformObjWithIfindex_COMMON \ - int ifindex; \ - ; + int ifindex; \ + ; struct _NMPlatformObjWithIfindex { - __NMPlatformObjWithIfindex_COMMON; + __NMPlatformObjWithIfindex_COMMON; }; struct _NMPlatformLink { - __NMPlatformObjWithIfindex_COMMON; - char name[NMP_IFNAMSIZ]; - NMLinkType type; + __NMPlatformObjWithIfindex_COMMON; + char name[NMP_IFNAMSIZ]; + NMLinkType type; - /* rtnl_link_get_type(), IFLA_INFO_KIND. */ - /* NMPlatform initializes this field with a static string. */ - const char *kind; + /* rtnl_link_get_type(), IFLA_INFO_KIND. */ + /* NMPlatform initializes this field with a static string. */ + const char *kind; - /* NMPlatform initializes this field with a static string. */ - const char *driver; + /* NMPlatform initializes this field with a static string. */ + const char *driver; - int master; + int master; - /* rtnl_link_get_link(), IFLA_LINK. - * If IFLA_LINK_NETNSID indicates that the parent is in another namespace, - * this field be set to (negative) NM_PLATFORM_LINK_OTHER_NETNS. */ - int parent; + /* rtnl_link_get_link(), IFLA_LINK. + * If IFLA_LINK_NETNSID indicates that the parent is in another namespace, + * this field be set to (negative) NM_PLATFORM_LINK_OTHER_NETNS. */ + int parent; - /* IFF_* flags. Note that the flags in 'struct ifinfomsg' are declared as 'unsigned'. */ - guint n_ifi_flags; + /* IFF_* flags. Note that the flags in 'struct ifinfomsg' are declared as 'unsigned'. */ + guint n_ifi_flags; - guint mtu; + guint mtu; - /* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */ - guint32 arptype; + /* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */ + guint32 arptype; - /* IFLA_ADDRESS */ - NMPLinkAddress l_address; + /* IFLA_ADDRESS */ + NMPLinkAddress l_address; - /* IFLA_BROADCAST */ - NMPLinkAddress l_broadcast; + /* IFLA_BROADCAST */ + NMPLinkAddress l_broadcast; - /* rtnl_link_inet6_get_token(), IFLA_INET6_TOKEN */ - NMUtilsIPv6IfaceId inet6_token; + /* rtnl_link_inet6_get_token(), IFLA_INET6_TOKEN */ + NMUtilsIPv6IfaceId inet6_token; - /* The bitwise inverse of rtnl_link_inet6_get_addr_gen_mode(). It is inverse - * to have a default of 0 -- meaning: unspecified. That way, a struct - * initialized with memset(0) has and unset value.*/ - guint8 inet6_addr_gen_mode_inv; + /* The bitwise inverse of rtnl_link_inet6_get_addr_gen_mode(). It is inverse + * to have a default of 0 -- meaning: unspecified. That way, a struct + * initialized with memset(0) has and unset value.*/ + guint8 inet6_addr_gen_mode_inv; - /* Statistics */ - guint64 rx_packets; - guint64 rx_bytes; - guint64 tx_packets; - guint64 tx_bytes; + /* Statistics */ + guint64 rx_packets; + guint64 rx_bytes; + guint64 tx_packets; + guint64 tx_bytes; - /* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters, - * where we coerce the link as disconnect if it has no slaves. */ - bool connected:1; + /* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters, + * where we coerce the link as disconnect if it has no slaves. */ + bool connected : 1; - bool initialized:1; + bool initialized : 1; }; typedef enum { /*< skip >*/ - NM_PLATFORM_SIGNAL_ID_NONE, - NM_PLATFORM_SIGNAL_ID_LINK, - NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, - NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, - NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, - NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, - NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, - NM_PLATFORM_SIGNAL_ID_QDISC, - NM_PLATFORM_SIGNAL_ID_TFILTER, - _NM_PLATFORM_SIGNAL_ID_LAST, + NM_PLATFORM_SIGNAL_ID_NONE, + NM_PLATFORM_SIGNAL_ID_LINK, + NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, + NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, + NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, + NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, + NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, + NM_PLATFORM_SIGNAL_ID_QDISC, + NM_PLATFORM_SIGNAL_ID_TFILTER, + _NM_PLATFORM_SIGNAL_ID_LAST, } NMPlatformSignalIdType; -guint _nm_platform_signal_id_get (NMPlatformSignalIdType signal_type); +guint _nm_platform_signal_id_get(NMPlatformSignalIdType signal_type); typedef enum { - NM_PLATFORM_SIGNAL_NONE, - NM_PLATFORM_SIGNAL_ADDED, - NM_PLATFORM_SIGNAL_CHANGED, - NM_PLATFORM_SIGNAL_REMOVED, + NM_PLATFORM_SIGNAL_NONE, + NM_PLATFORM_SIGNAL_ADDED, + NM_PLATFORM_SIGNAL_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, } NMPlatformSignalChangeType; #define NM_PLATFORM_IP_ADDRESS_CAST(address) \ - NM_CONSTCAST (NMPlatformIPAddress, (address), NMPlatformIPXAddress, NMPlatformIP4Address, NMPlatformIP6Address) - -#define __NMPlatformIPAddress_COMMON \ - __NMPlatformObjWithIfindex_COMMON; \ - NMIPConfigSource addr_source; \ - \ - /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*(). - * - * The rules are: - * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses - * are permanent. This rule is so that unset addresses (calloc) are permanent by default. - * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly - * set to 0). Such addresses are permanent. - * 3 Non permanent addresses should (almost) always have @timestamp > 0. 0 is not a valid timestamp - * and never returned by nm_utils_get_monotonic_timestamp_sec(). In this case @valid/@preferred - * is anchored at @timestamp. - * 4 Non permanent addresses with @timestamp == 0 are implicitly anchored at *now*, thus the time - * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add(). - * - * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the - * lease was received. Addresses from kernel might have the @timestamp based on the last modification - * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring - * @lifetime and @preferred. - */ \ - guint32 timestamp; \ - guint32 lifetime; /* seconds since timestamp */ \ - guint32 preferred; /* seconds since timestamp */ \ - \ - /* ifa_flags in 'struct ifaddrmsg' from <linux/if_addr.h>, extended to 32 bit by - * IFA_FLAGS attribute. */ \ - guint32 n_ifa_flags; \ - \ - guint8 plen; \ - \ - bool external:1; \ - \ - bool use_ip4_broadcast_address:1; \ - ; + NM_CONSTCAST(NMPlatformIPAddress, \ + (address), \ + NMPlatformIPXAddress, \ + NMPlatformIP4Address, \ + NMPlatformIP6Address) + +#define __NMPlatformIPAddress_COMMON \ + __NMPlatformObjWithIfindex_COMMON; \ + NMIPConfigSource addr_source; \ + \ + /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*(). + * + * The rules are: + * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses + * are permanent. This rule is so that unset addresses (calloc) are permanent by default. + * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly + * set to 0). Such addresses are permanent. + * 3 Non permanent addresses should (almost) always have @timestamp > 0. 0 is not a valid timestamp + * and never returned by nm_utils_get_monotonic_timestamp_sec(). In this case @valid/@preferred + * is anchored at @timestamp. + * 4 Non permanent addresses with @timestamp == 0 are implicitly anchored at *now*, thus the time + * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add(). + * + * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the + * lease was received. Addresses from kernel might have the @timestamp based on the last modification + * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring + * @lifetime and @preferred. + */ \ + guint32 timestamp; \ + guint32 lifetime; /* seconds since timestamp */ \ + guint32 preferred; /* seconds since timestamp */ \ + \ + /* ifa_flags in 'struct ifaddrmsg' from <linux/if_addr.h>, extended to 32 bit by + * IFA_FLAGS attribute. */ \ + guint32 n_ifa_flags; \ + \ + guint8 plen; \ + \ + /* FIXME(l3cfg): the external marker won't be necessary anymore, because we only + * merge addresses we care about, and ignore (don't remove) external addresses. */ \ + bool external : 1; \ + \ + bool use_ip4_broadcast_address : 1; \ + ; /** * NMPlatformIPAddress: @@ -320,11 +334,11 @@ typedef enum { * Common parts of NMPlatformIP4Address and NMPlatformIP6Address. **/ typedef struct { - __NMPlatformIPAddress_COMMON; - union { - guint8 address_ptr[1]; - guint32 __dummy_for_32bit_alignment; - }; + __NMPlatformIPAddress_COMMON; + union { + guint8 address_ptr[1]; + guint32 __dummy_for_32bit_alignment; + }; } NMPlatformIPAddress; /** @@ -332,29 +346,29 @@ typedef struct { * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec() **/ struct _NMPlatformIP4Address { - __NMPlatformIPAddress_COMMON; - - /* The local address IFA_LOCAL. */ - in_addr_t address; - - /* The IFA_ADDRESS PTP peer address. This field is rather important, because - * it constitutes the identifier for the IPv4 address (e.g. you can add two - * addresses that only differ by their peer's network-part. - * - * Beware that for most cases, NetworkManager doesn't want to set an explicit - * peer-address. Hoever, that corresponds to setting the peer address to @address - * itself. Leaving peer-address unset/zero, means explicitly setting the peer - * address to 0.0.0.0, which you probably don't want. - * */ - in_addr_t peer_address; /* PTP peer address */ - - /* IFA_BROADCAST. - * - * This parameter is ignored unless use_ip4_broadcast_address is TRUE. - * See nm_platform_ip4_broadcast_address_from_addr(). */ - in_addr_t broadcast_address; - - char label[NMP_IFNAMSIZ]; + __NMPlatformIPAddress_COMMON; + + /* The local address IFA_LOCAL. */ + in_addr_t address; + + /* The IFA_ADDRESS PTP peer address. This field is rather important, because + * it constitutes the identifier for the IPv4 address (e.g. you can add two + * addresses that only differ by their peer's network-part. + * + * Beware that for most cases, NetworkManager doesn't want to set an explicit + * peer-address. However, that corresponds to setting the peer address to @address + * itself. Leaving peer-address unset/zero, means explicitly setting the peer + * address to 0.0.0.0, which you probably don't want. + * */ + in_addr_t peer_address; /* PTP peer address */ + + /* IFA_BROADCAST. + * + * This parameter is ignored unless use_ip4_broadcast_address is TRUE. + * See nm_platform_ip4_broadcast_address_from_addr(). */ + in_addr_t broadcast_address; + + char label[NMP_IFNAMSIZ]; }; /** @@ -362,618 +376,676 @@ struct _NMPlatformIP4Address { * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_sec() **/ struct _NMPlatformIP6Address { - __NMPlatformIPAddress_COMMON; - struct in6_addr address; - struct in6_addr peer_address; + __NMPlatformIPAddress_COMMON; + struct in6_addr address; + struct in6_addr peer_address; }; typedef union { - NMPlatformIPAddress ax; - NMPlatformIP4Address a4; - NMPlatformIP6Address a6; + NMPlatformIPAddress ax; + NMPlatformIP4Address a4; + NMPlatformIP6Address a6; } NMPlatformIPXAddress; #undef __NMPlatformIPAddress_COMMON +#define NM_PLATFORM_IP4_ADDRESS_INIT(...) (&((const NMPlatformIP4Address){__VA_ARGS__})) + +#define NM_PLATFORM_IP6_ADDRESS_INIT(...) (&((const NMPlatformIP6Address){__VA_ARGS__})) + /* Default value for adding an IPv4 route. This is also what iproute2 does. * Note that contrary to IPv6, you can add routes with metric 0 and it is even * the default. */ -#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 0 +#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 ((guint32) 0u) /* Default value for adding an IPv6 route. This is also what iproute2 does. * Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024). * * Note that kernel doesn't allow adding IPv6 routes with metric zero via netlink. * It however can itself add routes with metric zero. */ -#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 1024 +#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 ((guint32) 1024u) /* For IPv4, kernel adds a device route (subnet routes) with metric 0 when user * configures addresses. */ -#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE 0 - -#define __NMPlatformIPRoute_COMMON \ - __NMPlatformObjWithIfindex_COMMON; \ - \ - /* The NMIPConfigSource. For routes that we receive from cache this corresponds - * to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values). - * When adding a route, the source will be coerced to the protocol using - * nmp_utils_ip_config_source_coerce_to_rtprot(). - * - * rtm_protocol is part of the primary key of an IPv4 route (meaning, you can add - * two IPv4 routes that only differ in their rtm_protocol. For IPv6, that is not - * the case. - * - * When deleting an IPv4/IPv6 route, the rtm_protocol field must match (even - * if it is not part of the primary key for IPv6) -- unless rtm_protocol is set - * to zero, in which case the first matching route (with proto ignored) is deleted. */ \ - NMIPConfigSource rt_source; \ - \ - guint8 plen; \ - \ - /* RTA_METRICS: - * - * For IPv4 routes, these properties are part of their - * ID (meaning: you can add otherwise idential IPv4 routes that - * only differ by the metric property). - * On the other hand, for IPv6 you cannot add two IPv6 routes that only differ - * by an RTA_METRICS property. - * - * When deleting a route, kernel seems to ignore the RTA_METRICS properties. - * That is a problem/bug for IPv4 because you cannot explicitly select which - * route to delete. Kernel just picks the first. See rh#1475642. */ \ - \ - /* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \ - bool lock_window:1; \ - bool lock_cwnd:1; \ - bool lock_initcwnd:1; \ - bool lock_initrwnd:1; \ - bool lock_mtu:1; \ - \ - /* rtnh_flags - * - * Routes with rtm_flags RTM_F_CLONED are hidden by platform and - * do not exist from the point-of-view of platform users. - * Such a route is not alive, according to nmp_object_is_alive(). - * - * NOTE: currently we ignore all flags except RTM_F_CLONED - * and RTNH_F_ONLINK. - * We also may not properly consider the flags as part of the ID - * in route-cmp. */ \ - unsigned r_rtm_flags; \ - \ - /* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \ - guint32 mss; \ - \ - /* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \ - guint32 window; \ - \ - /* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \ - guint32 cwnd; \ - \ - /* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \ - guint32 initcwnd; \ - \ - /* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \ - guint32 initrwnd; \ - \ - /* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \ - guint32 mtu; \ - \ - \ - /* RTA_PRIORITY (iproute2: metric) */ \ - guint32 metric; \ - \ - /* rtm_table, RTA_TABLE. - * - * This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and - * zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main - * table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \ - guint32 table_coerced; \ - \ - /* rtm_type. - * - * This is not the original type, if type_coerced is 0 then - * it means RTN_UNSPEC otherwise the type value is preserved. - * */ \ - guint8 type_coerced; \ - \ - /*end*/ +#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE ((guint32) 0u) + +#define __NMPlatformIPRoute_COMMON \ + __NMPlatformObjWithIfindex_COMMON; \ + \ + /* The NMIPConfigSource. For routes that we receive from cache this corresponds + * to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values). + * When adding a route, the source will be coerced to the protocol using + * nmp_utils_ip_config_source_coerce_to_rtprot(). + * + * rtm_protocol is part of the primary key of an IPv4 route (meaning, you can add + * two IPv4 routes that only differ in their rtm_protocol. For IPv6, that is not + * the case. + * + * When deleting an IPv4/IPv6 route, the rtm_protocol field must match (even + * if it is not part of the primary key for IPv6) -- unless rtm_protocol is set + * to zero, in which case the first matching route (with proto ignored) is deleted. */ \ + NMIPConfigSource rt_source; \ + \ + guint8 plen; \ + \ + /* RTA_METRICS: + * + * For IPv4 routes, these properties are part of their + * ID (meaning: you can add otherwise identical IPv4 routes that + * only differ by the metric property). + * On the other hand, for IPv6 you cannot add two IPv6 routes that only differ + * by an RTA_METRICS property. + * + * When deleting a route, kernel seems to ignore the RTA_METRICS properties. + * That is a problem/bug for IPv4 because you cannot explicitly select which + * route to delete. Kernel just picks the first. See rh#1475642. */ \ + \ + /* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \ + bool lock_window : 1; \ + bool lock_cwnd : 1; \ + bool lock_initcwnd : 1; \ + bool lock_initrwnd : 1; \ + bool lock_mtu : 1; \ + \ + /* if TRUE, the "metric" field gets ignored and can be overridden with settings from + * the device. This is to track routes that should be configured (e.g. from a DHCP + * lease), but where the actual metric is determined by NMDevice. */ \ + bool metric_any : 1; \ + \ + /* like "metric_any", the table is determined by other layers of the code. + * This field overrides "table_coerced" field. */ \ + bool table_any : 1; \ + \ + /* rtnh_flags + * + * Routes with rtm_flags RTM_F_CLONED are hidden by platform and + * do not exist from the point-of-view of platform users. + * Such a route is not alive, according to nmp_object_is_alive(). + * + * NOTE: currently we ignore all flags except RTM_F_CLONED + * and RTNH_F_ONLINK. + * We also may not properly consider the flags as part of the ID + * in route-cmp. */ \ + unsigned r_rtm_flags; \ + \ + /* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \ + guint32 mss; \ + \ + /* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \ + guint32 window; \ + \ + /* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \ + guint32 cwnd; \ + \ + /* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \ + guint32 initcwnd; \ + \ + /* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \ + guint32 initrwnd; \ + \ + /* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \ + guint32 mtu; \ + \ + /* RTA_PRIORITY (iproute2: metric) */ \ + guint32 metric; \ + \ + /* rtm_table, RTA_TABLE. + * + * This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and + * zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main + * table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \ + guint32 table_coerced; \ + \ + /* rtm_type. + * + * This is not the original type, if type_coerced is 0 then + * it means RTN_UNSPEC otherwise the type value is preserved. + * */ \ + guint8 type_coerced; \ + \ + /*end*/ typedef struct { - __NMPlatformIPRoute_COMMON; - union { - guint8 network_ptr[1]; - guint32 __dummy_for_32bit_alignment; - }; + __NMPlatformIPRoute_COMMON; + union { + guint8 network_ptr[1]; + guint32 __dummy_for_32bit_alignment; + }; } NMPlatformIPRoute; #define NM_PLATFORM_IP_ROUTE_CAST(route) \ - NM_CONSTCAST (NMPlatformIPRoute, (route), NMPlatformIPXRoute, NMPlatformIP4Route, NMPlatformIP6Route) + NM_CONSTCAST(NMPlatformIPRoute, \ + (route), \ + NMPlatformIPXRoute, \ + NMPlatformIP4Route, \ + NMPlatformIP6Route) -#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \ - (NM_PLATFORM_IP_ROUTE_CAST (route)->plen <= 0) +#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) (NM_PLATFORM_IP_ROUTE_CAST(route)->plen <= 0) struct _NMPlatformIP4Route { - __NMPlatformIPRoute_COMMON; - in_addr_t network; - - /* RTA_GATEWAY. The gateway is part of the primary key for a route */ - in_addr_t gateway; - - /* RTA_PREFSRC (called "src" by iproute2). - * - * pref_src is part of the ID of an IPv4 route. When deleting a route, - * pref_src must match, unless set to 0.0.0.0 to match any. */ - in_addr_t pref_src; - - /* rtm_tos (iproute2: tos) - * - * For IPv4, tos is part of the weak-id (like metric). - * - * For IPv6, tos is ignored by kernel. */ - guint8 tos; - - /* The bitwise inverse of the route scope rtm_scope. It is inverted so that the - * default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv() - * to convert back and forth between the inverse representation and the - * real value. - * - * rtm_scope is part of the primary key for IPv4 routes. When deleting a route, - * the scope must match, unless it is left at RT_SCOPE_NOWHERE, in which case the first - * matching route is deleted. - * - * For IPv6 routes, the scope is ignored and kernel always assumes global scope. - * Hence, this field is only in NMPlatformIP4Route. */ - guint8 scope_inv; + __NMPlatformIPRoute_COMMON; + in_addr_t network; + + /* RTA_GATEWAY. The gateway is part of the primary key for a route */ + in_addr_t gateway; + + /* RTA_PREFSRC (called "src" by iproute2). + * + * pref_src is part of the ID of an IPv4 route. When deleting a route, + * pref_src must match, unless set to 0.0.0.0 to match any. */ + in_addr_t pref_src; + + /* rtm_tos (iproute2: tos) + * + * For IPv4, tos is part of the weak-id (like metric). + * + * For IPv6, tos is ignored by kernel. */ + guint8 tos; + + /* The bitwise inverse of the route scope rtm_scope. It is inverted so that the + * default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv() + * to convert back and forth between the inverse representation and the + * real value. + * + * rtm_scope is part of the primary key for IPv4 routes. When deleting a route, + * the scope must match, unless it is left at RT_SCOPE_NOWHERE, in which case the first + * matching route is deleted. + * + * For IPv6 routes, the scope is ignored and kernel always assumes global scope. + * Hence, this field is only in NMPlatformIP4Route. */ + guint8 scope_inv; }; struct _NMPlatformIP6Route { - __NMPlatformIPRoute_COMMON; - struct in6_addr network; - - /* RTA_GATEWAY. The gateway is part of the primary key for a route */ - struct in6_addr gateway; - - /* RTA_PREFSRC (called "src" by iproute2). - * - * pref_src is not part of the ID for an IPv6 route. You cannot add two - * routes that only differ by pref_src. - * - * When deleting a route, pref_src is ignored by kernel. */ - struct in6_addr pref_src; - - /* RTA_SRC and rtm_src_len (called "from" by iproute2). - * - * Kernel clears the host part of src/src_plen. - * - * src/src_plen is part of the ID of a route just like network/plen. That is, - * Not only `ip route append`, but also `ip route add` allows to add routes that only - * differ in their src/src_plen. - */ - struct in6_addr src; - guint8 src_plen; - - /* RTA_PREF router preference. - * - * The type is guint8 to keep the struct size small. But the values are compatible with - * the NMIcmpv6RouterPref enum. */ - guint8 rt_pref; + __NMPlatformIPRoute_COMMON; + struct in6_addr network; + + /* RTA_GATEWAY. The gateway is part of the primary key for a route */ + struct in6_addr gateway; + + /* RTA_PREFSRC (called "src" by iproute2). + * + * pref_src is not part of the ID for an IPv6 route. You cannot add two + * routes that only differ by pref_src. + * + * When deleting a route, pref_src is ignored by kernel. */ + struct in6_addr pref_src; + + /* RTA_SRC and rtm_src_len (called "from" by iproute2). + * + * Kernel clears the host part of src/src_plen. + * + * src/src_plen is part of the ID of a route just like network/plen. That is, + * Not only `ip route append`, but also `ip route add` allows to add routes that only + * differ in their src/src_plen. + */ + struct in6_addr src; + guint8 src_plen; + + /* RTA_PREF router preference. + * + * The type is guint8 to keep the struct size small. But the values are compatible with + * the NMIcmpv6RouterPref enum. */ + guint8 rt_pref; }; typedef union { - NMPlatformIPRoute rx; - NMPlatformIP4Route r4; - NMPlatformIP6Route r6; + NMPlatformIPRoute rx; + NMPlatformIP4Route r4; + NMPlatformIP6Route r6; } NMPlatformIPXRoute; #undef __NMPlatformIPRoute_COMMON typedef struct { - /* struct fib_rule_uid_range */ - guint32 start; - guint32 end; + /* struct fib_rule_uid_range */ + guint32 start; + guint32 end; } NMFibRuleUidRange; typedef struct { - /* struct fib_rule_port_range */ - guint16 start; - guint16 end; + /* struct fib_rule_port_range */ + guint16 start; + guint16 end; } NMFibRulePortRange; typedef struct { - NMIPAddr src; /* FRA_SRC */ - NMIPAddr dst; /* FRA_DST */ - guint64 tun_id; /* betoh64(FRA_TUN_ID) */ - guint32 table; /* (struct fib_rule_hdr).table, FRA_TABLE */ - guint32 flags; /* (struct fib_rule_hdr).flags */ - guint32 priority; /* RA_PRIORITY */ - guint32 fwmark; /* FRA_FWMARK */ - guint32 fwmask; /* FRA_FWMASK */ - guint32 goto_target; /* FRA_GOTO */ - guint32 flow; /* FRA_FLOW */ - guint32 suppress_prefixlen_inverse; /* ~(FRA_SUPPRESS_PREFIXLEN) */ - guint32 suppress_ifgroup_inverse; /* ~(FRA_SUPPRESS_IFGROUP) */ - NMFibRuleUidRange uid_range; /* FRA_UID_RANGE */ - NMFibRulePortRange sport_range; /* FRA_SPORT_RANGE */ - NMFibRulePortRange dport_range; /* FRA_DPORT_RANGE */ - char iifname[NMP_IFNAMSIZ]; /* FRA_IIFNAME */ - char oifname[NMP_IFNAMSIZ]; /* FRA_OIFNAME */ - guint8 addr_family; /* (struct fib_rule_hdr).family */ - guint8 action; /* (struct fib_rule_hdr).action */ - guint8 tos; /* (struct fib_rule_hdr).tos */ - guint8 src_len; /* (struct fib_rule_hdr).src_len */ - guint8 dst_len; /* (struct fib_rule_hdr).dst_len */ - guint8 l3mdev; /* FRA_L3MDEV */ - guint8 protocol; /* FRA_PROTOCOL */ - guint8 ip_proto; /* FRA_IP_PROTO */ - - bool uid_range_has:1; /* has(FRA_UID_RANGE) */ + NMIPAddr src; /* FRA_SRC */ + NMIPAddr dst; /* FRA_DST */ + guint64 tun_id; /* betoh64(FRA_TUN_ID) */ + guint32 table; /* (struct fib_rule_hdr).table, FRA_TABLE */ + guint32 flags; /* (struct fib_rule_hdr).flags */ + guint32 priority; /* RA_PRIORITY */ + guint32 fwmark; /* FRA_FWMARK */ + guint32 fwmask; /* FRA_FWMASK */ + guint32 goto_target; /* FRA_GOTO */ + guint32 flow; /* FRA_FLOW */ + guint32 suppress_prefixlen_inverse; /* ~(FRA_SUPPRESS_PREFIXLEN) */ + guint32 suppress_ifgroup_inverse; /* ~(FRA_SUPPRESS_IFGROUP) */ + NMFibRuleUidRange uid_range; /* FRA_UID_RANGE */ + NMFibRulePortRange sport_range; /* FRA_SPORT_RANGE */ + NMFibRulePortRange dport_range; /* FRA_DPORT_RANGE */ + char iifname[NMP_IFNAMSIZ]; /* FRA_IIFNAME */ + char oifname[NMP_IFNAMSIZ]; /* FRA_OIFNAME */ + guint8 addr_family; /* (struct fib_rule_hdr).family */ + guint8 action; /* (struct fib_rule_hdr).action */ + guint8 tos; /* (struct fib_rule_hdr).tos */ + guint8 src_len; /* (struct fib_rule_hdr).src_len */ + guint8 dst_len; /* (struct fib_rule_hdr).dst_len */ + guint8 l3mdev; /* FRA_L3MDEV */ + guint8 protocol; /* FRA_PROTOCOL */ + guint8 ip_proto; /* FRA_IP_PROTO */ + + bool uid_range_has : 1; /* has(FRA_UID_RANGE) */ } NMPlatformRoutingRule; -#define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET (~((guint32) 0)) +#define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET (~((guint32) 0)) #define NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED ((guint32) 0x83126E97u) -G_STATIC_ASSERT (((((guint64) NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) * 1000u) >> 10) == (guint64) INT_MAX); +G_STATIC_ASSERT(((((guint64) NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) * 1000u) >> 10) + == (guint64) INT_MAX); typedef struct { - guint32 limit; - guint32 flows; - guint32 target; - guint32 interval; - guint32 quantum; - guint32 ce_threshold; /* TCA_FQ_CODEL_CE_THRESHOLD: kernel internally stores this value as - * ((val64 * NSEC_PER_USEC) >> CODEL_SHIFT). The default value (in - * the domain with this coersion) is CODEL_DISABLED_THRESHOLD (INT_MAX). - * That means, "disabled" is expressed on RTM_NEWQDISC netlink API by absence of the - * netlink attribute but also as the special value 0x83126E97u - * (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED). - * Beware: zero is not the default you must always explicitly set this value. */ - guint32 memory_limit; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel - * and kernel defaults to 32MB. - * Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET - * to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request). - * This will cause kernel to choose the default (32MB). - * Beware: zero is not the default you must always explicitly set this value. */ - bool ecn:1; + guint32 limit; + guint32 flows; + guint32 target; + guint32 interval; + guint32 quantum; + + /* TCA_FQ_CODEL_CE_THRESHOLD: kernel internally stores this value as + * ((val64 * NSEC_PER_USEC) >> CODEL_SHIFT). The default value (in + * the domain with this coercion) is CODEL_DISABLED_THRESHOLD (INT_MAX). + * That means, "disabled" is expressed on RTM_NEWQDISC netlink API by absence of the + * netlink attribute but also as the special value 0x83126E97u + * (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED). + * Beware: zero is not the default you must always explicitly set this value. */ + guint32 ce_threshold; + + /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel + * and kernel defaults to 32MB. + * Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET + * to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request). + * This will cause kernel to choose the default (32MB). + * Beware: zero is not the default you must always explicitly set this value. */ + guint32 memory_limit; + + bool ecn : 1; } NMPlatformQdiscFqCodel; typedef struct { - unsigned quantum; - int perturb_period; - guint32 limit; - unsigned divisor; - unsigned flows; - unsigned depth; + unsigned quantum; + int perturb_period; + guint32 limit; + unsigned divisor; + unsigned flows; + unsigned depth; } NMPlatformQdiscSfq; typedef struct { - guint64 rate; - guint32 burst; - guint32 limit; - guint32 latency; + guint64 rate; + guint32 burst; + guint32 limit; + guint32 latency; } NMPlatformQdiscTbf; typedef struct { - __NMPlatformObjWithIfindex_COMMON; - - /* beware, kind is embedded in an NMPObject, hence you must - * take care of the lifetime of the string. */ - const char *kind; - - int addr_family; - guint32 handle; - guint32 parent; - guint32 info; - union { - NMPlatformQdiscFqCodel fq_codel; - NMPlatformQdiscSfq sfq; - NMPlatformQdiscTbf tbf; - }; + __NMPlatformObjWithIfindex_COMMON; + + /* beware, kind is embedded in an NMPObject, hence you must + * take care of the lifetime of the string. */ + const char *kind; + + int addr_family; + guint32 handle; + guint32 parent; + guint32 info; + union { + NMPlatformQdiscFqCodel fq_codel; + NMPlatformQdiscSfq sfq; + NMPlatformQdiscTbf tbf; + }; } NMPlatformQdisc; typedef struct { - char sdata[32]; + char sdata[32]; } NMPlatformActionSimple; typedef struct { - int ifindex; - bool egress:1; - bool ingress:1; - bool mirror:1; - bool redirect:1; + int ifindex; + bool egress : 1; + bool ingress : 1; + bool mirror : 1; + bool redirect : 1; } NMPlatformActionMirred; typedef struct { - - /* beware, kind is embedded in an NMPObject, hence you must - * take care of the lifetime of the string. */ - const char *kind; - - union { - NMPlatformActionSimple simple; - NMPlatformActionMirred mirred; - }; + /* beware, kind is embedded in an NMPObject, hence you must + * take care of the lifetime of the string. */ + const char *kind; + + union { + NMPlatformActionSimple simple; + NMPlatformActionMirred mirred; + }; } NMPlatformAction; #define NM_PLATFORM_ACTION_KIND_SIMPLE "simple" #define NM_PLATFORM_ACTION_KIND_MIRRED "mirred" typedef struct { - __NMPlatformObjWithIfindex_COMMON; + __NMPlatformObjWithIfindex_COMMON; - /* beware, kind is embedded in an NMPObject, hence you must - * take care of the lifetime of the string. */ - const char *kind; + /* beware, kind is embedded in an NMPObject, hence you must + * take care of the lifetime of the string. */ + const char *kind; - int addr_family; - guint32 handle; - guint32 parent; - guint32 info; - NMPlatformAction action; + int addr_family; + guint32 handle; + guint32 parent; + guint32 info; + NMPlatformAction action; } NMPlatformTfilter; #undef __NMPlatformObjWithIfindex_COMMON typedef struct { - gboolean is_ip4; - NMPObjectType obj_type; - int addr_family; - gsize sizeof_route; - int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type); - const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len); + gboolean is_ip4; + NMPObjectType obj_type; + int addr_family; + gsize sizeof_route; + int (*route_cmp)(const NMPlatformIPXRoute *a, + const NMPlatformIPXRoute *b, + NMPlatformIPRouteCmpType cmp_type); + const char *(*route_to_string)(const NMPlatformIPXRoute *route, char *buf, gsize len); } NMPlatformVTableRoute; typedef union { - struct { - NMPlatformVTableRoute v6; - NMPlatformVTableRoute v4; - }; - NMPlatformVTableRoute vx[2]; + struct { + NMPlatformVTableRoute v6; + NMPlatformVTableRoute v4; + }; + NMPlatformVTableRoute vx[2]; } _NMPlatformVTableRouteUnion; extern const _NMPlatformVTableRouteUnion nm_platform_vtable_route; typedef struct { - guint16 id; - guint32 qos; - bool proto_ad:1; + guint16 id; + guint32 qos; + bool proto_ad : 1; } NMPlatformVFVlan; typedef struct { - guint32 index; - guint32 min_tx_rate; - guint32 max_tx_rate; - guint num_vlans; - NMPlatformVFVlan *vlans; - struct { - guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */ - guint8 len; - } mac; - gint8 spoofchk; - gint8 trust; + guint32 index; + guint32 min_tx_rate; + guint32 max_tx_rate; + guint num_vlans; + NMPlatformVFVlan *vlans; + struct { + guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */ + guint8 len; + } mac; + gint8 spoofchk; + gint8 trust; } NMPlatformVF; typedef struct { - guint16 vid_start; - guint16 vid_end; - bool untagged:1; - bool pvid:1; + guint16 vid_start; + guint16 vid_end; + bool untagged : 1; + bool pvid : 1; } NMPlatformBridgeVlan; typedef struct { - in_addr_t local; - in_addr_t remote; - int parent_ifindex; - guint16 input_flags; - guint16 output_flags; - guint32 input_key; - guint32 output_key; - guint8 ttl; - guint8 tos; - bool path_mtu_discovery:1; - bool is_tap:1; + NMEtherAddr group_addr; + bool mcast_querier : 1; + bool mcast_query_use_ifaddr : 1; + bool mcast_snooping : 1; + bool stp_state : 1; + bool vlan_stats_enabled : 1; + guint16 group_fwd_mask; + guint16 priority; + guint16 vlan_protocol; + guint32 ageing_time; + guint32 forward_delay; + guint32 hello_time; + guint32 max_age; + guint32 mcast_last_member_count; + guint32 mcast_startup_query_count; + guint32 mcast_hash_max; + guint64 mcast_last_member_interval; + guint64 mcast_membership_interval; + guint64 mcast_querier_interval; + guint64 mcast_query_interval; + guint64 mcast_query_response_interval; + guint64 mcast_startup_query_interval; + guint8 mcast_router; +} NMPlatformLnkBridge; + +extern const NMPlatformLnkBridge nm_platform_lnk_bridge_default; + +typedef struct { + in_addr_t local; + in_addr_t remote; + int parent_ifindex; + guint16 input_flags; + guint16 output_flags; + guint32 input_key; + guint32 output_key; + guint8 ttl; + guint8 tos; + bool path_mtu_discovery : 1; + bool is_tap : 1; } NMPlatformLnkGre; typedef struct { - int p_key; - const char *mode; + int p_key; + const char *mode; } NMPlatformLnkInfiniband; typedef struct { - struct in6_addr local; - struct in6_addr remote; - int parent_ifindex; - guint8 ttl; - guint8 tclass; - guint8 encap_limit; - guint8 proto; - guint flow_label; - guint32 flags; - - /* IP6GRE only */ - guint32 input_key; - guint32 output_key; - guint16 input_flags; - guint16 output_flags; - bool is_tap:1; - bool is_gre:1; + struct in6_addr local; + struct in6_addr remote; + int parent_ifindex; + guint8 ttl; + guint8 tclass; + guint8 encap_limit; + guint8 proto; + guint flow_label; + guint32 flags; + + /* IP6GRE only */ + guint32 input_key; + guint32 output_key; + guint16 input_flags; + guint16 output_flags; + bool is_tap : 1; + bool is_gre : 1; } NMPlatformLnkIp6Tnl; typedef struct { - in_addr_t local; - in_addr_t remote; - int parent_ifindex; - guint8 ttl; - guint8 tos; - bool path_mtu_discovery:1; + in_addr_t local; + in_addr_t remote; + int parent_ifindex; + guint8 ttl; + guint8 tos; + bool path_mtu_discovery : 1; } NMPlatformLnkIpIp; typedef struct { - int parent_ifindex; - guint64 sci; /* host byte order */ - guint64 cipher_suite; - guint32 window; - guint8 icv_length; - guint8 encoding_sa; - guint8 validation; - bool encrypt:1; - bool protect:1; - bool include_sci:1; - bool es:1; - bool scb:1; - bool replay_protect:1; + int parent_ifindex; + guint64 sci; /* host byte order */ + guint64 cipher_suite; + guint32 window; + guint8 icv_length; + guint8 encoding_sa; + guint8 validation; + bool encrypt : 1; + bool protect : 1; + bool include_sci : 1; + bool es : 1; + bool scb : 1; + bool replay_protect : 1; } NMPlatformLnkMacsec; typedef struct { - guint mode; - bool no_promisc:1; - bool tap:1; + guint mode; + bool no_promisc : 1; + bool tap : 1; } NMPlatformLnkMacvlan; typedef struct { - in_addr_t local; - in_addr_t remote; - int parent_ifindex; - guint16 flags; - guint8 ttl; - guint8 tos; - guint8 proto; - bool path_mtu_discovery:1; + in_addr_t local; + in_addr_t remote; + int parent_ifindex; + guint16 flags; + guint8 ttl; + guint8 tos; + guint8 proto; + bool path_mtu_discovery : 1; } NMPlatformLnkSit; typedef struct { - guint32 owner; - guint32 group; + guint32 owner; + guint32 group; - guint8 type; + guint8 type; - bool owner_valid:1; - bool group_valid:1; + bool owner_valid : 1; + bool group_valid : 1; - bool pi:1; - bool vnet_hdr:1; - bool multi_queue:1; - bool persist:1; + bool pi : 1; + bool vnet_hdr : 1; + bool multi_queue : 1; + bool persist : 1; } NMPlatformLnkTun; typedef struct { - /* rtnl_link_vlan_get_id(), IFLA_VLAN_ID */ - guint16 id; - NMVlanFlags flags; + /* rtnl_link_vlan_get_id(), IFLA_VLAN_ID */ + guint16 id; + NMVlanFlags flags; } NMPlatformLnkVlan; typedef struct { - guint32 table; + guint32 table; } NMPlatformLnkVrf; typedef struct { - struct in6_addr group6; - struct in6_addr local6; - in_addr_t group; - in_addr_t local; - int parent_ifindex; - guint32 id; - guint32 ageing; - guint32 limit; - guint16 dst_port; - guint16 src_port_min; - guint16 src_port_max; - guint8 tos; - guint8 ttl; - bool learning:1; - bool proxy:1; - bool rsc:1; - bool l2miss:1; - bool l3miss:1; + struct in6_addr group6; + struct in6_addr local6; + in_addr_t group; + in_addr_t local; + int parent_ifindex; + guint32 id; + guint32 ageing; + guint32 limit; + guint16 dst_port; + guint16 src_port_min; + guint16 src_port_max; + guint8 tos; + guint8 ttl; + bool learning : 1; + bool proxy : 1; + bool rsc : 1; + bool l2miss : 1; + bool l3miss : 1; } NMPlatformLnkVxlan; -#define NMP_WIREGUARD_PUBLIC_KEY_LEN 32 +#define NMP_WIREGUARD_PUBLIC_KEY_LEN 32 #define NMP_WIREGUARD_SYMMETRIC_KEY_LEN 32 typedef struct { - guint32 fwmark; - guint16 listen_port; - guint8 private_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; - guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; + guint32 fwmark; + guint16 listen_port; + guint8 private_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; + guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; } NMPlatformLnkWireGuard; typedef enum { - NM_PLATFORM_LINK_DUPLEX_UNKNOWN, - NM_PLATFORM_LINK_DUPLEX_HALF, - NM_PLATFORM_LINK_DUPLEX_FULL, + NM_PLATFORM_LINK_DUPLEX_UNKNOWN, + NM_PLATFORM_LINK_DUPLEX_HALF, + NM_PLATFORM_LINK_DUPLEX_FULL, } NMPlatformLinkDuplexType; typedef enum { - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0, - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0), - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1), - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT = (1LL << 2), - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK = (1LL << 3), + NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0, + NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0), + NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1), + NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT = (1LL << 2), + NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK = (1LL << 3), } NMPlatformWireGuardChangeFlags; typedef enum { - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE = 0, - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME = (1LL << 0), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY = (1LL << 1), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL = (1LL << 2), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT = (1LL << 3), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS = (1LL << 4), - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS = (1LL << 5), - - NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT - | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE = 0, + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME = (1LL << 0), + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY = (1LL << 1), + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL = (1LL << 2), + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT = (1LL << 3), + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS = (1LL << 4), + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS = (1LL << 5), + + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT = + NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT + | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, } NMPlatformWireGuardChangePeerFlags; -typedef void (*NMPlatformAsyncCallback) (GError *error, gpointer user_data); +typedef void (*NMPlatformAsyncCallback)(GError *error, gpointer user_data); /*****************************************************************************/ typedef enum { - NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL, - - /* this also includes FRA_SPORT_RANGE and FRA_DPORT_RANGE which - * were added at the same time. */ - NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO, - - _NM_PLATFORM_KERNEL_SUPPORT_NUM, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED, + + /* this also includes FRA_SPORT_RANGE and FRA_DPORT_RANGE which + * were added at the same time. */ + NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO, + + _NM_PLATFORM_KERNEL_SUPPORT_NUM, } NMPlatformKernelSupportType; extern volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM]; -int _nm_platform_kernel_support_init (NMPlatformKernelSupportType type, - int value); +int _nm_platform_kernel_support_init(NMPlatformKernelSupportType type, int value); static inline gboolean -_nm_platform_kernel_support_detected (NMPlatformKernelSupportType type) +_nm_platform_kernel_support_detected(NMPlatformKernelSupportType type) { - nm_assert ( _NM_INT_NOT_NEGATIVE (type) - && type < G_N_ELEMENTS (_nm_platform_kernel_support_state)); + nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(_nm_platform_kernel_support_state)); - return G_LIKELY (_nm_platform_kernel_support_state[type] != 0); + return G_LIKELY(g_atomic_int_get(&_nm_platform_kernel_support_state[type]) != 0); } -static inline gboolean -nm_platform_kernel_support_get (NMPlatformKernelSupportType type) +static inline NMTernary +nm_platform_kernel_support_get_full(NMPlatformKernelSupportType type, gboolean init_if_not_set) { - int v; + int v; + + nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(_nm_platform_kernel_support_state)); - nm_assert (_NM_INT_NOT_NEGATIVE (type) - && type < G_N_ELEMENTS (_nm_platform_kernel_support_state)); + v = g_atomic_int_get(&_nm_platform_kernel_support_state[type]); + if (G_UNLIKELY(v == 0)) { + if (!init_if_not_set) + return NM_TERNARY_DEFAULT; + v = _nm_platform_kernel_support_init(type, 0); + } + return (v >= 0); +} - v = _nm_platform_kernel_support_state[type]; - if (G_UNLIKELY (v == 0)) - v = _nm_platform_kernel_support_init (type, 0); - return (v >= 0); +static inline gboolean +nm_platform_kernel_support_get(NMPlatformKernelSupportType type) +{ + return nm_platform_kernel_support_get_full(type, TRUE) != NM_TERNARY_FALSE; } /*****************************************************************************/ @@ -981,176 +1053,193 @@ nm_platform_kernel_support_get (NMPlatformKernelSupportType type) struct _NMPlatformPrivate; struct _NMPlatform { - GObject parent; - NMPNetns *_netns; - struct _NMPlatformPrivate *_priv; + GObject parent; + NMPNetns * _netns; + struct _NMPlatformPrivate *_priv; }; typedef struct { - GObjectClass parent; - - gboolean (*sysctl_set) (NMPlatform *self, const char *pathid, int dirfd, const char *path, const char *value); - void (*sysctl_set_async) (NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - const char *const *values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable *cancellable); - char * (*sysctl_get) (NMPlatform *self, const char *pathid, int dirfd, const char *path); - - void (*refresh_all) (NMPlatform *self, NMPObjectType obj_type); - void (*process_events) (NMPlatform *self); - - int (*link_add) (NMPlatform *self, - NMLinkType type, - const char *name, - int parent, - const void *address, - size_t address_len, - gconstpointer extra_data, - const NMPlatformLink **out_link); - gboolean (*link_delete) (NMPlatform *self, int ifindex); - gboolean (*link_refresh) (NMPlatform *self, int ifindex); - gboolean (*link_set_netns) (NMPlatform *self, int ifindex, int netns_fd); - gboolean (*link_set_up) (NMPlatform *self, int ifindex, gboolean *out_no_firmware); - gboolean (*link_set_down) (NMPlatform *self, int ifindex); - gboolean (*link_set_arp) (NMPlatform *self, int ifindex); - gboolean (*link_set_noarp) (NMPlatform *self, int ifindex); - - int (*link_set_user_ipv6ll_enabled) (NMPlatform *self, int ifindex, gboolean enabled); - gboolean (*link_set_token) (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); - - gboolean (*link_get_permanent_address) (NMPlatform *self, - int ifindex, - guint8 *buf, - size_t *length); - int (*link_set_address) (NMPlatform *self, int ifindex, gconstpointer address, size_t length); - int (*link_set_mtu) (NMPlatform *self, int ifindex, guint32 mtu); - gboolean (*link_set_name) (NMPlatform *self, int ifindex, const char *name); - void (*link_set_sriov_params_async) (NMPlatform *self, - int ifindex, - guint num_vfs, - int autoprobe, - NMPlatformAsyncCallback callback, - gpointer callback_data, - GCancellable *cancellable); - gboolean (*link_set_sriov_vfs) (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs); - gboolean (*link_set_bridge_vlans) (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans); - - char * (*link_get_physical_port_id) (NMPlatform *self, int ifindex); - guint (*link_get_dev_id) (NMPlatform *self, int ifindex); - gboolean (*link_get_wake_on_lan) (NMPlatform *self, int ifindex); - gboolean (*link_get_driver_info) (NMPlatform *self, - int ifindex, - char **out_driver_name, - char **out_driver_version, - char **out_fw_version); - - gboolean (*link_supports_carrier_detect) (NMPlatform *self, int ifindex); - gboolean (*link_supports_vlans) (NMPlatform *self, int ifindex); - gboolean (*link_supports_sriov) (NMPlatform *self, int ifindex); - - gboolean (*link_enslave) (NMPlatform *self, int master, int slave); - gboolean (*link_release) (NMPlatform *self, int master, int slave); - - gboolean (*link_can_assume) (NMPlatform *self, int ifindex); - - int (*link_wireguard_change) (NMPlatform *self, - int ifindex, - const NMPlatformLnkWireGuard *lnk_wireguard, - const struct _NMPWireGuardPeer *peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags); - - gboolean (*link_vlan_change) (NMPlatform *self, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map); - gboolean (*link_tun_add) (NMPlatform *self, - const char *name, - const NMPlatformLnkTun *props, - const NMPlatformLink **out_link, - int *out_fd); - - gboolean (*infiniband_partition_add) (NMPlatform *self, int parent, int p_key, const NMPlatformLink **out_link); - gboolean (*infiniband_partition_delete) (NMPlatform *self, int parent, int p_key); - - gboolean (*wifi_get_capabilities) (NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps); - gboolean (*wifi_get_bssid) (NMPlatform *self, int ifindex, guint8 *bssid); - guint32 (*wifi_get_frequency) (NMPlatform *self, int ifindex); - int (*wifi_get_quality) (NMPlatform *self, int ifindex); - guint32 (*wifi_get_rate) (NMPlatform *self, int ifindex); - NM80211Mode (*wifi_get_mode) (NMPlatform *self, int ifindex); - void (*wifi_set_mode) (NMPlatform *self, int ifindex, NM80211Mode mode); - void (*wifi_set_powersave) (NMPlatform *self, int ifindex, guint32 powersave); - guint32 (*wifi_find_frequency) (NMPlatform *self, int ifindex, const guint32 *freqs); - void (*wifi_indicate_addressing_running) (NMPlatform *self, int ifindex, gboolean running); - NMSettingWirelessWakeOnWLan (*wifi_get_wake_on_wlan) (NMPlatform *self, int ifindex); - gboolean (*wifi_set_wake_on_wlan) (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl); - - guint32 (*mesh_get_channel) (NMPlatform *self, int ifindex); - gboolean (*mesh_set_channel) (NMPlatform *self, int ifindex, guint32 channel); - gboolean (*mesh_set_ssid) (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); - - guint16 (*wpan_get_pan_id) (NMPlatform *self, int ifindex); - gboolean (*wpan_set_pan_id) (NMPlatform *self, int ifindex, guint16 pan_id); - guint16 (*wpan_get_short_addr) (NMPlatform *self, int ifindex); - gboolean (*wpan_set_short_addr) (NMPlatform *self, int ifindex, guint16 short_addr); - gboolean (*wpan_set_channel) (NMPlatform *self, int ifindex, guint8 page, guint8 channel); - - gboolean (*object_delete) (NMPlatform *self, const NMPObject *obj); - - gboolean (*ip4_address_add) (NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags, - const char *label); - gboolean (*ip6_address_add) (NMPlatform *self, - int ifindex, - struct in6_addr address, - guint8 plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags); - gboolean (*ip4_address_delete) (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address); - gboolean (*ip6_address_delete) (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen); - - int (*ip_route_add) (NMPlatform *self, - NMPNlmFlags flags, - int addr_family, - const NMPlatformIPRoute *route); - int (*ip_route_get) (NMPlatform *self, - int addr_family, - gconstpointer address, - int oif_ifindex, - NMPObject **out_route); - - int (*routing_rule_add) (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformRoutingRule *routing_rule); - - int (*qdisc_add) (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformQdisc *qdisc); - - int (*tfilter_add) (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformTfilter *tfilter); + GObjectClass parent; + + gboolean (*sysctl_set)(NMPlatform *self, + const char *pathid, + int dirfd, + const char *path, + const char *value); + void (*sysctl_set_async)(NMPlatform * self, + const char * pathid, + int dirfd, + const char * path, + const char *const * values, + NMPlatformAsyncCallback callback, + gpointer data, + GCancellable * cancellable); + char *(*sysctl_get)(NMPlatform *self, const char *pathid, int dirfd, const char *path); + + void (*refresh_all)(NMPlatform *self, NMPObjectType obj_type); + void (*process_events)(NMPlatform *self); + + int (*link_add)(NMPlatform * self, + NMLinkType type, + const char * name, + int parent, + const void * address, + size_t address_len, + gconstpointer extra_data, + const NMPlatformLink **out_link); + gboolean (*link_delete)(NMPlatform *self, int ifindex); + gboolean (*link_refresh)(NMPlatform *self, int ifindex); + gboolean (*link_set_netns)(NMPlatform *self, int ifindex, int netns_fd); + gboolean (*link_set_up)(NMPlatform *self, int ifindex, gboolean *out_no_firmware); + gboolean (*link_set_down)(NMPlatform *self, int ifindex); + gboolean (*link_set_arp)(NMPlatform *self, int ifindex); + gboolean (*link_set_noarp)(NMPlatform *self, int ifindex); + + int (*link_set_user_ipv6ll_enabled)(NMPlatform *self, int ifindex, gboolean enabled); + gboolean (*link_set_token)(NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); + + gboolean (*link_get_permanent_address)(NMPlatform *self, + int ifindex, + guint8 * buf, + size_t * length); + int (*link_set_address)(NMPlatform *self, int ifindex, gconstpointer address, size_t length); + int (*link_set_mtu)(NMPlatform *self, int ifindex, guint32 mtu); + gboolean (*link_set_name)(NMPlatform *self, int ifindex, const char *name); + void (*link_set_sriov_params_async)(NMPlatform * self, + int ifindex, + guint num_vfs, + int autoprobe, + NMPlatformAsyncCallback callback, + gpointer callback_data, + GCancellable * cancellable); + gboolean (*link_set_sriov_vfs)(NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs); + gboolean (*link_set_bridge_vlans)(NMPlatform * self, + int ifindex, + gboolean on_master, + const NMPlatformBridgeVlan *const *vlans); + + char *(*link_get_physical_port_id)(NMPlatform *self, int ifindex); + guint (*link_get_dev_id)(NMPlatform *self, int ifindex); + gboolean (*link_get_wake_on_lan)(NMPlatform *self, int ifindex); + gboolean (*link_get_driver_info)(NMPlatform *self, + int ifindex, + char ** out_driver_name, + char ** out_driver_version, + char ** out_fw_version); + + gboolean (*link_supports_carrier_detect)(NMPlatform *self, int ifindex); + gboolean (*link_supports_vlans)(NMPlatform *self, int ifindex); + gboolean (*link_supports_sriov)(NMPlatform *self, int ifindex); + + gboolean (*link_enslave)(NMPlatform *self, int master, int slave); + gboolean (*link_release)(NMPlatform *self, int master, int slave); + + gboolean (*link_can_assume)(NMPlatform *self, int ifindex); + + int (*link_wireguard_change)(NMPlatform * self, + int ifindex, + const NMPlatformLnkWireGuard * lnk_wireguard, + const struct _NMPWireGuardPeer * peers, + const NMPlatformWireGuardChangePeerFlags *peer_flags, + guint peers_len, + NMPlatformWireGuardChangeFlags change_flags); + + gboolean (*link_vlan_change)(NMPlatform * self, + int ifindex, + NMVlanFlags flags_mask, + NMVlanFlags flags_set, + gboolean ingress_reset_all, + const NMVlanQosMapping *ingress_map, + gsize n_ingress_map, + gboolean egress_reset_all, + const NMVlanQosMapping *egress_map, + gsize n_egress_map); + gboolean (*link_tun_add)(NMPlatform * self, + const char * name, + const NMPlatformLnkTun *props, + const NMPlatformLink ** out_link, + int * out_fd); + + gboolean (*infiniband_partition_add)(NMPlatform * self, + int parent, + int p_key, + const NMPlatformLink **out_link); + gboolean (*infiniband_partition_delete)(NMPlatform *self, int parent, int p_key); + + gboolean (*wifi_get_capabilities)(NMPlatform * self, + int ifindex, + NMDeviceWifiCapabilities *caps); + gboolean (*wifi_get_bssid)(NMPlatform *self, int ifindex, guint8 *bssid); + guint32 (*wifi_get_frequency)(NMPlatform *self, int ifindex); + int (*wifi_get_quality)(NMPlatform *self, int ifindex); + guint32 (*wifi_get_rate)(NMPlatform *self, int ifindex); + NM80211Mode (*wifi_get_mode)(NMPlatform *self, int ifindex); + void (*wifi_set_mode)(NMPlatform *self, int ifindex, NM80211Mode mode); + void (*wifi_set_powersave)(NMPlatform *self, int ifindex, guint32 powersave); + guint32 (*wifi_find_frequency)(NMPlatform *self, int ifindex, const guint32 *freqs); + void (*wifi_indicate_addressing_running)(NMPlatform *self, int ifindex, gboolean running); + NMSettingWirelessWakeOnWLan (*wifi_get_wake_on_wlan)(NMPlatform *self, int ifindex); + gboolean (*wifi_set_wake_on_wlan)(NMPlatform * self, + int ifindex, + NMSettingWirelessWakeOnWLan wowl); + + guint32 (*mesh_get_channel)(NMPlatform *self, int ifindex); + gboolean (*mesh_set_channel)(NMPlatform *self, int ifindex, guint32 channel); + gboolean (*mesh_set_ssid)(NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); + + guint16 (*wpan_get_pan_id)(NMPlatform *self, int ifindex); + gboolean (*wpan_set_pan_id)(NMPlatform *self, int ifindex, guint16 pan_id); + guint16 (*wpan_get_short_addr)(NMPlatform *self, int ifindex); + gboolean (*wpan_set_short_addr)(NMPlatform *self, int ifindex, guint16 short_addr); + gboolean (*wpan_set_channel)(NMPlatform *self, int ifindex, guint8 page, guint8 channel); + + gboolean (*object_delete)(NMPlatform *self, const NMPObject *obj); + + gboolean (*ip4_address_add)(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address, + in_addr_t broadcast_address, + guint32 lifetime, + guint32 preferred_lft, + guint32 flags, + const char *label); + gboolean (*ip6_address_add)(NMPlatform * self, + int ifindex, + struct in6_addr address, + guint8 plen, + struct in6_addr peer_address, + guint32 lifetime, + guint32 preferred_lft, + guint32 flags); + gboolean (*ip4_address_delete)(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address); + gboolean (*ip6_address_delete)(NMPlatform * self, + int ifindex, + struct in6_addr address, + guint8 plen); + + int (*ip_route_add)(NMPlatform * self, + NMPNlmFlags flags, + int addr_family, + const NMPlatformIPRoute *route); + int (*ip_route_get)(NMPlatform * self, + int addr_family, + gconstpointer address, + int oif_ifindex, + NMPObject ** out_route); + + int (*routing_rule_add)(NMPlatform * self, + NMPNlmFlags flags, + const NMPlatformRoutingRule *routing_rule); + + int (*qdisc_add)(NMPlatform *self, NMPNlmFlags flags, const NMPlatformQdisc *qdisc); + + int (*tfilter_add)(NMPlatform *self, NMPNlmFlags flags, const NMPlatformTfilter *tfilter); } NMPlatformClass; /* NMPlatform signals @@ -1164,49 +1253,47 @@ typedef struct { * but you are free to copy the provided information and use it for later * reference. */ -#define NM_PLATFORM_SIGNAL_LINK_CHANGED "link-changed" -#define NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED "ip4-address-changed" -#define NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED "ip6-address-changed" -#define NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED "ip4-route-changed" -#define NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED "ip6-route-changed" +#define NM_PLATFORM_SIGNAL_LINK_CHANGED "link-changed" +#define NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED "ip4-address-changed" +#define NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED "ip6-address-changed" +#define NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED "ip4-route-changed" +#define NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED "ip6-route-changed" #define NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED "routing-rule-changed" -#define NM_PLATFORM_SIGNAL_QDISC_CHANGED "qdisc-changed" -#define NM_PLATFORM_SIGNAL_TFILTER_CHANGED "tfilter-changed" +#define NM_PLATFORM_SIGNAL_QDISC_CHANGED "qdisc-changed" +#define NM_PLATFORM_SIGNAL_TFILTER_CHANGED "tfilter-changed" -const char *nm_platform_signal_change_type_to_string (NMPlatformSignalChangeType change_type); +const char *nm_platform_signal_change_type_to_string(NMPlatformSignalChangeType change_type); /*****************************************************************************/ -GType nm_platform_get_type (void); +GType nm_platform_get_type(void); -void nm_platform_setup (NMPlatform *instance); -NMPlatform *nm_platform_get (void); +void nm_platform_setup(NMPlatform *instance); +NMPlatform *nm_platform_get(void); -#define NM_PLATFORM_GET (nm_platform_get ()) +#define NM_PLATFORM_GET (nm_platform_get()) /*****************************************************************************/ static inline in_addr_t -nm_platform_ip4_broadcast_address_create (in_addr_t address, - guint8 plen) +nm_platform_ip4_broadcast_address_create(in_addr_t address, guint8 plen) { - return address | ~_nm_utils_ip4_prefix_to_netmask (plen); + return address | ~_nm_utils_ip4_prefix_to_netmask(plen); } static inline in_addr_t -nm_platform_ip4_broadcast_address_from_addr (const NMPlatformIP4Address *addr) +nm_platform_ip4_broadcast_address_from_addr(const NMPlatformIP4Address *addr) { - nm_assert (addr); + nm_assert(addr); - if (addr->use_ip4_broadcast_address) - return addr->broadcast_address; + if (addr->use_ip4_broadcast_address) + return addr->broadcast_address; - /* the set broadcast-address gets ignored, and we determine a default brd base - * on the peer IFA_ADDRESS. */ - if ( addr->peer_address != 0u - && addr->plen < 31 /* RFC3021 */) - return nm_platform_ip4_broadcast_address_create (addr->peer_address, addr->plen); - return 0u; + /* the set broadcast-address gets ignored, and we determine a default brd base + * on the peer IFA_ADDRESS. */ + if (addr->peer_address != 0u && addr->plen < 31 /* RFC3021 */) + return nm_platform_ip4_broadcast_address_create(addr->peer_address, addr->plen); + return 0u; } /*****************************************************************************/ @@ -1220,27 +1307,27 @@ nm_platform_ip4_broadcast_address_from_addr (const NMPlatformIP4Address *addr) * NMPlatformIPRoute.table_coerced. */ static inline guint32 -nm_platform_route_table_coerce (guint32 table) +nm_platform_route_table_coerce(guint32 table) { - /* For kernel, the default table is RT_TABLE_MAIN (254). - * We want that in NMPlatformIPRoute.table_coerced a numeric - * zero is the default. Hence, @table_coerced swaps the - * value 0 and 254. Use nm_platform_route_table_coerce() - * and nm_platform_route_table_uncoerce() to convert between - * the two domains. */ - switch (table) { - case 0 /* RT_TABLE_UNSPEC */: - return 254; - case 254 /* RT_TABLE_MAIN */: - return 0; - default: - return table; - } + /* For kernel, the default table is RT_TABLE_MAIN (254). + * We want that in NMPlatformIPRoute.table_coerced a numeric + * zero is the default. Hence, @table_coerced swaps the + * value 0 and 254. Use nm_platform_route_table_coerce() + * and nm_platform_route_table_uncoerce() to convert between + * the two domains. */ + switch (table) { + case 0 /* RT_TABLE_UNSPEC */: + return 254; + case 254 /* RT_TABLE_MAIN */: + return 0; + default: + return table; + } } /** * nm_platform_route_table_uncoerce: - * @table: the route table, in its coerced value + * @table_coerced: the route table, in its coerced value * @normalize: whether to normalize RT_TABLE_UNSPEC to * RT_TABLE_MAIN. For kernel, routes with a table id * RT_TABLE_UNSPEC do not exist and are treated like @@ -1250,31 +1337,31 @@ nm_platform_route_table_coerce (guint32 table) * to the original value as kernel understands it. */ static inline guint32 -nm_platform_route_table_uncoerce (guint32 table_coerced, gboolean normalize) +nm_platform_route_table_uncoerce(guint32 table_coerced, gboolean normalize) { - /* this undoes nm_platform_route_table_coerce(). */ - switch (table_coerced) { - case 0 /* RT_TABLE_UNSPEC */: - return 254; - case 254 /* RT_TABLE_MAIN */: - return normalize ? 254 : 0; - default: - return table_coerced; - } + /* this undoes nm_platform_route_table_coerce(). */ + switch (table_coerced) { + case 0 /* RT_TABLE_UNSPEC */: + return 254; + case 254 /* RT_TABLE_MAIN */: + return normalize ? 254 : 0; + default: + return table_coerced; + } } static inline gboolean -nm_platform_route_table_is_main (guint32 table) +nm_platform_route_table_is_main(guint32 table) { - /* same as - * nm_platform_route_table_uncoerce (table, TRUE) == RT_TABLE_MAIN - * and - * nm_platform_route_table_uncoerce (nm_platform_route_table_coerce (table), TRUE) == RT_TABLE_MAIN - * - * That is, the function operates the same on @table and its coerced - * form. - */ - return table == 0 || table == 254; + /* same as + * nm_platform_route_table_uncoerce (table, TRUE) == RT_TABLE_MAIN + * and + * nm_platform_route_table_uncoerce (nm_platform_route_table_coerce (table), TRUE) == RT_TABLE_MAIN + * + * That is, the function operates the same on @table and its coerced + * form. + */ + return table == 0 || table == 254; } /** @@ -1289,9 +1376,9 @@ nm_platform_route_table_is_main (guint32 table) * */ #define nm_platform_route_scope_inv _nm_platform_uint8_inv static inline guint8 -_nm_platform_uint8_inv (guint8 scope) +_nm_platform_uint8_inv(guint8 scope) { - return (guint8) ~scope; + return (guint8) ~scope; } /** @@ -1302,16 +1389,16 @@ _nm_platform_uint8_inv (guint8 scope) * NMPlatformIPRoute.type_coerced. */ static inline guint8 -nm_platform_route_type_coerce (guint8 type) +nm_platform_route_type_coerce(guint8 type) { - switch (type) { - case 0 /* RTN_UNSPEC */: - return 1; - case 1 /* RTN_UNICAST */: - return 0; - default: - return type; - } + switch (type) { + case 0 /* RTN_UNSPEC */: + return 1; + case 1 /* RTN_UNICAST */: + return 0; + default: + return type; + } } /** @@ -1322,727 +1409,932 @@ nm_platform_route_type_coerce (guint8 type) * to the original value as kernel understands it. */ static inline guint8 -nm_platform_route_type_uncoerce (guint8 type_coerced) +nm_platform_route_type_uncoerce(guint8 type_coerced) { - return nm_platform_route_type_coerce (type_coerced); + return nm_platform_route_type_coerce(type_coerced); } -gboolean nm_platform_get_use_udev (NMPlatform *self); -gboolean nm_platform_get_log_with_ptr (NMPlatform *self); - -NMPNetns *nm_platform_netns_get (NMPlatform *self); -gboolean nm_platform_netns_push (NMPlatform *self, NMPNetns **netns); - -const char *nm_link_type_to_string (NMLinkType link_type); - -#define NMP_SYSCTL_PATHID_ABSOLUTE(path) \ - ((const char *) NULL), -1, (path) - -#define NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname, path) \ - nm_sprintf_buf_unsafe_a ( NM_STRLEN ("net:/sys/class/net//\0") \ - + NMP_IFNAMSIZ \ - + ({ \ - const gsize _l = strlen (path); \ - \ - nm_assert (_l < 200); \ - _l; \ - }), \ - "net:/sys/class/net/%s/%s", (ifname), (path)), \ - (dirfd), (path) - -#define NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, path) \ - nm_sprintf_bufa (NM_STRLEN ("net:/sys/class/net//"path"/\0") + NMP_IFNAMSIZ, \ - "net:/sys/class/net/%s/%s", (ifname), path), \ - (dirfd), (""path"") - -int nm_platform_sysctl_open_netdir (NMPlatform *self, int ifindex, char *out_ifname); -gboolean nm_platform_sysctl_set (NMPlatform *self, const char *pathid, int dirfd, const char *path, const char *value); -void nm_platform_sysctl_set_async (NMPlatform *self, - const char *pathid, - int dirfd, - const char *path, - const char *const *values, - NMPlatformAsyncCallback callback, - gpointer data, - GCancellable *cancellable); -char *nm_platform_sysctl_get (NMPlatform *self, const char *pathid, int dirfd, const char *path); -gint32 nm_platform_sysctl_get_int32 (NMPlatform *self, const char *pathid, int dirfd, const char *path, gint32 fallback); -gint64 nm_platform_sysctl_get_int_checked (NMPlatform *self, const char *pathid, int dirfd, const char *path, guint base, gint64 min, gint64 max, gint64 fallback); - -char *nm_platform_sysctl_ip_conf_get (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property); - -gint64 nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - guint base, - gint64 min, - gint64 max, - gint64 fallback); - -gboolean nm_platform_sysctl_ip_conf_set (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - const char *value); - -gboolean nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *self, - int addr_family, - const char *ifname, - const char *property, - gint64 value); - -gboolean nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self, +gboolean nm_platform_get_use_udev(NMPlatform *self); +gboolean nm_platform_get_log_with_ptr(NMPlatform *self); + +NMPNetns *nm_platform_netns_get(NMPlatform *self); +gboolean nm_platform_netns_push(NMPlatform *self, NMPNetns **netns); + +const char *nm_link_type_to_string(NMLinkType link_type); + +#define NMP_SYSCTL_PATHID_ABSOLUTE(path) ((const char *) NULL), -1, (path) + +#define NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname, path) \ + nm_sprintf_buf_unsafe_a(NM_STRLEN("net:/sys/class/net//\0") + NMP_IFNAMSIZ + ({ \ + const gsize _l = strlen(path); \ + \ + nm_assert(_l < 200); \ + _l; \ + }), \ + "net:/sys/class/net/%s/%s", \ + (ifname), \ + (path)), \ + (dirfd), (path) + +#define NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, path) \ + nm_sprintf_bufa(NM_STRLEN("net:/sys/class/net//" path "/\0") + NMP_IFNAMSIZ, \ + "net:/sys/class/net/%s/%s", \ + (ifname), \ + path), \ + (dirfd), ("" path "") + +int nm_platform_sysctl_open_netdir(NMPlatform *self, int ifindex, char *out_ifname); +gboolean nm_platform_sysctl_set(NMPlatform *self, + const char *pathid, + int dirfd, + const char *path, + const char *value); +void nm_platform_sysctl_set_async(NMPlatform * self, + const char * pathid, + int dirfd, + const char * path, + const char *const * values, + NMPlatformAsyncCallback callback, + gpointer data, + GCancellable * cancellable); +char * nm_platform_sysctl_get(NMPlatform *self, const char *pathid, int dirfd, const char *path); +gint32 nm_platform_sysctl_get_int32(NMPlatform *self, + const char *pathid, + int dirfd, + const char *path, + gint32 fallback); +gint64 nm_platform_sysctl_get_int_checked(NMPlatform *self, + const char *pathid, + int dirfd, + const char *path, + guint base, + gint64 min, + gint64 max, + gint64 fallback); + +char *nm_platform_sysctl_ip_conf_get(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property); + +gint64 nm_platform_sysctl_ip_conf_get_int_checked(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property, + guint base, + gint64 min, + gint64 max, + gint64 fallback); + +gboolean nm_platform_sysctl_ip_conf_set(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property, + const char *value); + +gboolean nm_platform_sysctl_ip_conf_set_int64(NMPlatform *self, + int addr_family, + const char *ifname, + const char *property, + gint64 value); + +gboolean +nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(NMPlatform *self, const char *iface, int value); +gboolean nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(NMPlatform *self, const char *iface, - int value); -gboolean nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NMPlatform *self, - const char *iface, - guint value_ms); -gboolean nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NMPlatform *self, - const char *iface, - guint value_ms); -int nm_platform_sysctl_ip_conf_get_rp_filter_ipv4 (NMPlatform *platform, - const char *iface, - gboolean consider_all, - gboolean *out_due_to_all); - -const char *nm_platform_if_indextoname (NMPlatform *self, int ifindex, - char out_ifname[static 16 /* IFNAMSIZ */]); -int nm_platform_if_nametoindex (NMPlatform *self, const char *ifname); - -const NMPObject *nm_platform_link_get_obj (NMPlatform *self, - int ifindex, - gboolean visible_only); -const NMPlatformLink *nm_platform_link_get (NMPlatform *self, int ifindex); -const NMPlatformLink *nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname); -const NMPlatformLink *nm_platform_link_get_by_address (NMPlatform *self, NMLinkType link_type, gconstpointer address, size_t length); - -GPtrArray *nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name); - -int nm_platform_link_add (NMPlatform *self, - NMLinkType type, - const char *name, - int parent, - const void *address, - size_t address_len, - gconstpointer extra_data, - const NMPlatformLink **out_link); + guint value_ms); +gboolean nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(NMPlatform *self, + const char *iface, + guint value_ms); +int nm_platform_sysctl_ip_conf_get_rp_filter_ipv4(NMPlatform *platform, + const char *iface, + gboolean consider_all, + gboolean * out_due_to_all); + +const char *nm_platform_if_indextoname(NMPlatform *self, + int ifindex, + char out_ifname[static 16 /* IFNAMSIZ */]); +int nm_platform_if_nametoindex(NMPlatform *self, const char *ifname); + +const NMPObject *nm_platform_link_get_obj(NMPlatform *self, int ifindex, gboolean visible_only); +const NMPlatformLink *nm_platform_link_get(NMPlatform *self, int ifindex); +const NMPlatformLink *nm_platform_link_get_by_ifname(NMPlatform *self, const char *ifname); +const NMPlatformLink *nm_platform_link_get_by_address(NMPlatform * self, + NMLinkType link_type, + gconstpointer address, + size_t length); + +GPtrArray *nm_platform_link_get_all(NMPlatform *self, gboolean sort_by_name); + +int nm_platform_link_add(NMPlatform * self, + NMLinkType type, + const char * name, + int parent, + const void * address, + size_t address_len, + gconstpointer extra_data, + const NMPlatformLink **out_link); static inline int -nm_platform_link_veth_add (NMPlatform *self, - const char *name, - const char *peer, - const NMPlatformLink **out_link) +nm_platform_link_veth_add(NMPlatform * self, + const char * name, + const char * peer, + const NMPlatformLink **out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_VETH, name, 0, NULL, 0, peer, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_VETH, name, 0, NULL, 0, peer, out_link); } static inline int -nm_platform_link_dummy_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) +nm_platform_link_dummy_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_DUMMY, name, 0, NULL, 0, NULL, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_DUMMY, name, 0, NULL, 0, NULL, out_link); } static inline int -nm_platform_link_bridge_add (NMPlatform *self, - const char *name, - const void *address, - size_t address_len, - const NMPlatformLink **out_link) +nm_platform_link_bridge_add(NMPlatform * self, + const char * name, + const void * address, + size_t address_len, + const NMPlatformLnkBridge *props, + const NMPlatformLink ** out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_BRIDGE, name, 0, address, address_len, NULL, out_link); + return nm_platform_link_add(self, + NM_LINK_TYPE_BRIDGE, + name, + 0, + address, + address_len, + props, + out_link); } static inline int -nm_platform_link_bond_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) +nm_platform_link_bond_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_BOND, name, 0, NULL, 0, NULL, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_BOND, name, 0, NULL, 0, NULL, out_link); } static inline int -nm_platform_link_team_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) +nm_platform_link_team_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_TEAM, name, 0, NULL, 0, NULL, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_TEAM, name, 0, NULL, 0, NULL, out_link); } static inline int -nm_platform_link_wireguard_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link) +nm_platform_link_wireguard_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_WIREGUARD, name, 0, NULL, 0, NULL, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_WIREGUARD, name, 0, NULL, 0, NULL, out_link); } static inline int -nm_platform_link_gre_add (NMPlatform *self, - const char *name, - const void *address, - size_t address_len, - const NMPlatformLnkGre *props, - const NMPlatformLink **out_link) +nm_platform_link_gre_add(NMPlatform * self, + const char * name, + const void * address, + size_t address_len, + const NMPlatformLnkGre *props, + const NMPlatformLink ** out_link) { - g_return_val_if_fail (props, -NME_BUG); - - return nm_platform_link_add (self, props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, name, 0, address, address_len, props, out_link); + g_return_val_if_fail(props, -NME_BUG); + + return nm_platform_link_add(self, + props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, + name, + 0, + address, + address_len, + props, + out_link); } static inline int -nm_platform_link_sit_add (NMPlatform *self, - const char *name, - const NMPlatformLnkSit *props, - const NMPlatformLink **out_link) +nm_platform_link_sit_add(NMPlatform * self, + const char * name, + const NMPlatformLnkSit *props, + const NMPlatformLink ** out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_SIT, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_SIT, name, 0, NULL, 0, props, out_link); } static inline int -nm_platform_link_vlan_add (NMPlatform *self, - const char *name, - int parent, - int vlanid, - guint32 vlanflags, - const NMPlatformLink **out_link) +nm_platform_link_vlan_add(NMPlatform * self, + const char * name, + int parent, + int vlanid, + guint32 vlanflags, + const NMPlatformLink **out_link) { - g_return_val_if_fail (parent >= 0, -NME_BUG); - g_return_val_if_fail (vlanid >= 0, -NME_BUG); - - return nm_platform_link_add (self, - NM_LINK_TYPE_VLAN, - name, - parent, - NULL, - 0, - &((NMPlatformLnkVlan) { - .id = vlanid, - .flags = vlanflags, - }), - out_link); + g_return_val_if_fail(parent >= 0, -NME_BUG); + g_return_val_if_fail(vlanid >= 0, -NME_BUG); + + return nm_platform_link_add(self, + NM_LINK_TYPE_VLAN, + name, + parent, + NULL, + 0, + &((NMPlatformLnkVlan){ + .id = vlanid, + .flags = vlanflags, + }), + out_link); } static inline int -nm_platform_link_vrf_add (NMPlatform *self, - const char *name, - const NMPlatformLnkVrf *props, - const NMPlatformLink **out_link) +nm_platform_link_vrf_add(NMPlatform * self, + const char * name, + const NMPlatformLnkVrf *props, + const NMPlatformLink ** out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_VRF, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_VRF, name, 0, NULL, 0, props, out_link); } static inline int -nm_platform_link_vxlan_add (NMPlatform *self, - const char *name, - const NMPlatformLnkVxlan *props, - const NMPlatformLink **out_link) +nm_platform_link_vxlan_add(NMPlatform * self, + const char * name, + const NMPlatformLnkVxlan *props, + const NMPlatformLink ** out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, props, out_link); } static inline int -nm_platform_link_6lowpan_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLink **out_link) +nm_platform_link_6lowpan_add(NMPlatform * self, + const char * name, + int parent, + const NMPlatformLink **out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_6LOWPAN, name, parent, NULL, 0, NULL, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_6LOWPAN, name, parent, NULL, 0, NULL, out_link); } static inline int -nm_platform_link_ip6tnl_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link) +nm_platform_link_ip6tnl_add(NMPlatform * self, + const char * name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink ** out_link) { - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (!props->is_gre, -NME_BUG); + g_return_val_if_fail(props, -NME_BUG); + g_return_val_if_fail(!props->is_gre, -NME_BUG); - return nm_platform_link_add (self, NM_LINK_TYPE_IP6TNL, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_IP6TNL, name, 0, NULL, 0, props, out_link); } static inline int -nm_platform_link_ip6gre_add (NMPlatform *self, - const char *name, - const void *address, - size_t address_len, - const NMPlatformLnkIp6Tnl *props, - const NMPlatformLink **out_link) +nm_platform_link_ip6gre_add(NMPlatform * self, + const char * name, + const void * address, + size_t address_len, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink ** out_link) { - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (props->is_gre, -NME_BUG); - - return nm_platform_link_add (self, props->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, name, 0, address, address_len, props, out_link); + g_return_val_if_fail(props, -NME_BUG); + g_return_val_if_fail(props->is_gre, -NME_BUG); + + return nm_platform_link_add(self, + props->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, + name, + 0, + address, + address_len, + props, + out_link); } static inline int -nm_platform_link_ipip_add (NMPlatform *self, - const char *name, - const NMPlatformLnkIpIp *props, - const NMPlatformLink **out_link) +nm_platform_link_ipip_add(NMPlatform * self, + const char * name, + const NMPlatformLnkIpIp *props, + const NMPlatformLink ** out_link) { - g_return_val_if_fail (props, -NME_BUG); + g_return_val_if_fail(props, -NME_BUG); - return nm_platform_link_add (self, NM_LINK_TYPE_IPIP, name, 0, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_IPIP, name, 0, NULL, 0, props, out_link); } static inline int -nm_platform_link_macsec_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacsec *props, - const NMPlatformLink **out_link) +nm_platform_link_macsec_add(NMPlatform * self, + const char * name, + int parent, + const NMPlatformLnkMacsec *props, + const NMPlatformLink ** out_link) { - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (parent > 0, -NME_BUG); + g_return_val_if_fail(props, -NME_BUG); + g_return_val_if_fail(parent > 0, -NME_BUG); - return nm_platform_link_add (self, NM_LINK_TYPE_MACSEC, name, parent, NULL, 0, props, out_link); + return nm_platform_link_add(self, NM_LINK_TYPE_MACSEC, name, parent, NULL, 0, props, out_link); } static inline int -nm_platform_link_macvlan_add (NMPlatform *self, - const char *name, - int parent, - const NMPlatformLnkMacvlan *props, - const NMPlatformLink **out_link) +nm_platform_link_macvlan_add(NMPlatform * self, + const char * name, + int parent, + const NMPlatformLnkMacvlan *props, + const NMPlatformLink ** out_link) { - g_return_val_if_fail (props, -NME_BUG); - g_return_val_if_fail (parent > 0, -NME_BUG); - - return nm_platform_link_add (self, props->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN, name, parent, NULL, 0, props, out_link); + g_return_val_if_fail(props, -NME_BUG); + g_return_val_if_fail(parent > 0, -NME_BUG); + + return nm_platform_link_add(self, + props->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN, + name, + parent, + NULL, + 0, + props, + out_link); } -gboolean nm_platform_link_delete (NMPlatform *self, int ifindex); +gboolean nm_platform_link_delete(NMPlatform *self, int ifindex); -gboolean nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd); +gboolean nm_platform_link_set_netns(NMPlatform *self, int ifindex, int netns_fd); struct _NMDedupMultiHeadEntry; struct _NMPLookup; -const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *self, - const struct _NMPLookup *lookup); +const struct _NMDedupMultiHeadEntry *nm_platform_lookup(NMPlatform * self, + const struct _NMPLookup *lookup); -gboolean nm_platform_lookup_predicate_routes_main (const NMPObject *obj, - gpointer user_data); -gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj, - gpointer user_data); +#define nm_platform_iter_obj_for_each(iter, self, lookup, obj) \ + for (nm_dedup_multi_iter_init((iter), nm_platform_lookup((self), (lookup))); \ + nm_platform_dedup_multi_iter_next_obj((iter), (obj), NMP_OBJECT_TYPE_UNKNOWN);) -GPtrArray *nm_platform_lookup_clone (NMPlatform *self, - const struct _NMPLookup *lookup, - NMPObjectPredicateFunc predicate, - gpointer user_data); +gboolean nm_platform_lookup_predicate_routes_main(const NMPObject *obj, gpointer user_data); +gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel(const NMPObject *obj, + gpointer user_data); + +GPtrArray *nm_platform_lookup_clone(NMPlatform * self, + const struct _NMPLookup *lookup, + NMPObjectPredicateFunc predicate, + gpointer user_data); /* convenience methods to lookup the link and access fields of NMPlatformLink. */ -int nm_platform_link_get_ifindex (NMPlatform *self, const char *name); -const char *nm_platform_link_get_name (NMPlatform *self, int ifindex); -NMLinkType nm_platform_link_get_type (NMPlatform *self, int ifindex); -gboolean nm_platform_link_is_software (NMPlatform *self, int ifindex); -int nm_platform_link_get_ifi_flags (NMPlatform *self, int ifindex, guint requested_flags); -gboolean nm_platform_link_is_up (NMPlatform *self, int ifindex); -gboolean nm_platform_link_is_connected (NMPlatform *self, int ifindex); -gboolean nm_platform_link_uses_arp (NMPlatform *self, int ifindex); -guint32 nm_platform_link_get_mtu (NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex); - -gconstpointer nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length); - -int nm_platform_link_get_master (NMPlatform *self, int slave); - -gboolean nm_platform_link_can_assume (NMPlatform *self, int ifindex); - -gboolean nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanaged); -gboolean nm_platform_link_supports_slaves (NMPlatform *self, int ifindex); -const char *nm_platform_link_get_type_name (NMPlatform *self, int ifindex); - -gboolean nm_platform_link_refresh (NMPlatform *self, int ifindex); -void nm_platform_process_events (NMPlatform *self); - -const NMPlatformLink *nm_platform_process_events_ensure_link (NMPlatform *self, - int ifindex, - const char *ifname); - -gboolean nm_platform_link_set_up (NMPlatform *self, int ifindex, gboolean *out_no_firmware); -gboolean nm_platform_link_set_down (NMPlatform *self, int ifindex); -gboolean nm_platform_link_set_arp (NMPlatform *self, int ifindex); -gboolean nm_platform_link_set_noarp (NMPlatform *self, int ifindex); - -const char *nm_platform_link_get_udi (NMPlatform *self, int ifindex); -const char *nm_platform_link_get_path (NMPlatform *self, int ifindex); - -struct udev_device *nm_platform_link_get_udev_device (NMPlatform *self, int ifindex); - -int nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolean enabled); -gboolean nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); - -gboolean nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex, guint8 *buf, size_t *length); -int nm_platform_link_set_address (NMPlatform *self, int ifindex, const void *address, size_t length); -int nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu); -gboolean nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name); - -void nm_platform_link_set_sriov_params_async (NMPlatform *self, - int ifindex, - guint num_vfs, - int autoprobe, - NMPlatformAsyncCallback callback, - gpointer callback_data, - GCancellable *cancellable); - -gboolean nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs); -gboolean nm_platform_link_set_bridge_vlans (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans); - -char *nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex); -guint nm_platform_link_get_dev_id (NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_wake_on_lan (NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_driver_info (NMPlatform *self, - int ifindex, - char **out_driver_name, - char **out_driver_version, - char **out_fw_version); - -gboolean nm_platform_link_supports_carrier_detect (NMPlatform *self, int ifindex); -gboolean nm_platform_link_supports_vlans (NMPlatform *self, int ifindex); -gboolean nm_platform_link_supports_sriov (NMPlatform *self, int ifindex); - -gboolean nm_platform_link_enslave (NMPlatform *self, int master, int slave); -gboolean nm_platform_link_release (NMPlatform *self, int master, int slave); - -gboolean nm_platform_sysctl_master_set_option (NMPlatform *self, int ifindex, const char *option, const char *value); -char *nm_platform_sysctl_master_get_option (NMPlatform *self, int ifindex, const char *option); -gboolean nm_platform_sysctl_slave_set_option (NMPlatform *self, int ifindex, const char *option, const char *value); -char *nm_platform_sysctl_slave_get_option (NMPlatform *self, int ifindex, const char *option); - -const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link); -const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkGre *nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkMacsec *nm_platform_link_get_lnk_macsec (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvtap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkTun *nm_platform_link_get_lnk_tun (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkVlan *nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkVrf *nm_platform_link_get_lnk_vrf (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkVxlan *nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); -const NMPlatformLnkWireGuard *nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); - -gboolean nm_platform_link_vlan_set_ingress_map (NMPlatform *self, int ifindex, int from, int to); -gboolean nm_platform_link_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, int to); -gboolean nm_platform_link_vlan_change (NMPlatform *self, - int ifindex, - NMVlanFlags flags_mask, - NMVlanFlags flags_set, - gboolean ingress_reset_all, - const NMVlanQosMapping *ingress_map, - gsize n_ingress_map, - gboolean egress_reset_all, - const NMVlanQosMapping *egress_map, - gsize n_egress_map); - -int nm_platform_link_infiniband_add (NMPlatform *self, - int parent, - int p_key, - const NMPlatformLink **out_link); -int nm_platform_link_infiniband_delete (NMPlatform *self, - int parent, - int p_key); -gboolean nm_platform_link_infiniband_get_properties (NMPlatform *self, int ifindex, int *parent, int *p_key, const char **mode); - -gboolean nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_peer_ifindex); -gboolean nm_platform_link_tun_get_properties (NMPlatform *self, - int ifindex, - NMPlatformLnkTun *out_properties); - -gboolean nm_platform_wifi_get_capabilities (NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps); -gboolean nm_platform_wifi_get_bssid (NMPlatform *self, int ifindex, guint8 *bssid); -guint32 nm_platform_wifi_get_frequency (NMPlatform *self, int ifindex); -int nm_platform_wifi_get_quality (NMPlatform *self, int ifindex); -guint32 nm_platform_wifi_get_rate (NMPlatform *self, int ifindex); -NM80211Mode nm_platform_wifi_get_mode (NMPlatform *self, int ifindex); -void nm_platform_wifi_set_mode (NMPlatform *self, int ifindex, NM80211Mode mode); -void nm_platform_wifi_set_powersave (NMPlatform *self, int ifindex, guint32 powersave); -guint32 nm_platform_wifi_find_frequency (NMPlatform *self, int ifindex, const guint32 *freqs); -void nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gboolean running); -NMSettingWirelessWakeOnWLan nm_platform_wifi_get_wake_on_wlan (NMPlatform *self, int ifindex); -gboolean nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl); - -guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex); -gboolean nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel); -gboolean nm_platform_mesh_set_ssid (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); - -guint16 nm_platform_wpan_get_pan_id (NMPlatform *self, int ifindex); -gboolean nm_platform_wpan_set_pan_id (NMPlatform *self, int ifindex, guint16 pan_id); -guint16 nm_platform_wpan_get_short_addr (NMPlatform *self, int ifindex); -gboolean nm_platform_wpan_set_short_addr (NMPlatform *self, int ifindex, guint16 short_addr); -gboolean nm_platform_wpan_set_channel (NMPlatform *self, int ifindex, guint8 page, guint8 channel); - -void nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, guint8 plen); -const struct in6_addr *nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr); - -const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address); - -int nm_platform_link_sit_add (NMPlatform *self, - const char *name, - const NMPlatformLnkSit *props, - const NMPlatformLink **out_link); -int nm_platform_link_tun_add (NMPlatform *self, - const char *name, - const NMPlatformLnkTun *props, - const NMPlatformLink **out_link, - int *out_fd); -gboolean nm_platform_link_6lowpan_get_properties (NMPlatform *self, - int ifindex, - int *out_parent); - -int nm_platform_link_wireguard_add (NMPlatform *self, - const char *name, - const NMPlatformLink **out_link); - -int nm_platform_link_wireguard_change (NMPlatform *self, - int ifindex, - const NMPlatformLnkWireGuard *lnk_wireguard, - const struct _NMPWireGuardPeer *peers, - const NMPlatformWireGuardChangePeerFlags *peer_flags, - guint peers_len, - NMPlatformWireGuardChangeFlags change_flags); - -const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address); - -gboolean nm_platform_object_delete (NMPlatform *self, const NMPObject *route); - -gboolean nm_platform_ip4_address_add (NMPlatform *self, - int ifindex, - in_addr_t address, - guint8 plen, - in_addr_t peer_address, - in_addr_t broadcast_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags, - const char *label); -gboolean nm_platform_ip6_address_add (NMPlatform *self, - int ifindex, - struct in6_addr address, - guint8 plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred_lft, - guint32 flags); -gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address); -gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen); -gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, GPtrArray *known_addresses); -gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, GPtrArray *known_addresses, gboolean full_sync); -gboolean nm_platform_ip_address_flush (NMPlatform *self, - int addr_family, - int ifindex); - -void nm_platform_ip_route_normalize (int addr_family, - NMPlatformIPRoute *route); - -int nm_platform_ip_route_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPObject *route); -int nm_platform_ip4_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route); -int nm_platform_ip6_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *route); - -GPtrArray *nm_platform_ip_route_get_prune_list (NMPlatform *self, - int addr_family, - int ifindex, - NMIPRouteTableSyncMode route_table_sync); - -gboolean nm_platform_ip_route_sync (NMPlatform *self, - int addr_family, - int ifindex, - GPtrArray *routes, - GPtrArray *routes_prune, - GPtrArray **out_temporary_not_available); - -gboolean nm_platform_ip_route_flush (NMPlatform *self, - int addr_family, - int ifindex); - -int nm_platform_ip_route_get (NMPlatform *self, - int addr_family, - gconstpointer address, - int oif_ifindex, - NMPObject **out_route); - -int nm_platform_routing_rule_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformRoutingRule *routing_rule); - -int nm_platform_qdisc_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformQdisc *qdisc); -gboolean nm_platform_qdisc_sync (NMPlatform *self, - int ifindex, - GPtrArray *known_qdiscs); - -int nm_platform_tfilter_add (NMPlatform *self, - NMPNlmFlags flags, - const NMPlatformTfilter *tfilter); -gboolean nm_platform_tfilter_sync (NMPlatform *self, - int ifindex, - GPtrArray *known_tfilters); - -const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len); -const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len); -const char *nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); -const char *nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len); -const char *nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len); -const char *nm_platform_lnk_macsec_to_string (const NMPlatformLnkMacsec *lnk, char *buf, gsize len); -const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len); -const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len); -const char *nm_platform_lnk_tun_to_string (const NMPlatformLnkTun *lnk, char *buf, gsize len); -const char *nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len); -const char *nm_platform_lnk_vrf_to_string (const NMPlatformLnkVrf *lnk, char *buf, gsize len); -const char *nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len); -const char *nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len); -const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len); -const char *nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *buf, gsize len); -const char *nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsize len); -const char *nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len); -const char *nm_platform_routing_rule_to_string (const NMPlatformRoutingRule *routing_rule, char *buf, gsize len); -const char *nm_platform_qdisc_to_string (const NMPlatformQdisc *qdisc, char *buf, gsize len); -const char *nm_platform_tfilter_to_string (const NMPlatformTfilter *tfilter, char *buf, gsize len); -const char *nm_platform_vf_to_string (const NMPlatformVF *vf, char *buf, gsize len); -const char *nm_platform_bridge_vlan_to_string (const NMPlatformBridgeVlan *vlan, char *buf, gsize len); - -const char *nm_platform_vlan_qos_mapping_to_string (const char *name, - const NMVlanQosMapping *map, - gsize n_map, - char *buf, - gsize len); - -const char *nm_platform_wireguard_peer_to_string (const struct _NMPWireGuardPeer *peer, - char *buf, - gsize len); - -int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b); -int nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); -int nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b); -int nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b); -int nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b); -int nm_platform_lnk_macsec_cmp (const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b); -int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b); -int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); -int nm_platform_lnk_tun_cmp (const NMPlatformLnkTun *a, const NMPlatformLnkTun *b); -int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b); -int nm_platform_lnk_vrf_cmp (const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b); -int nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b); -int nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b); -int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); -int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b); - -int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteCmpType cmp_type); -int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, NMPlatformIPRouteCmpType cmp_type); +int nm_platform_link_get_ifindex(NMPlatform *self, const char *name); +const char *nm_platform_link_get_name(NMPlatform *self, int ifindex); +NMLinkType nm_platform_link_get_type(NMPlatform *self, int ifindex); +gboolean nm_platform_link_is_software(NMPlatform *self, int ifindex); +int nm_platform_link_get_ifi_flags(NMPlatform *self, int ifindex, guint requested_flags); +gboolean nm_platform_link_is_up(NMPlatform *self, int ifindex); +gboolean nm_platform_link_is_connected(NMPlatform *self, int ifindex); +gboolean nm_platform_link_uses_arp(NMPlatform *self, int ifindex); +guint32 nm_platform_link_get_mtu(NMPlatform *self, int ifindex); +gboolean nm_platform_link_get_user_ipv6ll_enabled(NMPlatform *self, int ifindex); + +gconstpointer nm_platform_link_get_address(NMPlatform *self, int ifindex, size_t *length); + +int nm_platform_link_get_master(NMPlatform *self, int slave); + +gboolean nm_platform_link_can_assume(NMPlatform *self, int ifindex); + +gboolean nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex, gboolean *unmanaged); +gboolean nm_platform_link_supports_slaves(NMPlatform *self, int ifindex); +const char *nm_platform_link_get_type_name(NMPlatform *self, int ifindex); + +gboolean nm_platform_link_refresh(NMPlatform *self, int ifindex); +void nm_platform_process_events(NMPlatform *self); + +const NMPlatformLink * +nm_platform_process_events_ensure_link(NMPlatform *self, int ifindex, const char *ifname); + +gboolean nm_platform_link_set_up(NMPlatform *self, int ifindex, gboolean *out_no_firmware); +gboolean nm_platform_link_set_down(NMPlatform *self, int ifindex); +gboolean nm_platform_link_set_arp(NMPlatform *self, int ifindex); +gboolean nm_platform_link_set_noarp(NMPlatform *self, int ifindex); + +const char *nm_platform_link_get_udi(NMPlatform *self, int ifindex); +const char *nm_platform_link_get_path(NMPlatform *self, int ifindex); + +struct udev_device *nm_platform_link_get_udev_device(NMPlatform *self, int ifindex); + +int nm_platform_link_set_user_ipv6ll_enabled(NMPlatform *self, int ifindex, gboolean enabled); +gboolean nm_platform_link_set_ipv6_token(NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); + +gboolean +nm_platform_link_get_permanent_address(NMPlatform *self, int ifindex, guint8 *buf, size_t *length); +int nm_platform_link_set_address(NMPlatform *self, int ifindex, const void *address, size_t length); +int nm_platform_link_set_mtu(NMPlatform *self, int ifindex, guint32 mtu); +gboolean nm_platform_link_set_name(NMPlatform *self, int ifindex, const char *name); + +void nm_platform_link_set_sriov_params_async(NMPlatform * self, + int ifindex, + guint num_vfs, + int autoprobe, + NMPlatformAsyncCallback callback, + gpointer callback_data, + GCancellable * cancellable); + +gboolean +nm_platform_link_set_sriov_vfs(NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs); +gboolean nm_platform_link_set_bridge_vlans(NMPlatform * self, + int ifindex, + gboolean on_master, + const NMPlatformBridgeVlan *const *vlans); + +char * nm_platform_link_get_physical_port_id(NMPlatform *self, int ifindex); +guint nm_platform_link_get_dev_id(NMPlatform *self, int ifindex); +gboolean nm_platform_link_get_wake_on_lan(NMPlatform *self, int ifindex); +gboolean nm_platform_link_get_driver_info(NMPlatform *self, + int ifindex, + char ** out_driver_name, + char ** out_driver_version, + char ** out_fw_version); + +gboolean nm_platform_link_supports_carrier_detect(NMPlatform *self, int ifindex); +gboolean nm_platform_link_supports_vlans(NMPlatform *self, int ifindex); +gboolean nm_platform_link_supports_sriov(NMPlatform *self, int ifindex); + +gboolean nm_platform_link_enslave(NMPlatform *self, int master, int slave); +gboolean nm_platform_link_release(NMPlatform *self, int master, int slave); + +gboolean nm_platform_sysctl_master_set_option(NMPlatform *self, + int ifindex, + const char *option, + const char *value); +char * nm_platform_sysctl_master_get_option(NMPlatform *self, int ifindex, const char *option); +gboolean nm_platform_sysctl_slave_set_option(NMPlatform *self, + int ifindex, + const char *option, + const char *value); +char * nm_platform_sysctl_slave_get_option(NMPlatform *self, int ifindex, const char *option); + +const NMPObject *nm_platform_link_get_lnk(NMPlatform * self, + int ifindex, + NMLinkType link_type, + const NMPlatformLink **out_link); +const NMPlatformLnkBridge * +nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkGre * +nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkGre * +nm_platform_link_get_lnk_gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIp6Tnl * +nm_platform_link_get_lnk_ip6tnl(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIp6Tnl * +nm_platform_link_get_lnk_ip6gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIp6Tnl * +nm_platform_link_get_lnk_ip6gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIpIp * +nm_platform_link_get_lnk_ipip(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkInfiniband * +nm_platform_link_get_lnk_infiniband(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIpIp * +nm_platform_link_get_lnk_ipip(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkMacsec * +nm_platform_link_get_lnk_macsec(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkMacvlan * +nm_platform_link_get_lnk_macvlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkMacvlan * +nm_platform_link_get_lnk_macvtap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkSit * +nm_platform_link_get_lnk_sit(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkTun * +nm_platform_link_get_lnk_tun(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkVlan * +nm_platform_link_get_lnk_vlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkVrf * +nm_platform_link_get_lnk_vrf(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkVxlan * +nm_platform_link_get_lnk_vxlan(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkWireGuard * +nm_platform_link_get_lnk_wireguard(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); + +gboolean nm_platform_link_vlan_set_ingress_map(NMPlatform *self, int ifindex, int from, int to); +gboolean nm_platform_link_vlan_set_egress_map(NMPlatform *self, int ifindex, int from, int to); +gboolean nm_platform_link_vlan_change(NMPlatform * self, + int ifindex, + NMVlanFlags flags_mask, + NMVlanFlags flags_set, + gboolean ingress_reset_all, + const NMVlanQosMapping *ingress_map, + gsize n_ingress_map, + gboolean egress_reset_all, + const NMVlanQosMapping *egress_map, + gsize n_egress_map); + +int nm_platform_link_infiniband_add(NMPlatform * self, + int parent, + int p_key, + const NMPlatformLink **out_link); +int nm_platform_link_infiniband_delete(NMPlatform *self, int parent, int p_key); +gboolean nm_platform_link_infiniband_get_properties(NMPlatform * self, + int ifindex, + int * parent, + int * p_key, + const char **mode); + +gboolean nm_platform_link_veth_get_properties(NMPlatform *self, int ifindex, int *out_peer_ifindex); +gboolean nm_platform_link_tun_get_properties(NMPlatform * self, + int ifindex, + NMPlatformLnkTun *out_properties); + +gboolean +nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps); +gboolean nm_platform_wifi_get_bssid(NMPlatform *self, int ifindex, guint8 *bssid); +guint32 nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex); +int nm_platform_wifi_get_quality(NMPlatform *self, int ifindex); +guint32 nm_platform_wifi_get_rate(NMPlatform *self, int ifindex); +NM80211Mode nm_platform_wifi_get_mode(NMPlatform *self, int ifindex); +void nm_platform_wifi_set_mode(NMPlatform *self, int ifindex, NM80211Mode mode); +void nm_platform_wifi_set_powersave(NMPlatform *self, int ifindex, guint32 powersave); +guint32 nm_platform_wifi_find_frequency(NMPlatform *self, int ifindex, const guint32 *freqs); +void nm_platform_wifi_indicate_addressing_running(NMPlatform *self, int ifindex, gboolean running); +NMSettingWirelessWakeOnWLan nm_platform_wifi_get_wake_on_wlan(NMPlatform *self, int ifindex); +gboolean +nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl); + +guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex); +gboolean nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel); +gboolean nm_platform_mesh_set_ssid(NMPlatform *self, int ifindex, const guint8 *ssid, gsize len); + +guint16 nm_platform_wpan_get_pan_id(NMPlatform *self, int ifindex); +gboolean nm_platform_wpan_set_pan_id(NMPlatform *self, int ifindex, guint16 pan_id); +guint16 nm_platform_wpan_get_short_addr(NMPlatform *self, int ifindex); +gboolean nm_platform_wpan_set_short_addr(NMPlatform *self, int ifindex, guint16 short_addr); +gboolean nm_platform_wpan_set_channel(NMPlatform *self, int ifindex, guint8 page, guint8 channel); + +void nm_platform_ip4_address_set_addr(NMPlatformIP4Address *addr, in_addr_t address, guint8 plen); +const struct in6_addr *nm_platform_ip6_address_get_peer(const NMPlatformIP6Address *addr); + +const NMPlatformIP4Address *nm_platform_ip4_address_get(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address); + +int nm_platform_link_sit_add(NMPlatform * self, + const char * name, + const NMPlatformLnkSit *props, + const NMPlatformLink ** out_link); +int nm_platform_link_tun_add(NMPlatform * self, + const char * name, + const NMPlatformLnkTun *props, + const NMPlatformLink ** out_link, + int * out_fd); +gboolean nm_platform_link_6lowpan_get_properties(NMPlatform *self, int ifindex, int *out_parent); + +int +nm_platform_link_wireguard_add(NMPlatform *self, const char *name, const NMPlatformLink **out_link); + +int nm_platform_link_wireguard_change(NMPlatform * self, + int ifindex, + const NMPlatformLnkWireGuard * lnk_wireguard, + const struct _NMPWireGuardPeer * peers, + const NMPlatformWireGuardChangePeerFlags *peer_flags, + guint peers_len, + NMPlatformWireGuardChangeFlags change_flags); + +const NMPlatformIP6Address * +nm_platform_ip6_address_get(NMPlatform *self, int ifindex, const struct in6_addr *address); + +gboolean nm_platform_object_delete(NMPlatform *self, const NMPObject *route); + +gboolean nm_platform_ip4_address_add(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address, + in_addr_t broadcast_address, + guint32 lifetime, + guint32 preferred_lft, + guint32 flags, + const char *label); +gboolean nm_platform_ip6_address_add(NMPlatform * self, + int ifindex, + struct in6_addr address, + guint8 plen, + struct in6_addr peer_address, + guint32 lifetime, + guint32 preferred_lft, + guint32 flags); +gboolean nm_platform_ip4_address_delete(NMPlatform *self, + int ifindex, + in_addr_t address, + guint8 plen, + in_addr_t peer_address); +gboolean +nm_platform_ip6_address_delete(NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen); + +gboolean nm_platform_ip_address_sync(NMPlatform *self, + int addr_family, + int ifindex, + GPtrArray * known_addresses, + GPtrArray * addresses_prune); + +GPtrArray *nm_platform_ip_address_get_prune_list(NMPlatform *self, + int addr_family, + int ifindex, + gboolean exclude_ipv6_temporary_addrs); + +static inline gboolean +_nm_platform_ip_address_sync(NMPlatform *self, + int addr_family, + int ifindex, + GPtrArray * known_addresses, + gboolean full_sync) +{ + gs_unref_ptrarray GPtrArray *addresses_prune = NULL; + + addresses_prune = nm_platform_ip_address_get_prune_list(self, addr_family, ifindex, !full_sync); + return nm_platform_ip_address_sync(self, + addr_family, + ifindex, + known_addresses, + addresses_prune); +} + +static inline gboolean +nm_platform_ip4_address_sync(NMPlatform *self, int ifindex, GPtrArray *known_addresses) +{ + return _nm_platform_ip_address_sync(self, AF_INET, ifindex, known_addresses, TRUE); +} + +static inline gboolean +nm_platform_ip6_address_sync(NMPlatform *self, + int ifindex, + GPtrArray * known_addresses, + gboolean full_sync) +{ + return _nm_platform_ip_address_sync(self, AF_INET6, ifindex, known_addresses, full_sync); +} + +gboolean nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex); + +static inline gconstpointer +nm_platform_ip_address_get_peer_address(int addr_family, const NMPlatformIPAddress *addr) +{ + nm_assert_addr_family(addr_family); + nm_assert(addr); + + if (NM_IS_IPv4(addr_family)) + return &((NMPlatformIP4Address *) addr)->peer_address; + return &((NMPlatformIP6Address *) addr)->peer_address; +} + +void nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route); + +static inline guint32 +nm_platform_ip4_route_get_effective_metric(const NMPlatformIP4Route *r) +{ + nm_assert(r); + nm_assert(!r->metric_any || r->metric == 0); + + return r->metric_any ? NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 : r->metric; +} + +static inline guint32 +nm_platform_ip6_route_get_effective_metric(const NMPlatformIP6Route *r) +{ + nm_assert(r); + nm_assert(!r->metric_any || r->metric == 0); + + return r->metric_any ? NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 : r->metric; +} + +static inline guint32 +nm_platform_ip_route_get_effective_table(const NMPlatformIPRoute *r) +{ + nm_assert(r); + nm_assert(!r->table_any || r->table_coerced == 0); + + return r->table_any ? 254u /* RT_TABLE_MAIN */ + : nm_platform_route_table_uncoerce(r->table_coerced, TRUE); +} + +static inline gconstpointer +nm_platform_ip_route_get_gateway(int addr_family, const NMPlatformIPRoute *route) +{ + nm_assert_addr_family(addr_family); + nm_assert(route); + + if (NM_IS_IPv4(addr_family)) + return &((NMPlatformIP4Route *) route)->gateway; + return &((NMPlatformIP6Route *) route)->gateway; +} + +int nm_platform_ip_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPObject *route); +int nm_platform_ip4_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route); +int nm_platform_ip6_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *route); + +GPtrArray *nm_platform_ip_route_get_prune_list(NMPlatform * self, + int addr_family, + int ifindex, + NMIPRouteTableSyncMode route_table_sync); + +gboolean nm_platform_ip_route_sync(NMPlatform *self, + int addr_family, + int ifindex, + GPtrArray * routes, + GPtrArray * routes_prune, + GPtrArray **out_temporary_not_available); + +gboolean nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex); + +int nm_platform_ip_route_get(NMPlatform * self, + int addr_family, + gconstpointer address, + int oif_ifindex, + NMPObject ** out_route); + +int nm_platform_routing_rule_add(NMPlatform * self, + NMPNlmFlags flags, + const NMPlatformRoutingRule *routing_rule); + +int nm_platform_qdisc_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformQdisc *qdisc); +gboolean nm_platform_qdisc_sync(NMPlatform *self, int ifindex, GPtrArray *known_qdiscs); + +int nm_platform_tfilter_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatformTfilter *tfilter); +gboolean nm_platform_tfilter_sync(NMPlatform *self, int ifindex, GPtrArray *known_tfilters); + +const char *nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len); +const char *nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsize len); +const char *nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len); +const char * +nm_platform_lnk_infiniband_to_string(const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); +const char *nm_platform_lnk_ip6tnl_to_string(const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len); +const char *nm_platform_lnk_ipip_to_string(const NMPlatformLnkIpIp *lnk, char *buf, gsize len); +const char *nm_platform_lnk_macsec_to_string(const NMPlatformLnkMacsec *lnk, char *buf, gsize len); +const char * +nm_platform_lnk_macvlan_to_string(const NMPlatformLnkMacvlan *lnk, char *buf, gsize len); +const char *nm_platform_lnk_sit_to_string(const NMPlatformLnkSit *lnk, char *buf, gsize len); +const char *nm_platform_lnk_tun_to_string(const NMPlatformLnkTun *lnk, char *buf, gsize len); +const char *nm_platform_lnk_vlan_to_string(const NMPlatformLnkVlan *lnk, char *buf, gsize len); +const char *nm_platform_lnk_vrf_to_string(const NMPlatformLnkVrf *lnk, char *buf, gsize len); +const char *nm_platform_lnk_vxlan_to_string(const NMPlatformLnkVxlan *lnk, char *buf, gsize len); +const char * +nm_platform_lnk_wireguard_to_string(const NMPlatformLnkWireGuard *lnk, char *buf, gsize len); +const char * +nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf, gsize len); +const char * +nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf, gsize len); +const char *nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsize len); +const char *nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsize len); +const char * +nm_platform_routing_rule_to_string(const NMPlatformRoutingRule *routing_rule, char *buf, gsize len); +const char *nm_platform_qdisc_to_string(const NMPlatformQdisc *qdisc, char *buf, gsize len); +const char *nm_platform_tfilter_to_string(const NMPlatformTfilter *tfilter, char *buf, gsize len); +const char *nm_platform_vf_to_string(const NMPlatformVF *vf, char *buf, gsize len); +const char * +nm_platform_bridge_vlan_to_string(const NMPlatformBridgeVlan *vlan, char *buf, gsize len); + +const char *nm_platform_vlan_qos_mapping_to_string(const char * name, + const NMVlanQosMapping *map, + gsize n_map, + char * buf, + gsize len); + +const char * +nm_platform_wireguard_peer_to_string(const struct _NMPWireGuardPeer *peer, char *buf, gsize len); + +int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b); +int nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b); +int nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); +int nm_platform_lnk_infiniband_cmp(const NMPlatformLnkInfiniband *a, + const NMPlatformLnkInfiniband *b); +int nm_platform_lnk_ip6tnl_cmp(const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b); +int nm_platform_lnk_ipip_cmp(const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b); +int nm_platform_lnk_macsec_cmp(const NMPlatformLnkMacsec *a, const NMPlatformLnkMacsec *b); +int nm_platform_lnk_macvlan_cmp(const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b); +int nm_platform_lnk_sit_cmp(const NMPlatformLnkSit *a, const NMPlatformLnkSit *b); +int nm_platform_lnk_tun_cmp(const NMPlatformLnkTun *a, const NMPlatformLnkTun *b); +int nm_platform_lnk_vlan_cmp(const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b); +int nm_platform_lnk_vrf_cmp(const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b); +int nm_platform_lnk_vxlan_cmp(const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b); +int nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b); +int nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); +int nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b); + +int nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1, + const NMPlatformIP4Address *a2); + +int nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1, + const NMPlatformIP6Address *a2, + gboolean prefer_temp); + +GHashTable *nm_platform_ip4_address_addr_to_hash(NMPlatform *self, int ifindex); + +int nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, + const NMPlatformIP4Route *b, + NMPlatformIPRouteCmpType cmp_type); +int nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, + const NMPlatformIP6Route *b, + NMPlatformIPRouteCmpType cmp_type); static inline int -nm_platform_ip4_route_cmp_full (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b) +nm_platform_ip4_route_cmp_full(const NMPlatformIP4Route *a, const NMPlatformIP4Route *b) { - return nm_platform_ip4_route_cmp (a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL); + return nm_platform_ip4_route_cmp(a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL); } static inline int -nm_platform_ip6_route_cmp_full (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b) +nm_platform_ip6_route_cmp_full(const NMPlatformIP6Route *a, const NMPlatformIP6Route *b) { - return nm_platform_ip6_route_cmp (a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL); + return nm_platform_ip6_route_cmp(a, b, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL); } -int nm_platform_routing_rule_cmp (const NMPlatformRoutingRule *a, const NMPlatformRoutingRule *b, NMPlatformRoutingRuleCmpType cmp_type); +int nm_platform_routing_rule_cmp(const NMPlatformRoutingRule *a, + const NMPlatformRoutingRule *b, + NMPlatformRoutingRuleCmpType cmp_type); static inline int -nm_platform_routing_rule_cmp_full (const NMPlatformRoutingRule *a, const NMPlatformRoutingRule *b) +nm_platform_routing_rule_cmp_full(const NMPlatformRoutingRule *a, const NMPlatformRoutingRule *b) { - return nm_platform_routing_rule_cmp (a, b, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL); + return nm_platform_routing_rule_cmp(a, b, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL); } -int nm_platform_qdisc_cmp (const NMPlatformQdisc *a, const NMPlatformQdisc *b); -int nm_platform_qdisc_cmp_full (const NMPlatformQdisc *a, - const NMPlatformQdisc *b, - gboolean compare_handle); -int nm_platform_tfilter_cmp (const NMPlatformTfilter *a, const NMPlatformTfilter *b); - -void nm_platform_link_hash_update (const NMPlatformLink *obj, NMHashState *h); -void nm_platform_ip4_address_hash_update (const NMPlatformIP4Address *obj, NMHashState *h); -void nm_platform_ip6_address_hash_update (const NMPlatformIP6Address *obj, NMHashState *h); -void nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h); -void nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h); -void nm_platform_routing_rule_hash_update (const NMPlatformRoutingRule *obj, NMPlatformRoutingRuleCmpType cmp_type, NMHashState *h); -void nm_platform_lnk_gre_hash_update (const NMPlatformLnkGre *obj, NMHashState *h); -void nm_platform_lnk_infiniband_hash_update (const NMPlatformLnkInfiniband *obj, NMHashState *h); -void nm_platform_lnk_ip6tnl_hash_update (const NMPlatformLnkIp6Tnl *obj, NMHashState *h); -void nm_platform_lnk_ipip_hash_update (const NMPlatformLnkIpIp *obj, NMHashState *h); -void nm_platform_lnk_macsec_hash_update (const NMPlatformLnkMacsec *obj, NMHashState *h); -void nm_platform_lnk_macvlan_hash_update (const NMPlatformLnkMacvlan *obj, NMHashState *h); -void nm_platform_lnk_sit_hash_update (const NMPlatformLnkSit *obj, NMHashState *h); -void nm_platform_lnk_tun_hash_update (const NMPlatformLnkTun *obj, NMHashState *h); -void nm_platform_lnk_vlan_hash_update (const NMPlatformLnkVlan *obj, NMHashState *h); -void nm_platform_lnk_vrf_hash_update (const NMPlatformLnkVrf *obj, NMHashState *h); -void nm_platform_lnk_vxlan_hash_update (const NMPlatformLnkVxlan *obj, NMHashState *h); -void nm_platform_lnk_wireguard_hash_update (const NMPlatformLnkWireGuard *obj, NMHashState *h); - -void nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h); -void nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h); +int nm_platform_qdisc_cmp(const NMPlatformQdisc *a, const NMPlatformQdisc *b); +int nm_platform_qdisc_cmp_full(const NMPlatformQdisc *a, + const NMPlatformQdisc *b, + gboolean compare_handle); +int nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b); + +void nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h); +void nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h); +void nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h); +void nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, + NMPlatformIPRouteCmpType cmp_type, + NMHashState * h); +void nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, + NMPlatformIPRouteCmpType cmp_type, + NMHashState * h); +void nm_platform_routing_rule_hash_update(const NMPlatformRoutingRule *obj, + NMPlatformRoutingRuleCmpType cmp_type, + NMHashState * h); +void nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *h); +void nm_platform_lnk_gre_hash_update(const NMPlatformLnkGre *obj, NMHashState *h); +void nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h); +void nm_platform_lnk_ip6tnl_hash_update(const NMPlatformLnkIp6Tnl *obj, NMHashState *h); +void nm_platform_lnk_ipip_hash_update(const NMPlatformLnkIpIp *obj, NMHashState *h); +void nm_platform_lnk_macsec_hash_update(const NMPlatformLnkMacsec *obj, NMHashState *h); +void nm_platform_lnk_macvlan_hash_update(const NMPlatformLnkMacvlan *obj, NMHashState *h); +void nm_platform_lnk_sit_hash_update(const NMPlatformLnkSit *obj, NMHashState *h); +void nm_platform_lnk_tun_hash_update(const NMPlatformLnkTun *obj, NMHashState *h); +void nm_platform_lnk_vlan_hash_update(const NMPlatformLnkVlan *obj, NMHashState *h); +void nm_platform_lnk_vrf_hash_update(const NMPlatformLnkVrf *obj, NMHashState *h); +void nm_platform_lnk_vxlan_hash_update(const NMPlatformLnkVxlan *obj, NMHashState *h); +void nm_platform_lnk_wireguard_hash_update(const NMPlatformLnkWireGuard *obj, NMHashState *h); + +void nm_platform_qdisc_hash_update(const NMPlatformQdisc *obj, NMHashState *h); +void nm_platform_tfilter_hash_update(const NMPlatformTfilter *obj, NMHashState *h); #define NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN ((gsize) 162) -const char *nm_platform_link_flags2str (unsigned flags, char *buf, gsize len); -const char *nm_platform_link_inet6_addrgenmode2str (guint8 mode, char *buf, gsize len); -const char *nm_platform_addr_flags2str (unsigned flags, char *buf, gsize len); -const char *nm_platform_route_scope2str (int scope, char *buf, gsize len); - -int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b); - -gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMSettingWiredWakeOnLan wol, const char *wol_password); -gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex); -gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex); +const char *nm_platform_link_flags2str(unsigned flags, char *buf, gsize len); +const char *nm_platform_link_inet6_addrgenmode2str(guint8 mode, char *buf, gsize len); +const char *nm_platform_addr_flags2str(unsigned flags, char *buf, gsize len); +const char *nm_platform_route_scope2str(int scope, char *buf, gsize len); + +int nm_platform_ip_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b); + +gboolean nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, + int ifindex, + NMSettingWiredWakeOnLan wol, + const char * wol_password); +gboolean nm_platform_ethtool_set_link_settings(NMPlatform * self, + int ifindex, + gboolean autoneg, + guint32 speed, + NMPlatformLinkDuplexType duplex); +gboolean nm_platform_ethtool_get_link_settings(NMPlatform * self, + int ifindex, + gboolean * out_autoneg, + guint32 * out_speed, + NMPlatformLinkDuplexType *out_duplex); typedef struct _NMEthtoolFeatureStates NMEthtoolFeatureStates; -NMEthtoolFeatureStates *nm_platform_ethtool_get_link_features (NMPlatform *self, - int ifindex); -gboolean nm_platform_ethtool_set_features (NMPlatform *self, - int ifindex, - const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */); +NMEthtoolFeatureStates *nm_platform_ethtool_get_link_features(NMPlatform *self, int ifindex); +gboolean nm_platform_ethtool_set_features( + NMPlatform * self, + int ifindex, + const NMEthtoolFeatureStates *features, + const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */); typedef struct _NMEthtoolCoalesceState NMEthtoolCoalesceState; -gboolean nm_platform_ethtool_get_link_coalesce (NMPlatform *self, - int ifindex, - NMEthtoolCoalesceState *coalesce); +gboolean nm_platform_ethtool_get_link_coalesce(NMPlatform * self, + int ifindex, + NMEthtoolCoalesceState *coalesce); -gboolean nm_platform_ethtool_set_coalesce (NMPlatform *self, - int ifindex, - const NMEthtoolCoalesceState *coalesce); +gboolean nm_platform_ethtool_set_coalesce(NMPlatform * self, + int ifindex, + const NMEthtoolCoalesceState *coalesce); typedef struct _NMEthtoolRingState NMEthtoolRingState; -gboolean nm_platform_ethtool_get_link_ring (NMPlatform *self, - int ifindex, - NMEthtoolRingState *ring); +gboolean nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring); + +gboolean +nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring); -gboolean nm_platform_ethtool_set_ring (NMPlatform *self, - int ifindex, - const NMEthtoolRingState *ring); +const char *nm_platform_link_duplex_type_to_string(NMPlatformLinkDuplexType duplex); -const char * nm_platform_link_duplex_type_to_string (NMPlatformLinkDuplexType duplex); +void nm_platform_ip4_dev_route_blacklist_set(NMPlatform *self, + int ifindex, + GPtrArray * ip4_dev_route_blacklist); -void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, - int ifindex, - GPtrArray *ip4_dev_route_blacklist); +struct _NMDedupMultiIndex *nm_platform_get_multi_idx(NMPlatform *self); + +/*****************************************************************************/ -struct _NMDedupMultiIndex *nm_platform_get_multi_idx (NMPlatform *self); +gboolean nm_platform_ip6_address_match(const NMPlatformIP6Address *addr, + NMPlatformMatchFlags match_flag); #endif /* __NETWORKMANAGER_PLATFORM_H__ */ diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c index bc91d7a8..07f7a7c9 100644 --- a/src/platform/nmp-netns.c +++ b/src/platform/nmp-netns.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 Red Hat, Inc. */ @@ -28,103 +28,107 @@ #define PROC_SELF_NS_MNT "/proc/self/ns/mnt" #define PROC_SELF_NS_NET "/proc/self/ns/net" -#define _CLONE_NS_ALL ((int) (CLONE_NEWNS | CLONE_NEWNET)) -#define _CLONE_NS_ALL_V CLONE_NEWNS , CLONE_NEWNET +#define _CLONE_NS_ALL ((int) (CLONE_NEWNS | CLONE_NEWNET)) +#define _CLONE_NS_ALL_V CLONE_NEWNS, CLONE_NEWNET -static -NM_UTILS_FLAGS2STR_DEFINE (_clone_ns_to_str, int, - NM_UTILS_FLAGS2STR (CLONE_NEWNS, "mnt"), - NM_UTILS_FLAGS2STR (CLONE_NEWNET, "net"), -); +static NM_UTILS_FLAGS2STR_DEFINE(_clone_ns_to_str, + int, + NM_UTILS_FLAGS2STR(CLONE_NEWNS, "mnt"), + NM_UTILS_FLAGS2STR(CLONE_NEWNET, "net"), ); static const char * -__ns_types_to_str (int ns_types, int ns_types_already_set, char *buf, gsize len) +__ns_types_to_str(int ns_types, int ns_types_already_set, char *buf, gsize len) { - const char *b = buf; - char bb[200]; - - nm_utils_strbuf_append_c (&buf, &len, '['); - if (ns_types & ~ns_types_already_set) { - nm_utils_strbuf_append_str (&buf, &len, - _clone_ns_to_str (ns_types & ~ns_types_already_set, bb, sizeof (bb))); - } - if (ns_types & ns_types_already_set) { - if (ns_types & ~ns_types_already_set) - nm_utils_strbuf_append_c (&buf, &len, '/'); - nm_utils_strbuf_append_str (&buf, &len, - _clone_ns_to_str (ns_types & ns_types_already_set, bb, sizeof (bb))); - } - nm_utils_strbuf_append_c (&buf, &len, ']'); - return b; + const char *b = buf; + char bb[200]; + + nm_utils_strbuf_append_c(&buf, &len, '['); + if (ns_types & ~ns_types_already_set) { + nm_utils_strbuf_append_str( + &buf, + &len, + _clone_ns_to_str(ns_types & ~ns_types_already_set, bb, sizeof(bb))); + } + if (ns_types & ns_types_already_set) { + if (ns_types & ~ns_types_already_set) + nm_utils_strbuf_append_c(&buf, &len, '/'); + nm_utils_strbuf_append_str( + &buf, + &len, + _clone_ns_to_str(ns_types & ns_types_already_set, bb, sizeof(bb))); + } + nm_utils_strbuf_append_c(&buf, &len, ']'); + return b; } #define _ns_types_to_str(ns_types, ns_types_already_set, buf) \ - __ns_types_to_str (ns_types, ns_types_already_set, buf, sizeof (buf)) + __ns_types_to_str(ns_types, ns_types_already_set, buf, sizeof(buf)) /*****************************************************************************/ -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG_PREFIX_NAME "netns" -#define _NMLOG(level, netns, ...) \ - G_STMT_START { \ - NMLogLevel _level = (level); \ - \ - if (nm_logging_enabled (_level, _NMLOG_DOMAIN)) { \ - NMPNetns *_netns = (netns); \ - char _sbuf[20]; \ - \ - _nm_log (_level, _NMLOG_DOMAIN, 0, NULL, NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - (_netns ? nm_sprintf_buf (_sbuf, "[%p]", _netns) : "") \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } G_STMT_END +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG_PREFIX_NAME "netns" +#define _NMLOG(level, netns, ...) \ + G_STMT_START \ + { \ + NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) { \ + NMPNetns *_netns = (netns); \ + char _sbuf[20]; \ + \ + _nm_log(_level, \ + _NMLOG_DOMAIN, \ + 0, \ + NULL, \ + NULL, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (_netns ? nm_sprintf_buf(_sbuf, "[%p]", _netns) \ + : "") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_FD_NET, - PROP_FD_MNT, -); +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_FD_NET, PROP_FD_MNT, ); typedef struct { - int fd_net; - int fd_mnt; + int fd_net; + int fd_mnt; } NMPNetnsPrivate; struct _NMPNetns { - GObject parent; - NMPNetnsPrivate _priv; + GObject parent; + NMPNetnsPrivate _priv; }; struct _NMPNetnsClass { - GObjectClass parent; + GObjectClass parent; }; -G_DEFINE_TYPE (NMPNetns, nmp_netns, G_TYPE_OBJECT); +G_DEFINE_TYPE(NMPNetns, nmp_netns, G_TYPE_OBJECT); -#define NMP_NETNS_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPNetns, NMP_IS_NETNS) +#define NMP_NETNS_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMPNetns, NMP_IS_NETNS) /*****************************************************************************/ typedef struct { - NMPNetns *netns; - int count; - int ns_types; + NMPNetns *netns; + int count; + int ns_types; } NetnsInfo; -static void _stack_push (GArray *netns_stack, - NMPNetns *netns, - int ns_types); -static NMPNetns *_netns_new (GError **error); +static void _stack_push(GArray *netns_stack, NMPNetns *netns, int ns_types); +static NMPNetns *_netns_new(GError **error); /*****************************************************************************/ static NMPNetns * -_netns_get (NetnsInfo *info) +_netns_get(NetnsInfo *info) { - nm_assert (!info || NMP_IS_NETNS (info->netns)); - return info ? info->netns : NULL; + nm_assert(!info || NMP_IS_NETNS(info->netns)); + return info ? info->netns : NULL; } /*****************************************************************************/ @@ -132,634 +136,629 @@ _netns_get (NetnsInfo *info) static _nm_thread_local GArray *_netns_stack = NULL; static void -_netns_stack_clear_cb (gpointer data) +_netns_stack_clear_cb(gpointer data) { - NetnsInfo *info = data; + NetnsInfo *info = data; - nm_assert (NMP_IS_NETNS (info->netns)); - g_object_unref (info->netns); + nm_assert(NMP_IS_NETNS(info->netns)); + g_object_unref(info->netns); } static GArray * -_netns_stack_get_impl (void) +_netns_stack_get_impl(void) { - gs_unref_object NMPNetns *netns = NULL; - gs_free_error GError *error = NULL; - pthread_key_t key; - GArray *s; - - s = g_array_new (FALSE, FALSE, sizeof (NetnsInfo)); - g_array_set_clear_func (s, _netns_stack_clear_cb); - _netns_stack = s; - - /* at the bottom of the stack we must try to create a netns instance - * that we never pop. It's the base to which we need to return. */ - netns = _netns_new (&error); - if (!netns) { - _LOGE (NULL, "failed to create initial netns: %s", error->message); - return s; - } - - /* we leak this instance inside the stack. */ - _stack_push (s, netns, _CLONE_NS_ALL); - - /* finally, register a destructor function to cleanup the array. If we fail - * to do so, we will leak NMPNetns instances (and their file descriptor) when the - * thread exits. */ - if (pthread_key_create (&key, (void (*) (void *)) g_array_unref) != 0) - _LOGE (NULL, "failure to initialize thread-local storage"); - else if (pthread_setspecific (key, s) != 0) - _LOGE (NULL, "failure to set thread-local storage"); - - return s; + gs_unref_object NMPNetns *netns = NULL; + gs_free_error GError *error = NULL; + pthread_key_t key; + GArray * s; + + s = g_array_new(FALSE, FALSE, sizeof(NetnsInfo)); + g_array_set_clear_func(s, _netns_stack_clear_cb); + _netns_stack = s; + + /* at the bottom of the stack we must try to create a netns instance + * that we never pop. It's the base to which we need to return. */ + netns = _netns_new(&error); + if (!netns) { + _LOGE(NULL, "failed to create initial netns: %s", error->message); + return s; + } + + /* we leak this instance inside the stack. */ + _stack_push(s, netns, _CLONE_NS_ALL); + + /* finally, register a destructor function to cleanup the array. If we fail + * to do so, we will leak NMPNetns instances (and their file descriptor) when the + * thread exits. */ + if (pthread_key_create(&key, (void (*)(void *)) g_array_unref) != 0) + _LOGE(NULL, "failure to initialize thread-local storage"); + else if (pthread_setspecific(key, s) != 0) + _LOGE(NULL, "failure to set thread-local storage"); + + return s; } -#define _netns_stack_get() \ - ({ \ - GArray *_s = _netns_stack; \ - \ - if (G_UNLIKELY (!_s)) \ - _s = _netns_stack_get_impl (); \ - _s; \ - }) +#define _netns_stack_get() \ + ({ \ + GArray *_s = _netns_stack; \ + \ + if (G_UNLIKELY(!_s)) \ + _s = _netns_stack_get_impl(); \ + _s; \ + }) /*****************************************************************************/ static NMPNetns * -_stack_current_netns (GArray *netns_stack, - int ns_types) +_stack_current_netns(GArray *netns_stack, int ns_types) { - guint j; + guint j; - nm_assert (netns_stack && netns_stack->len > 0); + nm_assert(netns_stack && netns_stack->len > 0); - /* we search the stack top-down to find the netns that has - * all @ns_types set. */ - for (j = netns_stack->len; ns_types && j >= 1; ) { - NetnsInfo *info; + /* we search the stack top-down to find the netns that has + * all @ns_types set. */ + for (j = netns_stack->len; ns_types && j >= 1;) { + NetnsInfo *info; - info = &g_array_index (netns_stack, NetnsInfo, --j); + info = &g_array_index(netns_stack, NetnsInfo, --j); - if (NM_FLAGS_ALL (info->ns_types, ns_types)) - return info->netns; - } + if (NM_FLAGS_ALL(info->ns_types, ns_types)) + return info->netns; + } - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static int -_stack_current_ns_types (GArray *netns_stack, - NMPNetns *netns, - int ns_types) +_stack_current_ns_types(GArray *netns_stack, NMPNetns *netns, int ns_types) { - const int ns_types_check[] = { _CLONE_NS_ALL_V }; - guint i, j; - int res = 0; - - nm_assert (netns); - nm_assert (netns_stack && netns_stack->len > 0); - - /* we search the stack top-down to check which of @ns_types - * are already set to @netns. */ - for (j = netns_stack->len; ns_types && j >= 1; ) { - NetnsInfo *info; - - info = &g_array_index (netns_stack, NetnsInfo, --j); - if (info->netns != netns) { - ns_types = NM_FLAGS_UNSET (ns_types, info->ns_types); - continue; - } - - for (i = 0; i < G_N_ELEMENTS (ns_types_check); i++) { - if ( NM_FLAGS_ANY (ns_types, ns_types_check[i]) - && NM_FLAGS_ANY (info->ns_types, ns_types_check[i])) { - res = NM_FLAGS_SET (res, ns_types_check[i]); - ns_types = NM_FLAGS_UNSET (ns_types, ns_types_check[i]); - } - } - } - - return res; + const int ns_types_check[] = {_CLONE_NS_ALL_V}; + guint i, j; + int res = 0; + + nm_assert(netns); + nm_assert(netns_stack && netns_stack->len > 0); + + /* we search the stack top-down to check which of @ns_types + * are already set to @netns. */ + for (j = netns_stack->len; ns_types && j >= 1;) { + NetnsInfo *info; + + info = &g_array_index(netns_stack, NetnsInfo, --j); + if (info->netns != netns) { + ns_types = NM_FLAGS_UNSET(ns_types, info->ns_types); + continue; + } + + for (i = 0; i < G_N_ELEMENTS(ns_types_check); i++) { + if (NM_FLAGS_ANY(ns_types, ns_types_check[i]) + && NM_FLAGS_ANY(info->ns_types, ns_types_check[i])) { + res = NM_FLAGS_SET(res, ns_types_check[i]); + ns_types = NM_FLAGS_UNSET(ns_types, ns_types_check[i]); + } + } + } + + return res; } static NetnsInfo * -_stack_peek (GArray *netns_stack) +_stack_peek(GArray *netns_stack) { - if (netns_stack->len > 0) - return &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1)); - return NULL; + if (netns_stack->len > 0) + return &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1)); + return NULL; } static NetnsInfo * -_stack_bottom (GArray *netns_stack) +_stack_bottom(GArray *netns_stack) { - if (netns_stack->len > 0) - return &g_array_index (netns_stack, NetnsInfo, 0); - return NULL; + if (netns_stack->len > 0) + return &g_array_index(netns_stack, NetnsInfo, 0); + return NULL; } static void -_stack_push (GArray *netns_stack, - NMPNetns *netns, - int ns_types) +_stack_push(GArray *netns_stack, NMPNetns *netns, int ns_types) { - NetnsInfo *info; + NetnsInfo *info; - nm_assert (netns_stack); - nm_assert (NMP_IS_NETNS (netns)); - nm_assert (NM_FLAGS_ANY (ns_types, _CLONE_NS_ALL)); - nm_assert (!NM_FLAGS_ANY (ns_types, ~_CLONE_NS_ALL)); + nm_assert(netns_stack); + nm_assert(NMP_IS_NETNS(netns)); + nm_assert(NM_FLAGS_ANY(ns_types, _CLONE_NS_ALL)); + nm_assert(!NM_FLAGS_ANY(ns_types, ~_CLONE_NS_ALL)); - g_array_set_size (netns_stack, netns_stack->len + 1); + g_array_set_size(netns_stack, netns_stack->len + 1); - info = &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1)); - *info = (NetnsInfo) { - .netns = g_object_ref (netns), - .ns_types = ns_types, - .count = 1, - }; + info = &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1)); + *info = (NetnsInfo){ + .netns = g_object_ref(netns), + .ns_types = ns_types, + .count = 1, + }; } static void -_stack_pop (GArray *netns_stack) +_stack_pop(GArray *netns_stack) { - NetnsInfo *info; + NetnsInfo *info; - nm_assert (netns_stack); - nm_assert (netns_stack->len > 1); + nm_assert(netns_stack); + nm_assert(netns_stack->len > 1); - info = &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1)); + info = &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1)); - nm_assert (NMP_IS_NETNS (info->netns)); - nm_assert (info->count == 1); + nm_assert(NMP_IS_NETNS(info->netns)); + nm_assert(info->count == 1); - g_array_set_size (netns_stack, netns_stack->len - 1); + g_array_set_size(netns_stack, netns_stack->len - 1); } static guint -_stack_size (GArray *netns_stack) +_stack_size(GArray *netns_stack) { - nm_assert (netns_stack); + nm_assert(netns_stack); - return netns_stack->len; + return netns_stack->len; } /*****************************************************************************/ static NMPNetns * -_netns_new (GError **error) +_netns_new(GError **error) { - NMPNetns *self; - int fd_net, fd_mnt; - int errsv; - - fd_net = open (PROC_SELF_NS_NET, O_RDONLY | O_CLOEXEC); - if (fd_net == -1) { - errsv = errno; - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "Failed opening netns: %s", - nm_strerror_native (errsv)); - errno = errsv; - return NULL; - } - - fd_mnt = open (PROC_SELF_NS_MNT, O_RDONLY | O_CLOEXEC); - if (fd_mnt == -1) { - errsv = errno; - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "Failed opening mntns: %s", - nm_strerror_native (errsv)); - nm_close (fd_net); - errno = errsv; - return NULL; - } - - self = g_object_new (NMP_TYPE_NETNS, - NMP_NETNS_FD_NET, fd_net, - NMP_NETNS_FD_MNT, fd_mnt, - NULL); - - _LOGD (self, "new netns (net:%d, mnt:%d)", fd_net, fd_mnt); - - return self; + NMPNetns *self; + int fd_net, fd_mnt; + int errsv; + + fd_net = open(PROC_SELF_NS_NET, O_RDONLY | O_CLOEXEC); + if (fd_net == -1) { + errsv = errno; + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "Failed opening netns: %s", + nm_strerror_native(errsv)); + errno = errsv; + return NULL; + } + + fd_mnt = open(PROC_SELF_NS_MNT, O_RDONLY | O_CLOEXEC); + if (fd_mnt == -1) { + errsv = errno; + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "Failed opening mntns: %s", + nm_strerror_native(errsv)); + nm_close(fd_net); + errno = errsv; + return NULL; + } + + self = g_object_new(NMP_TYPE_NETNS, NMP_NETNS_FD_NET, fd_net, NMP_NETNS_FD_MNT, fd_mnt, NULL); + + _LOGD(self, "new netns (net:%d, mnt:%d)", fd_net, fd_mnt); + + return self; } static int -_setns (NMPNetns *self, int type) +_setns(NMPNetns *self, int type) { - char buf[100]; - int fd; - NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE (self); + char buf[100]; + int fd; + NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self); - nm_assert (NM_IN_SET (type, _CLONE_NS_ALL_V)); + nm_assert(NM_IN_SET(type, _CLONE_NS_ALL_V)); - fd = (type == CLONE_NEWNET) ? priv->fd_net : priv->fd_mnt; + fd = (type == CLONE_NEWNET) ? priv->fd_net : priv->fd_mnt; - _LOGt (self, "set netns(%s, %d)", _ns_types_to_str (type, 0, buf), fd); + _LOGt(self, "set netns(%s, %d)", _ns_types_to_str(type, 0, buf), fd); - return setns (fd, type); + return setns(fd, type); } static gboolean -_netns_switch_push (GArray *netns_stack, - NMPNetns *self, - int ns_types) +_netns_switch_push(GArray *netns_stack, NMPNetns *self, int ns_types) { - int errsv; - - if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNET) - && !_stack_current_ns_types (netns_stack, self, CLONE_NEWNET) - && _setns (self, CLONE_NEWNET) != 0) { - errsv = errno; - _LOGE (self, "failed to switch netns: %s", nm_strerror_native (errsv)); - return FALSE; - } - if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNS) - && !_stack_current_ns_types (netns_stack, self, CLONE_NEWNS) - && _setns (self, CLONE_NEWNS) != 0) { - errsv = errno; - _LOGE (self, "failed to switch mntns: %s", nm_strerror_native (errsv)); - - /* try to fix the mess by returning to the previous netns. */ - if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNET) - && !_stack_current_ns_types (netns_stack, self, CLONE_NEWNET)) { - self = _stack_current_netns (netns_stack, CLONE_NEWNET); - if ( self - && _setns (self, CLONE_NEWNET) != 0) { - errsv = errno; - _LOGE (self, "failed to restore netns: %s", nm_strerror_native (errsv)); - } - } - return FALSE; - } - - return TRUE; + int errsv; + + if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET) + && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET) + && _setns(self, CLONE_NEWNET) != 0) { + errsv = errno; + _LOGE(self, "failed to switch netns: %s", nm_strerror_native(errsv)); + return FALSE; + } + if (NM_FLAGS_HAS(ns_types, CLONE_NEWNS) + && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNS) + && _setns(self, CLONE_NEWNS) != 0) { + errsv = errno; + _LOGE(self, "failed to switch mntns: %s", nm_strerror_native(errsv)); + + /* try to fix the mess by returning to the previous netns. */ + if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET) + && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET)) { + self = _stack_current_netns(netns_stack, CLONE_NEWNET); + if (self && _setns(self, CLONE_NEWNET) != 0) { + errsv = errno; + _LOGE(self, "failed to restore netns: %s", nm_strerror_native(errsv)); + } + } + return FALSE; + } + + return TRUE; } static gboolean -_netns_switch_pop (GArray *netns_stack, - NMPNetns *self, - int ns_types) +_netns_switch_pop(GArray *netns_stack, NMPNetns *self, int ns_types) { - int errsv; - NMPNetns *current; - int success = TRUE; - - if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNET) - && ( !self - || !_stack_current_ns_types (netns_stack, self, CLONE_NEWNET))) { - current = _stack_current_netns (netns_stack, CLONE_NEWNET); - if (!current) { - g_warn_if_reached (); - success = FALSE; - } else if (_setns (current, CLONE_NEWNET) != 0) { - errsv = errno; - _LOGE (self, "failed to switch netns: %s", nm_strerror_native (errsv)); - success = FALSE; - } - } - if ( NM_FLAGS_HAS (ns_types, CLONE_NEWNS) - && (!self || !_stack_current_ns_types (netns_stack, self, CLONE_NEWNS))) { - current = _stack_current_netns (netns_stack, CLONE_NEWNS); - if (!current) { - g_warn_if_reached (); - success = FALSE; - } else if (_setns (current, CLONE_NEWNS) != 0) { - errsv = errno; - _LOGE (self, "failed to switch mntns: %s", nm_strerror_native (errsv)); - success = FALSE; - } - } - - return success; + int errsv; + NMPNetns *current; + int success = TRUE; + + if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET) + && (!self || !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET))) { + current = _stack_current_netns(netns_stack, CLONE_NEWNET); + if (!current) { + g_warn_if_reached(); + success = FALSE; + } else if (_setns(current, CLONE_NEWNET) != 0) { + errsv = errno; + _LOGE(self, "failed to switch netns: %s", nm_strerror_native(errsv)); + success = FALSE; + } + } + if (NM_FLAGS_HAS(ns_types, CLONE_NEWNS) + && (!self || !_stack_current_ns_types(netns_stack, self, CLONE_NEWNS))) { + current = _stack_current_netns(netns_stack, CLONE_NEWNS); + if (!current) { + g_warn_if_reached(); + success = FALSE; + } else if (_setns(current, CLONE_NEWNS) != 0) { + errsv = errno; + _LOGE(self, "failed to switch mntns: %s", nm_strerror_native(errsv)); + success = FALSE; + } + } + + return success; } /*****************************************************************************/ int -nmp_netns_get_fd_net (NMPNetns *self) +nmp_netns_get_fd_net(NMPNetns *self) { - g_return_val_if_fail (NMP_IS_NETNS (self), 0); + g_return_val_if_fail(NMP_IS_NETNS(self), 0); - return NMP_NETNS_GET_PRIVATE (self)->fd_net; + return NMP_NETNS_GET_PRIVATE(self)->fd_net; } int -nmp_netns_get_fd_mnt (NMPNetns *self) +nmp_netns_get_fd_mnt(NMPNetns *self) { - g_return_val_if_fail (NMP_IS_NETNS (self), 0); + g_return_val_if_fail(NMP_IS_NETNS(self), 0); - return NMP_NETNS_GET_PRIVATE (self)->fd_mnt; + return NMP_NETNS_GET_PRIVATE(self)->fd_mnt; } /*****************************************************************************/ static gboolean -_nmp_netns_push_type (NMPNetns *self, int ns_types) +_nmp_netns_push_type(NMPNetns *self, int ns_types) { - GArray *netns_stack = _netns_stack_get (); - NetnsInfo *info; - char sbuf[100]; - - info = _stack_peek (netns_stack); - g_return_val_if_fail (info, FALSE); - - if (info->netns == self && info->ns_types == ns_types) { - info->count++; - _LOGt (self, "push#%u* %s (increase count to %d)", - _stack_size (netns_stack) - 1, - _ns_types_to_str (ns_types, ns_types, sbuf), info->count); - return TRUE; - } - - _LOGD (self, "push#%u %s", - _stack_size (netns_stack), - _ns_types_to_str (ns_types, - _stack_current_ns_types (netns_stack, self, ns_types), - sbuf)); - - if (!_netns_switch_push (netns_stack, self, ns_types)) - return FALSE; - - _stack_push (netns_stack, self, ns_types); - return TRUE; + GArray * netns_stack = _netns_stack_get(); + NetnsInfo *info; + char sbuf[100]; + + info = _stack_peek(netns_stack); + g_return_val_if_fail(info, FALSE); + + if (info->netns == self && info->ns_types == ns_types) { + info->count++; + _LOGt(self, + "push#%u* %s (increase count to %d)", + _stack_size(netns_stack) - 1, + _ns_types_to_str(ns_types, ns_types, sbuf), + info->count); + return TRUE; + } + + _LOGD(self, + "push#%u %s", + _stack_size(netns_stack), + _ns_types_to_str(ns_types, _stack_current_ns_types(netns_stack, self, ns_types), sbuf)); + + if (!_netns_switch_push(netns_stack, self, ns_types)) + return FALSE; + + _stack_push(netns_stack, self, ns_types); + return TRUE; } gboolean -nmp_netns_push (NMPNetns *self) +nmp_netns_push(NMPNetns *self) { - g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); + g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); - return _nmp_netns_push_type (self, _CLONE_NS_ALL); + return _nmp_netns_push_type(self, _CLONE_NS_ALL); } gboolean -nmp_netns_push_type (NMPNetns *self, int ns_types) +nmp_netns_push_type(NMPNetns *self, int ns_types) { - g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); - g_return_val_if_fail (!NM_FLAGS_ANY (ns_types, ~_CLONE_NS_ALL), FALSE); + g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); + g_return_val_if_fail(!NM_FLAGS_ANY(ns_types, ~_CLONE_NS_ALL), FALSE); - return _nmp_netns_push_type (self, ns_types == 0 ? _CLONE_NS_ALL : ns_types); + return _nmp_netns_push_type(self, ns_types == 0 ? _CLONE_NS_ALL : ns_types); } NMPNetns * -nmp_netns_new (void) +nmp_netns_new(void) { - GArray *netns_stack = _netns_stack_get (); - NMPNetns *self; - int errsv; - GError *error = NULL; - unsigned long mountflags = 0; - - if (!_stack_peek (netns_stack)) { - /* there are no netns instances. We cannot create a new one - * (because after unshare we couldn't return to the original one). */ - errno = ENOTSUP; - return NULL; - } - - if (unshare (_CLONE_NS_ALL) != 0) { - errsv = errno; - _LOGE (NULL, "failed to create new net and mnt namespace: %s", nm_strerror_native (errsv)); - return NULL; - } - - if (mount ("", "/", "none", MS_SLAVE | MS_REC, NULL) != 0) { - errsv = errno; - _LOGE (NULL, "failed mount --make-rslave: %s", nm_strerror_native (errsv)); - goto err_out; - } - - if (umount2 ("/sys", MNT_DETACH) != 0) { - errsv = errno; - _LOGE (NULL, "failed umount /sys: %s", nm_strerror_native (errsv)); - goto err_out; - } - - if (access ("/sys", W_OK) == -1) - mountflags = MS_RDONLY; - - if (mount ("sysfs", "/sys", "sysfs", mountflags, NULL) != 0) { - errsv = errno; - _LOGE (NULL, "failed mount /sys: %s", nm_strerror_native (errsv)); - goto err_out; - } - - self = _netns_new (&error); - if (!self) { - errsv = errno; - _LOGE (NULL, "failed to create netns after unshare: %s", error->message); - g_clear_error (&error); - goto err_out; - } - - _stack_push (netns_stack, self, _CLONE_NS_ALL); - - return self; + GArray * netns_stack = _netns_stack_get(); + NMPNetns * self; + int errsv; + GError * error = NULL; + unsigned long mountflags = 0; + + if (!_stack_peek(netns_stack)) { + /* there are no netns instances. We cannot create a new one + * (because after unshare we couldn't return to the original one). */ + errno = ENOTSUP; + return NULL; + } + + if (unshare(_CLONE_NS_ALL) != 0) { + errsv = errno; + _LOGE(NULL, "failed to create new net and mnt namespace: %s", nm_strerror_native(errsv)); + return NULL; + } + + if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL) != 0) { + errsv = errno; + _LOGE(NULL, "failed mount --make-rslave: %s", nm_strerror_native(errsv)); + goto err_out; + } + + if (umount2("/sys", MNT_DETACH) != 0) { + errsv = errno; + _LOGE(NULL, "failed umount /sys: %s", nm_strerror_native(errsv)); + goto err_out; + } + + if (access("/sys", W_OK) == -1) + mountflags = MS_RDONLY; + + if (mount("sysfs", "/sys", "sysfs", mountflags, NULL) != 0) { + errsv = errno; + _LOGE(NULL, "failed mount /sys: %s", nm_strerror_native(errsv)); + goto err_out; + } + + self = _netns_new(&error); + if (!self) { + errsv = errno; + _LOGE(NULL, "failed to create netns after unshare: %s", error->message); + g_clear_error(&error); + goto err_out; + } + + _stack_push(netns_stack, self, _CLONE_NS_ALL); + + return self; err_out: - _netns_switch_pop (netns_stack, NULL, _CLONE_NS_ALL); - errno = errsv; - return NULL; + _netns_switch_pop(netns_stack, NULL, _CLONE_NS_ALL); + errno = errsv; + return NULL; } gboolean -nmp_netns_pop (NMPNetns *self) +nmp_netns_pop(NMPNetns *self) { - GArray *netns_stack = _netns_stack_get (); - NetnsInfo *info; - int ns_types; + GArray * netns_stack = _netns_stack_get(); + NetnsInfo *info; + int ns_types; - g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); + g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); - info = _stack_peek (netns_stack); + info = _stack_peek(netns_stack); - g_return_val_if_fail (info, FALSE); - g_return_val_if_fail (info->netns == self, FALSE); + g_return_val_if_fail(info, FALSE); + g_return_val_if_fail(info->netns == self, FALSE); - if (info->count > 1) { - info->count--; - _LOGt (self, "pop#%u* (decrease count to %d)", - _stack_size (netns_stack) - 1, info->count); - return TRUE; - } - g_return_val_if_fail (info->count == 1, FALSE); + if (info->count > 1) { + info->count--; + _LOGt(self, "pop#%u* (decrease count to %d)", _stack_size(netns_stack) - 1, info->count); + return TRUE; + } + g_return_val_if_fail(info->count == 1, FALSE); - /* cannot pop the original netns. */ - g_return_val_if_fail (_stack_size (netns_stack) > 1, FALSE); + /* cannot pop the original netns. */ + g_return_val_if_fail(_stack_size(netns_stack) > 1, FALSE); - _LOGD (self, "pop#%u", _stack_size (netns_stack) - 1); + _LOGD(self, "pop#%u", _stack_size(netns_stack) - 1); - ns_types = info->ns_types; + ns_types = info->ns_types; - _stack_pop (netns_stack); + _stack_pop(netns_stack); - return _netns_switch_pop (netns_stack, self, ns_types); + return _netns_switch_pop(netns_stack, self, ns_types); } NMPNetns * -nmp_netns_get_current (void) +nmp_netns_get_current(void) { - return _netns_get (_stack_peek (_netns_stack_get ())); + return _netns_get(_stack_peek(_netns_stack_get())); } NMPNetns * -nmp_netns_get_initial (void) +nmp_netns_get_initial(void) { - return _netns_get (_stack_bottom (_netns_stack_get ())); + return _netns_get(_stack_bottom(_netns_stack_get())); } gboolean -nmp_netns_is_initial (void) +nmp_netns_is_initial(void) { - GArray *netns_stack = _netns_stack_get (); + GArray *netns_stack = _netns_stack_get(); - return ( _netns_get (_stack_peek (netns_stack)) - == _netns_get (_stack_bottom (netns_stack))); + return (_netns_get(_stack_peek(netns_stack)) == _netns_get(_stack_bottom(netns_stack))); } /*****************************************************************************/ gboolean -nmp_netns_bind_to_path (NMPNetns *self, const char *filename, int *out_fd) +nmp_netns_bind_to_path(NMPNetns *self, const char *filename, int *out_fd) { - gs_free char *dirname = NULL; - int errsv; - int fd; - nm_auto_pop_netns NMPNetns *netns_pop = NULL; - - g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); - g_return_val_if_fail (filename && filename[0] == '/', FALSE); - - if (!nmp_netns_push_type (self, CLONE_NEWNET)) - return FALSE; - netns_pop = self; - - dirname = g_path_get_dirname (filename); - if (mkdir (dirname, 0) != 0) { - errsv = errno; - if (errsv != EEXIST) { - _LOGE (self, "bind: failed to create directory %s: %s", - dirname, nm_strerror_native (errsv)); - return FALSE; - } - } - - if ((fd = creat (filename, S_IRUSR | S_IRGRP | S_IROTH)) == -1) { - errsv = errno; - _LOGE (self, "bind: failed to create %s: %s", - filename, nm_strerror_native (errsv)); - return FALSE; - } - nm_close (fd); - - if (mount (PROC_SELF_NS_NET, filename, "none", MS_BIND, NULL) != 0) { - errsv = errno; - _LOGE (self, "bind: failed to mount %s to %s: %s", - PROC_SELF_NS_NET, filename, nm_strerror_native (errsv)); - unlink (filename); - return FALSE; - } - - if (out_fd) { - if ((fd = open (filename, O_RDONLY | O_CLOEXEC)) == -1) { - errsv = errno; - _LOGE (self, "bind: failed to open %s: %s", filename, nm_strerror_native (errsv)); - umount2 (filename, MNT_DETACH); - unlink (filename); - return FALSE; - } - *out_fd = fd; - } - - return TRUE; + gs_free char * dirname = NULL; + int errsv; + int fd; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; + + g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); + g_return_val_if_fail(filename && filename[0] == '/', FALSE); + + if (!nmp_netns_push_type(self, CLONE_NEWNET)) + return FALSE; + netns_pop = self; + + dirname = g_path_get_dirname(filename); + if (mkdir(dirname, 0) != 0) { + errsv = errno; + if (errsv != EEXIST) { + _LOGE(self, + "bind: failed to create directory %s: %s", + dirname, + nm_strerror_native(errsv)); + return FALSE; + } + } + + if ((fd = creat(filename, S_IRUSR | S_IRGRP | S_IROTH)) == -1) { + errsv = errno; + _LOGE(self, "bind: failed to create %s: %s", filename, nm_strerror_native(errsv)); + return FALSE; + } + nm_close(fd); + + if (mount(PROC_SELF_NS_NET, filename, "none", MS_BIND, NULL) != 0) { + errsv = errno; + _LOGE(self, + "bind: failed to mount %s to %s: %s", + PROC_SELF_NS_NET, + filename, + nm_strerror_native(errsv)); + unlink(filename); + return FALSE; + } + + if (out_fd) { + if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) == -1) { + errsv = errno; + _LOGE(self, "bind: failed to open %s: %s", filename, nm_strerror_native(errsv)); + umount2(filename, MNT_DETACH); + unlink(filename); + return FALSE; + } + *out_fd = fd; + } + + return TRUE; } gboolean -nmp_netns_bind_to_path_destroy (NMPNetns *self, const char *filename) +nmp_netns_bind_to_path_destroy(NMPNetns *self, const char *filename) { - int errsv; - - g_return_val_if_fail (NMP_IS_NETNS (self), FALSE); - g_return_val_if_fail (filename && filename[0] == '/', FALSE); - - if (umount2 (filename, MNT_DETACH) != 0) { - errsv = errno; - _LOGE (self, "bind: failed to unmount2 %s: %s", filename, nm_strerror_native (errsv)); - return FALSE; - } - if (unlink (filename) != 0) { - errsv = errno; - _LOGE (self, "bind: failed to unlink %s: %s", filename, nm_strerror_native (errsv)); - return FALSE; - } - return TRUE; + int errsv; + + g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); + g_return_val_if_fail(filename && filename[0] == '/', FALSE); + + if (umount2(filename, MNT_DETACH) != 0) { + errsv = errno; + _LOGE(self, "bind: failed to unmount2 %s: %s", filename, nm_strerror_native(errsv)); + return FALSE; + } + if (unlink(filename) != 0) { + errsv = errno; + _LOGE(self, "bind: failed to unlink %s: %s", filename, nm_strerror_native(errsv)); + return FALSE; + } + return TRUE; } /*****************************************************************************/ static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMPNetns *self = NMP_NETNS (object); - NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE (self); - - switch (prop_id) { - case PROP_FD_NET: - /* construct-only */ - priv->fd_net = g_value_get_int (value); - g_return_if_fail (priv->fd_net > 0); - break; - case PROP_FD_MNT: - /* construct-only */ - priv->fd_mnt = g_value_get_int (value); - g_return_if_fail (priv->fd_mnt > 0); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + NMPNetns * self = NMP_NETNS(object); + NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self); + + switch (prop_id) { + case PROP_FD_NET: + /* construct-only */ + priv->fd_net = g_value_get_int(value); + g_return_if_fail(priv->fd_net > 0); + break; + case PROP_FD_MNT: + /* construct-only */ + priv->fd_mnt = g_value_get_int(value); + g_return_if_fail(priv->fd_mnt > 0); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } static void -nmp_netns_init (NMPNetns *self) -{ -} +nmp_netns_init(NMPNetns *self) +{} static void -dispose (GObject *object) +dispose(GObject *object) { - NMPNetns *self = NMP_NETNS (object); - NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE (self); + NMPNetns * self = NMP_NETNS(object); + NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self); - nm_close (priv->fd_net); - priv->fd_net = -1; + nm_close(priv->fd_net); + priv->fd_net = -1; - nm_close (priv->fd_mnt); - priv->fd_mnt = -1; + nm_close(priv->fd_mnt); + priv->fd_mnt = -1; - G_OBJECT_CLASS (nmp_netns_parent_class)->dispose (object); + G_OBJECT_CLASS(nmp_netns_parent_class)->dispose(object); } static void -nmp_netns_class_init (NMPNetnsClass *klass) +nmp_netns_class_init(NMPNetnsClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = set_property; - object_class->dispose = dispose; - - obj_properties[PROP_FD_NET] - = g_param_spec_int (NMP_NETNS_FD_NET, "", "", - 0, G_MAXINT, 0, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_FD_MNT] - = g_param_spec_int (NMP_NETNS_FD_MNT, "", "", - 0, G_MAXINT, 0, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->set_property = set_property; + object_class->dispose = dispose; + + obj_properties[PROP_FD_NET] = + g_param_spec_int(NMP_NETNS_FD_NET, + "", + "", + 0, + G_MAXINT, + 0, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_FD_MNT] = + g_param_spec_int(NMP_NETNS_FD_MNT, + "", + "", + 0, + G_MAXINT, + 0, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/platform/nmp-netns.h b/src/platform/nmp-netns.h index a74e2319..2516a79e 100644 --- a/src/platform/nmp-netns.h +++ b/src/platform/nmp-netns.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 Red Hat, Inc. */ @@ -8,46 +8,46 @@ /*****************************************************************************/ -#define NMP_TYPE_NETNS (nmp_netns_get_type ()) -#define NMP_NETNS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMP_TYPE_NETNS, NMPNetns)) -#define NMP_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMP_TYPE_NETNS, NMPNetnsClass)) -#define NMP_IS_NETNS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMP_TYPE_NETNS)) -#define NMP_IS_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMP_TYPE_NETNS)) -#define NMP_NETNS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMP_TYPE_NETNS, NMPNetnsClass)) +#define NMP_TYPE_NETNS (nmp_netns_get_type()) +#define NMP_NETNS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMP_TYPE_NETNS, NMPNetns)) +#define NMP_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NMP_TYPE_NETNS, NMPNetnsClass)) +#define NMP_IS_NETNS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMP_TYPE_NETNS)) +#define NMP_IS_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMP_TYPE_NETNS)) +#define NMP_NETNS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NMP_TYPE_NETNS, NMPNetnsClass)) -#define NMP_NETNS_FD_NET "fd-net" -#define NMP_NETNS_FD_MNT "fd-mnt" +#define NMP_NETNS_FD_NET "fd-net" +#define NMP_NETNS_FD_MNT "fd-mnt" typedef struct _NMPNetnsClass NMPNetnsClass; -GType nmp_netns_get_type (void); +GType nmp_netns_get_type(void); -NMPNetns *nmp_netns_new (void); +NMPNetns *nmp_netns_new(void); -gboolean nmp_netns_push (NMPNetns *self); -gboolean nmp_netns_push_type (NMPNetns *self, int ns_types); -gboolean nmp_netns_pop (NMPNetns *self); +gboolean nmp_netns_push(NMPNetns *self); +gboolean nmp_netns_push_type(NMPNetns *self, int ns_types); +gboolean nmp_netns_pop(NMPNetns *self); -NMPNetns *nmp_netns_get_current (void); -NMPNetns *nmp_netns_get_initial (void); -gboolean nmp_netns_is_initial (void); +NMPNetns *nmp_netns_get_current(void); +NMPNetns *nmp_netns_get_initial(void); +gboolean nmp_netns_is_initial(void); -int nmp_netns_get_fd_net (NMPNetns *self); -int nmp_netns_get_fd_mnt (NMPNetns *self); +int nmp_netns_get_fd_net(NMPNetns *self); +int nmp_netns_get_fd_mnt(NMPNetns *self); static inline void -_nm_auto_pop_netns (NMPNetns **p) +_nm_auto_pop_netns(NMPNetns **p) { - if (*p) { - int errsv = errno; + if (*p) { + int errsv = errno; - nmp_netns_pop (*p); - errno = errsv; - } + nmp_netns_pop(*p); + errno = errsv; + } } #define nm_auto_pop_netns nm_auto(_nm_auto_pop_netns) -gboolean nmp_netns_bind_to_path (NMPNetns *self, const char *filename, int *out_fd); -gboolean nmp_netns_bind_to_path_destroy (NMPNetns *self, const char *filename); +gboolean nmp_netns_bind_to_path(NMPNetns *self, const char *filename, int *out_fd); +gboolean nmp_netns_bind_to_path_destroy(NMPNetns *self, const char *filename); #endif /* __NMP_NETNS_UTILS_H__ */ diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index a6aa5e22..6eea732f 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ @@ -24,109 +24,112 @@ /*****************************************************************************/ #define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG(level, obj, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ - const NMPObject *const __obj = (obj); \ - \ - _nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \ - "nmp-object[%p/%s]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - __obj, \ - (__obj ? NMP_OBJECT_GET_CLASS (__obj)->obj_type_name : "???") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END +#define _NMLOG(level, obj, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ + const NMPObject *const __obj = (obj); \ + \ + _nm_log(__level, \ + _NMLOG_DOMAIN, \ + 0, \ + NULL, \ + NULL, \ + "nmp-object[%p/%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + __obj, \ + (__obj ? NMP_OBJECT_GET_CLASS(__obj)->obj_type_name \ + : "???") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ typedef struct { - NMDedupMultiIdxType parent; - NMPCacheIdType cache_id_type; + NMDedupMultiIdxType parent; + NMPCacheIdType cache_id_type; } DedupMultiIdxType; struct _NMPCache { - /* the cache contains only one hash table for all object types, and similarly - * it contains only one NMMultiIndex. - * This works, because different object types don't ever compare equal and - * because their index ids also don't overlap. - * - * For routes and addresses, the cache contains an address if (and only if) the - * object was reported via netlink. - * For links, the cache contain a link if it was reported by either netlink - * or udev. That means, a link object can be alive, even if it was already - * removed via netlink. - * - * This effectively merges the udev-device cache into the NMPCache. - */ - - NMDedupMultiIndex *multi_idx; - - /* an idx_type entry for each NMP_CACHE_ID_TYPE. Note that NONE (zero) - * is skipped, so the index is shifted by one: idx_type[cache_id_type - 1]. - * - * Don't bother, use _idx_type_get() instead! */ - DedupMultiIdxType idx_types[NMP_CACHE_ID_TYPE_MAX]; - - gboolean use_udev; + /* the cache contains only one hash table for all object types, and similarly + * it contains only one NMMultiIndex. + * This works, because different object types don't ever compare equal and + * because their index ids also don't overlap. + * + * For routes and addresses, the cache contains an address if (and only if) the + * object was reported via netlink. + * For links, the cache contain a link if it was reported by either netlink + * or udev. That means, a link object can be alive, even if it was already + * removed via netlink. + * + * This effectively merges the udev-device cache into the NMPCache. + */ + + NMDedupMultiIndex *multi_idx; + + /* an idx_type entry for each NMP_CACHE_ID_TYPE. Note that NONE (zero) + * is skipped, so the index is shifted by one: idx_type[cache_id_type - 1]. + * + * Don't bother, use _idx_type_get() instead! */ + DedupMultiIdxType idx_types[NMP_CACHE_ID_TYPE_MAX]; + + gboolean use_udev; }; /*****************************************************************************/ int -nm_sock_addr_union_cmp (const NMSockAddrUnion *a, const NMSockAddrUnion *b) +nm_sock_addr_union_cmp(const NMSockAddrUnion *a, const NMSockAddrUnion *b) { - nm_assert (!a || NM_IN_SET (a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); - nm_assert (!b || NM_IN_SET (b->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); + nm_assert(!a || NM_IN_SET(a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); + nm_assert(!b || NM_IN_SET(b->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); - NM_CMP_SELF (a, b); + NM_CMP_SELF(a, b); - NM_CMP_FIELD (a, b, sa.sa_family); - switch (a->sa.sa_family) { - case AF_INET: - NM_CMP_DIRECT (ntohl (a->in.sin_addr.s_addr), ntohl (b->in.sin_addr.s_addr)); - NM_CMP_DIRECT (htons (a->in.sin_port), htons (b->in.sin_port)); - break; - case AF_INET6: - NM_CMP_DIRECT_IN6ADDR (&a->in6.sin6_addr, &b->in6.sin6_addr); - NM_CMP_DIRECT (htons (a->in6.sin6_port), htons (b->in6.sin6_port)); - NM_CMP_FIELD (a, b, in6.sin6_scope_id); - NM_CMP_FIELD (a, b, in6.sin6_flowinfo); - break; - } - return 0; + NM_CMP_FIELD(a, b, sa.sa_family); + switch (a->sa.sa_family) { + case AF_INET: + NM_CMP_DIRECT(ntohl(a->in.sin_addr.s_addr), ntohl(b->in.sin_addr.s_addr)); + NM_CMP_DIRECT(htons(a->in.sin_port), htons(b->in.sin_port)); + break; + case AF_INET6: + NM_CMP_DIRECT_IN6ADDR(&a->in6.sin6_addr, &b->in6.sin6_addr); + NM_CMP_DIRECT(htons(a->in6.sin6_port), htons(b->in6.sin6_port)); + NM_CMP_FIELD(a, b, in6.sin6_scope_id); + NM_CMP_FIELD(a, b, in6.sin6_flowinfo); + break; + } + return 0; } void -nm_sock_addr_union_hash_update (const NMSockAddrUnion *a, NMHashState *h) -{ - if (!a) { - nm_hash_update_val (h, 1241364739u); - return; - } - - nm_assert (NM_IN_SET (a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); - - switch (a->sa.sa_family) { - case AF_INET: - nm_hash_update_vals (h, - a->in.sin_family, - a->in.sin_addr.s_addr, - a->in.sin_port); - return; - case AF_INET6: - nm_hash_update_vals (h, - a->in6.sin6_family, - a->in6.sin6_addr, - a->in6.sin6_port, - a->in6.sin6_scope_id, - a->in6.sin6_flowinfo); - return; - default: - nm_hash_update_val (h, a->sa.sa_family); - return; - } +nm_sock_addr_union_hash_update(const NMSockAddrUnion *a, NMHashState *h) +{ + if (!a) { + nm_hash_update_val(h, 1241364739u); + return; + } + + nm_assert(NM_IN_SET(a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6)); + + switch (a->sa.sa_family) { + case AF_INET: + nm_hash_update_vals(h, a->in.sin_family, a->in.sin_addr.s_addr, a->in.sin_port); + return; + case AF_INET6: + nm_hash_update_vals(h, + a->in6.sin6_family, + a->in6.sin6_addr, + a->in6.sin6_port, + a->in6.sin6_scope_id, + a->in6.sin6_flowinfo); + return; + default: + nm_hash_update_val(h, a->sa.sa_family); + return; + } } /** @@ -142,30 +145,30 @@ nm_sock_addr_union_hash_update (const NMSockAddrUnion *a, NMHashState *h) * @dst will always be fully initialized (including setting all un-used bytes to zero). */ void -nm_sock_addr_union_cpy (NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */) +nm_sock_addr_union_cpy(NMSockAddrUnion *dst, + gconstpointer src /* unaligned (const NMSockAddrUnion *) */) { - struct sockaddr sa; - gsize src_len; + struct sockaddr sa; + gsize src_len; - nm_assert (dst); + nm_assert(dst); - *dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC; + *dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC; - if (!src) - return; + if (!src) + return; - memcpy (&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof (sa.sa_family)); + memcpy(&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof(sa.sa_family)); - if (sa.sa_family == AF_INET) - src_len = sizeof (struct sockaddr_in); - else if (sa.sa_family == AF_INET6) - src_len = sizeof (struct sockaddr_in6); - else - return; + if (sa.sa_family == AF_INET) + src_len = sizeof(struct sockaddr_in); + else if (sa.sa_family == AF_INET6) + src_len = sizeof(struct sockaddr_in6); + else + return; - memcpy (dst, src, src_len); - nm_assert (dst->sa.sa_family == sa.sa_family); + memcpy(dst, src, src_len); + nm_assert(dst->sa.sa_family == sa.sa_family); } /** @@ -186,76 +189,74 @@ nm_sock_addr_union_cpy (NMSockAddrUnion *dst, * @dst will always be fully initialized (including setting all un-used bytes to zero). */ void -nm_sock_addr_union_cpy_untrusted (NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */, - gsize src_len) +nm_sock_addr_union_cpy_untrusted(NMSockAddrUnion *dst, + gconstpointer src /* unaligned (const NMSockAddrUnion *) */, + gsize src_len) { - int f_expected; - struct sockaddr sa; + int f_expected; + struct sockaddr sa; - nm_assert (dst); + nm_assert(dst); - *dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC; + *dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC; - if (src_len == sizeof (struct sockaddr_in)) - f_expected = AF_INET; - else if (src_len == sizeof (struct sockaddr_in6)) - f_expected = AF_INET6; - else - return; + if (src_len == sizeof(struct sockaddr_in)) + f_expected = AF_INET; + else if (src_len == sizeof(struct sockaddr_in6)) + f_expected = AF_INET6; + else + return; - memcpy (&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof (sa.sa_family)); + memcpy(&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof(sa.sa_family)); - if (sa.sa_family != f_expected) - return; + if (sa.sa_family != f_expected) + return; - memcpy (dst, src, src_len); - nm_assert (dst->sa.sa_family == sa.sa_family); + memcpy(dst, src, src_len); + nm_assert(dst->sa.sa_family == sa.sa_family); } const char * -nm_sock_addr_union_to_string (const NMSockAddrUnion *sa, - char *buf, - gsize len) -{ - char s_addr[NM_UTILS_INET_ADDRSTRLEN]; - char s_scope_id[40]; - - if (!nm_utils_to_string_buffer_init_null (sa, &buf, &len)) - return buf; - - /* maybe we should use getnameinfo(), but here implement it ourself. - * - * We want to see the actual bytes for debugging (as we understand them), - * and now what getnameinfo() makes of it. Also, it's simpler this way. */ - - switch (sa->sa.sa_family) { - case AF_INET: - g_snprintf (buf, len, - "%s:%u", - _nm_utils_inet4_ntop (sa->in.sin_addr.s_addr, s_addr), - (guint) htons (sa->in.sin_port)); - break; - case AF_INET6: - g_snprintf (buf, len, - "[%s%s]:%u", - _nm_utils_inet6_ntop (&sa->in6.sin6_addr, s_addr), - ( sa->in6.sin6_scope_id != 0 - ? nm_sprintf_buf (s_scope_id, "%u", sa->in6.sin6_scope_id) - : ""), - (guint) htons (sa->in6.sin6_port)); - break; - case AF_UNSPEC: - g_snprintf (buf, len, "unspec"); - break; - default: - g_snprintf (buf, len, - "{addr-family:%u}", - (unsigned) sa->sa.sa_family); - break; - } - - return buf; +nm_sock_addr_union_to_string(const NMSockAddrUnion *sa, char *buf, gsize len) +{ + char s_addr[NM_UTILS_INET_ADDRSTRLEN]; + char s_scope_id[40]; + + if (!nm_utils_to_string_buffer_init_null(sa, &buf, &len)) + return buf; + + /* maybe we should use getnameinfo(), but here implement it ourself. + * + * We want to see the actual bytes for debugging (as we understand them), + * and now what getnameinfo() makes of it. Also, it's simpler this way. */ + + switch (sa->sa.sa_family) { + case AF_INET: + g_snprintf(buf, + len, + "%s:%u", + _nm_utils_inet4_ntop(sa->in.sin_addr.s_addr, s_addr), + (guint) htons(sa->in.sin_port)); + break; + case AF_INET6: + g_snprintf(buf, + len, + "[%s%s]:%u", + _nm_utils_inet6_ntop(&sa->in6.sin6_addr, s_addr), + (sa->in6.sin6_scope_id != 0 + ? nm_sprintf_buf(s_scope_id, "%u", sa->in6.sin6_scope_id) + : ""), + (guint) htons(sa->in6.sin6_port)); + break; + case AF_UNSPEC: + g_snprintf(buf, len, "unspec"); + break; + default: + g_snprintf(buf, len, "{addr-family:%u}", (unsigned) sa->sa.sa_family); + break; + } + + return buf; } /*****************************************************************************/ @@ -263,974 +264,1014 @@ nm_sock_addr_union_to_string (const NMSockAddrUnion *sa, static const NMDedupMultiIdxTypeClass _dedup_multi_idx_type_class; static void -_idx_obj_id_hash_update (const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj *obj, - NMHashState *h) +_idx_obj_id_hash_update(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj, + NMHashState * h) { - const NMPObject *o = (NMPObject *) obj; + const NMPObject *o = (NMPObject *) obj; - nm_assert (idx_type && idx_type->klass == &_dedup_multi_idx_type_class); - nm_assert (NMP_OBJECT_GET_TYPE (o) != NMP_OBJECT_TYPE_UNKNOWN); + nm_assert(idx_type && idx_type->klass == &_dedup_multi_idx_type_class); + nm_assert(NMP_OBJECT_GET_TYPE(o) != NMP_OBJECT_TYPE_UNKNOWN); - nmp_object_id_hash_update (o, h); + nmp_object_id_hash_update(o, h); } static gboolean -_idx_obj_id_equal (const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj *obj_a, - const NMDedupMultiObj *obj_b) +_idx_obj_id_equal(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj_a, + const NMDedupMultiObj * obj_b) { - const NMPObject *o_a = (NMPObject *) obj_a; - const NMPObject *o_b = (NMPObject *) obj_b; + const NMPObject *o_a = (NMPObject *) obj_a; + const NMPObject *o_b = (NMPObject *) obj_b; - nm_assert (idx_type && idx_type->klass == &_dedup_multi_idx_type_class); - nm_assert (NMP_OBJECT_GET_TYPE (o_a) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert (NMP_OBJECT_GET_TYPE (o_b) != NMP_OBJECT_TYPE_UNKNOWN); + nm_assert(idx_type && idx_type->klass == &_dedup_multi_idx_type_class); + nm_assert(NMP_OBJECT_GET_TYPE(o_a) != NMP_OBJECT_TYPE_UNKNOWN); + nm_assert(NMP_OBJECT_GET_TYPE(o_b) != NMP_OBJECT_TYPE_UNKNOWN); - return nmp_object_id_equal (o_a, o_b); + return nmp_object_id_equal(o_a, o_b); } static guint -_idx_obj_part (const DedupMultiIdxType *idx_type, - const NMPObject *obj_a, - const NMPObject *obj_b, - NMHashState *h) -{ - NMPObjectType obj_type; - - /* the hash/equals functions are strongly related. So, keep them - * side-by-side and do it all in _idx_obj_part(). */ - - nm_assert (idx_type); - nm_assert (idx_type->parent.klass == &_dedup_multi_idx_type_class); - nm_assert (obj_a); - nm_assert (NMP_OBJECT_GET_TYPE (obj_a) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert (!obj_b || (NMP_OBJECT_GET_TYPE (obj_b) != NMP_OBJECT_TYPE_UNKNOWN)); - nm_assert (!h || !obj_b); - - switch (idx_type->cache_id_type) { - - case NMP_CACHE_ID_TYPE_OBJECT_TYPE: - if (obj_b) - return NMP_OBJECT_GET_TYPE (obj_a) == NMP_OBJECT_GET_TYPE (obj_b); - if (h) { - nm_hash_update_vals (h, - idx_type->cache_id_type, - NMP_OBJECT_GET_TYPE (obj_a)); - } - return 1; - - case NMP_CACHE_ID_TYPE_LINK_BY_IFNAME: - if (NMP_OBJECT_GET_TYPE (obj_a) != NMP_OBJECT_TYPE_LINK) { - /* first check, whether obj_a is suitable for this idx_type. - * If not, return 0 (which is correct for partitionable(), hash() and equal() - * functions. */ - if (h) - nm_hash_update_val (h, obj_a); - return 0; - } - if (obj_b) { - /* we are in equal() mode. Compare obj_b with obj_a. */ - return NMP_OBJECT_GET_TYPE (obj_b) == NMP_OBJECT_TYPE_LINK - && nm_streq (obj_a->link.name, obj_b->link.name); - } - if (h) { - nm_hash_update_val (h, idx_type->cache_id_type); - nm_hash_update_strarr (h, obj_a->link.name); - } - /* just return 1, to indicate that obj_a is partitionable by this idx_type. */ - return 1; - - case NMP_CACHE_ID_TYPE_DEFAULT_ROUTES: - if ( !NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_a), NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE) - || !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (&obj_a->ip_route) - || !nmp_object_is_visible (obj_a)) { - if (h) - nm_hash_update_val (h, obj_a); - return 0; - } - if (obj_b) { - return NMP_OBJECT_GET_TYPE (obj_a) == NMP_OBJECT_GET_TYPE (obj_b) - && NM_PLATFORM_IP_ROUTE_IS_DEFAULT (&obj_b->ip_route) - && nmp_object_is_visible (obj_b); - } - if (h) { - nm_hash_update_vals (h, - idx_type->cache_id_type, - NMP_OBJECT_GET_TYPE (obj_a)); - } - return 1; - - case NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX: - if ( !NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_a), NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE, - NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER) - || !nmp_object_is_visible (obj_a)) { - if (h) - nm_hash_update_val (h, obj_a); - return 0; - } - nm_assert (NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (obj_a)->ifindex > 0); - if (obj_b) { - return NMP_OBJECT_GET_TYPE (obj_a) == NMP_OBJECT_GET_TYPE (obj_b) - && NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (obj_a)->ifindex == NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (obj_b)->ifindex - && nmp_object_is_visible (obj_b); - } - if (h) { - nm_hash_update_vals (h, - idx_type->cache_id_type, - obj_a->obj_with_ifindex.ifindex); - } - return 1; - - case NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID: - obj_type = NMP_OBJECT_GET_TYPE (obj_a); - if ( !NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE) - || NMP_OBJECT_CAST_IP_ROUTE (obj_a)->ifindex <= 0) { - if (h) - nm_hash_update_val (h, obj_a); - return 0; - } - if (obj_b) { - return obj_type == NMP_OBJECT_GET_TYPE (obj_b) - && NMP_OBJECT_CAST_IP_ROUTE (obj_b)->ifindex > 0 - && (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE - ? (nm_platform_ip4_route_cmp (&obj_a->ip4_route, &obj_b->ip4_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) == 0) - : (nm_platform_ip6_route_cmp (&obj_a->ip6_route, &obj_b->ip6_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) == 0)); - } - if (h) { - nm_hash_update_val (h, idx_type->cache_id_type); - if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) - nm_platform_ip4_route_hash_update (&obj_a->ip4_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, h); - else - nm_platform_ip6_route_hash_update (&obj_a->ip6_route, NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, h); - } - return 1; - - case NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY: - obj_type = NMP_OBJECT_GET_TYPE (obj_a); - /* currently, only routing rules are supported for this cache-id-type. */ - if ( obj_type != NMP_OBJECT_TYPE_ROUTING_RULE - || !NM_IN_SET (obj_a->routing_rule.addr_family, AF_INET, AF_INET6)) { - if (h) - nm_hash_update_val (h, obj_a); - return 0; - } - if (obj_b) { - return NMP_OBJECT_GET_TYPE (obj_b) == NMP_OBJECT_TYPE_ROUTING_RULE - && obj_a->routing_rule.addr_family == obj_b->routing_rule.addr_family; - } - if (h) { - nm_hash_update_vals (h, idx_type->cache_id_type, - obj_a->routing_rule.addr_family); - } - return 1; - - case NMP_CACHE_ID_TYPE_NONE: - case __NMP_CACHE_ID_TYPE_MAX: - break; - } - nm_assert_not_reached (); - return 0; +_idx_obj_part(const DedupMultiIdxType *idx_type, + const NMPObject * obj_a, + const NMPObject * obj_b, + NMHashState * h) +{ + NMPObjectType obj_type; + + /* the hash/equals functions are strongly related. So, keep them + * side-by-side and do it all in _idx_obj_part(). */ + + nm_assert(idx_type); + nm_assert(idx_type->parent.klass == &_dedup_multi_idx_type_class); + nm_assert(obj_a); + nm_assert(NMP_OBJECT_GET_TYPE(obj_a) != NMP_OBJECT_TYPE_UNKNOWN); + nm_assert(!obj_b || (NMP_OBJECT_GET_TYPE(obj_b) != NMP_OBJECT_TYPE_UNKNOWN)); + nm_assert(!h || !obj_b); + + switch (idx_type->cache_id_type) { + case NMP_CACHE_ID_TYPE_OBJECT_TYPE: + if (obj_b) + return NMP_OBJECT_GET_TYPE(obj_a) == NMP_OBJECT_GET_TYPE(obj_b); + if (h) { + nm_hash_update_vals(h, idx_type->cache_id_type, NMP_OBJECT_GET_TYPE(obj_a)); + } + return 1; + + case NMP_CACHE_ID_TYPE_LINK_BY_IFNAME: + if (NMP_OBJECT_GET_TYPE(obj_a) != NMP_OBJECT_TYPE_LINK) { + /* first check, whether obj_a is suitable for this idx_type. + * If not, return 0 (which is correct for partitionable(), hash() and equal() + * functions. */ + if (h) + nm_hash_update_val(h, obj_a); + return 0; + } + if (obj_b) { + /* we are in equal() mode. Compare obj_b with obj_a. */ + return NMP_OBJECT_GET_TYPE(obj_b) == NMP_OBJECT_TYPE_LINK + && nm_streq(obj_a->link.name, obj_b->link.name); + } + if (h) { + nm_hash_update_val(h, idx_type->cache_id_type); + nm_hash_update_strarr(h, obj_a->link.name); + } + /* just return 1, to indicate that obj_a is partitionable by this idx_type. */ + return 1; + + case NMP_CACHE_ID_TYPE_DEFAULT_ROUTES: + if (!NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_a), + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE) + || !NM_PLATFORM_IP_ROUTE_IS_DEFAULT(&obj_a->ip_route) + || !nmp_object_is_visible(obj_a)) { + if (h) + nm_hash_update_val(h, obj_a); + return 0; + } + if (obj_b) { + return NMP_OBJECT_GET_TYPE(obj_a) == NMP_OBJECT_GET_TYPE(obj_b) + && NM_PLATFORM_IP_ROUTE_IS_DEFAULT(&obj_b->ip_route) + && nmp_object_is_visible(obj_b); + } + if (h) { + nm_hash_update_vals(h, idx_type->cache_id_type, NMP_OBJECT_GET_TYPE(obj_a)); + } + return 1; + + case NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX: + if (!NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_a), + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE, + NMP_OBJECT_TYPE_QDISC, + NMP_OBJECT_TYPE_TFILTER) + || !nmp_object_is_visible(obj_a)) { + if (h) + nm_hash_update_val(h, obj_a); + return 0; + } + nm_assert(NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_a)->ifindex > 0); + if (obj_b) { + return NMP_OBJECT_GET_TYPE(obj_a) == NMP_OBJECT_GET_TYPE(obj_b) + && NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_a)->ifindex + == NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_b)->ifindex + && nmp_object_is_visible(obj_b); + } + if (h) { + nm_hash_update_vals(h, idx_type->cache_id_type, obj_a->obj_with_ifindex.ifindex); + } + return 1; + + case NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID: + obj_type = NMP_OBJECT_GET_TYPE(obj_a); + if (!NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) + || NMP_OBJECT_CAST_IP_ROUTE(obj_a)->ifindex <= 0) { + if (h) + nm_hash_update_val(h, obj_a); + return 0; + } + if (obj_b) { + return obj_type == NMP_OBJECT_GET_TYPE(obj_b) + && NMP_OBJECT_CAST_IP_ROUTE(obj_b)->ifindex > 0 + && (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE + ? (nm_platform_ip4_route_cmp(&obj_a->ip4_route, + &obj_b->ip4_route, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) + == 0) + : (nm_platform_ip6_route_cmp(&obj_a->ip6_route, + &obj_b->ip6_route, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID) + == 0)); + } + if (h) { + nm_hash_update_val(h, idx_type->cache_id_type); + if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) + nm_platform_ip4_route_hash_update(&obj_a->ip4_route, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, + h); + else + nm_platform_ip6_route_hash_update(&obj_a->ip6_route, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, + h); + } + return 1; + + case NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY: + obj_type = NMP_OBJECT_GET_TYPE(obj_a); + /* currently, only routing rules are supported for this cache-id-type. */ + if (obj_type != NMP_OBJECT_TYPE_ROUTING_RULE + || !NM_IN_SET(obj_a->routing_rule.addr_family, AF_INET, AF_INET6)) { + if (h) + nm_hash_update_val(h, obj_a); + return 0; + } + if (obj_b) { + return NMP_OBJECT_GET_TYPE(obj_b) == NMP_OBJECT_TYPE_ROUTING_RULE + && obj_a->routing_rule.addr_family == obj_b->routing_rule.addr_family; + } + if (h) { + nm_hash_update_vals(h, idx_type->cache_id_type, obj_a->routing_rule.addr_family); + } + return 1; + + case NMP_CACHE_ID_TYPE_NONE: + case __NMP_CACHE_ID_TYPE_MAX: + break; + } + nm_assert_not_reached(); + return 0; } static gboolean -_idx_obj_partitionable (const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj *obj) +_idx_obj_partitionable(const NMDedupMultiIdxType *idx_type, const NMDedupMultiObj *obj) { - return _idx_obj_part ((DedupMultiIdxType *) idx_type, - (NMPObject *) obj, - NULL, - NULL) != 0; + return _idx_obj_part((DedupMultiIdxType *) idx_type, (NMPObject *) obj, NULL, NULL) != 0; } static void -_idx_obj_partition_hash_update (const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj *obj, - NMHashState *h) +_idx_obj_partition_hash_update(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj, + NMHashState * h) { - _idx_obj_part ((DedupMultiIdxType *) idx_type, - (NMPObject *) obj, - NULL, - h); + _idx_obj_part((DedupMultiIdxType *) idx_type, (NMPObject *) obj, NULL, h); } static gboolean -_idx_obj_partition_equal (const NMDedupMultiIdxType *idx_type, - const NMDedupMultiObj *obj_a, - const NMDedupMultiObj *obj_b) +_idx_obj_partition_equal(const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj * obj_a, + const NMDedupMultiObj * obj_b) { - return _idx_obj_part ((DedupMultiIdxType *) idx_type, - (NMPObject *) obj_a, - (NMPObject *) obj_b, - NULL); + return _idx_obj_part((DedupMultiIdxType *) idx_type, + (NMPObject *) obj_a, + (NMPObject *) obj_b, + NULL); } static const NMDedupMultiIdxTypeClass _dedup_multi_idx_type_class = { - .idx_obj_id_hash_update = _idx_obj_id_hash_update, - .idx_obj_id_equal = _idx_obj_id_equal, - .idx_obj_partitionable = _idx_obj_partitionable, - .idx_obj_partition_hash_update = _idx_obj_partition_hash_update, - .idx_obj_partition_equal = _idx_obj_partition_equal, + .idx_obj_id_hash_update = _idx_obj_id_hash_update, + .idx_obj_id_equal = _idx_obj_id_equal, + .idx_obj_partitionable = _idx_obj_partitionable, + .idx_obj_partition_hash_update = _idx_obj_partition_hash_update, + .idx_obj_partition_equal = _idx_obj_partition_equal, }; static void -_dedup_multi_idx_type_init (DedupMultiIdxType *idx_type, NMPCacheIdType cache_id_type) +_dedup_multi_idx_type_init(DedupMultiIdxType *idx_type, NMPCacheIdType cache_id_type) { - nm_dedup_multi_idx_type_init ((NMDedupMultiIdxType *) idx_type, - &_dedup_multi_idx_type_class); - idx_type->cache_id_type = cache_id_type; + nm_dedup_multi_idx_type_init((NMDedupMultiIdxType *) idx_type, &_dedup_multi_idx_type_class); + idx_type->cache_id_type = cache_id_type; } /*****************************************************************************/ static void -_vlan_xgress_qos_mappings_hash_update (guint n_map, - const NMVlanQosMapping *map, - NMHashState *h) +_vlan_xgress_qos_mappings_hash_update(guint n_map, const NMVlanQosMapping *map, NMHashState *h) { - /* ensure no padding. */ - G_STATIC_ASSERT (sizeof (NMVlanQosMapping) == 2 * sizeof (guint32)); + /* ensure no padding. */ + G_STATIC_ASSERT(sizeof(NMVlanQosMapping) == 2 * sizeof(guint32)); - nm_hash_update_val (h, n_map); - if (n_map) - nm_hash_update (h, map, n_map * sizeof (*map)); + nm_hash_update_val(h, n_map); + if (n_map) + nm_hash_update(h, map, n_map * sizeof(*map)); } static int -_vlan_xgress_qos_mappings_cmp (guint n_map, - const NMVlanQosMapping *map1, - const NMVlanQosMapping *map2) +_vlan_xgress_qos_mappings_cmp(guint n_map, + const NMVlanQosMapping *map1, + const NMVlanQosMapping *map2) { - guint i; + guint i; - for (i = 0; i < n_map; i++) { - if (map1[i].from != map2[i].from) - return map1[i].from < map2[i].from ? -1 : 1; - if (map1[i].to != map2[i].to) - return map1[i].to < map2[i].to ? -1 : 1; - } - return 0; + for (i = 0; i < n_map; i++) { + if (map1[i].from != map2[i].from) + return map1[i].from < map2[i].from ? -1 : 1; + if (map1[i].to != map2[i].to) + return map1[i].to < map2[i].to ? -1 : 1; + } + return 0; } static void -_vlan_xgress_qos_mappings_cpy (guint *dst_n_map, - NMVlanQosMapping **dst_map, - guint src_n_map, - const NMVlanQosMapping *src_map) -{ - if (src_n_map == 0) { - nm_clear_g_free (dst_map); - *dst_n_map = 0; - } else if ( src_n_map != *dst_n_map - || _vlan_xgress_qos_mappings_cmp (src_n_map, *dst_map, src_map) != 0) { - nm_clear_g_free (dst_map); - *dst_n_map = src_n_map; - if (src_n_map > 0) - *dst_map = nm_memdup (src_map, sizeof (*src_map) * src_n_map); - } +_vlan_xgress_qos_mappings_cpy(guint * dst_n_map, + NMVlanQosMapping ** dst_map, + guint src_n_map, + const NMVlanQosMapping *src_map) +{ + if (src_n_map == 0) { + nm_clear_g_free(dst_map); + *dst_n_map = 0; + } else if (src_n_map != *dst_n_map + || _vlan_xgress_qos_mappings_cmp(src_n_map, *dst_map, src_map) != 0) { + nm_clear_g_free(dst_map); + *dst_n_map = src_n_map; + if (src_n_map > 0) + *dst_map = nm_memdup(src_map, sizeof(*src_map) * src_n_map); + } } /*****************************************************************************/ static void -_wireguard_allowed_ip_hash_update (const NMPWireGuardAllowedIP *ip, - NMHashState *h) +_wireguard_allowed_ip_hash_update(const NMPWireGuardAllowedIP *ip, NMHashState *h) { - nm_hash_update_vals (h, ip->family, - ip->mask); + nm_hash_update_vals(h, ip->family, ip->mask); - if (ip->family == AF_INET) - nm_hash_update_val (h, ip->addr.addr4); - else if (ip->family == AF_INET6) - nm_hash_update_val (h, ip->addr.addr6); + if (ip->family == AF_INET) + nm_hash_update_val(h, ip->addr.addr4); + else if (ip->family == AF_INET6) + nm_hash_update_val(h, ip->addr.addr6); } static int -_wireguard_allowed_ip_cmp (const NMPWireGuardAllowedIP *a, - const NMPWireGuardAllowedIP *b) +_wireguard_allowed_ip_cmp(const NMPWireGuardAllowedIP *a, const NMPWireGuardAllowedIP *b) { - NM_CMP_SELF (a, b); + NM_CMP_SELF(a, b); - NM_CMP_FIELD (a, b, family); - NM_CMP_FIELD (a, b, mask); + NM_CMP_FIELD(a, b, family); + NM_CMP_FIELD(a, b, mask); - if (a->family == AF_INET) - NM_CMP_FIELD (a, b, addr.addr4); - else if (a->family == AF_INET6) - NM_CMP_FIELD_IN6ADDR (a, b, addr.addr6); + if (a->family == AF_INET) + NM_CMP_FIELD(a, b, addr.addr4); + else if (a->family == AF_INET6) + NM_CMP_FIELD_IN6ADDR(a, b, addr.addr6); - return 0; + return 0; } static void -_wireguard_peer_hash_update (const NMPWireGuardPeer *peer, - NMHashState *h) +_wireguard_peer_hash_update(const NMPWireGuardPeer *peer, NMHashState *h) { - guint i; + guint i; - nm_hash_update (h, peer->public_key, sizeof (peer->public_key)); - nm_hash_update (h, peer->preshared_key, sizeof (peer->preshared_key)); - nm_hash_update_vals (h, - peer->persistent_keepalive_interval, - peer->allowed_ips_len, - peer->rx_bytes, - peer->tx_bytes, - peer->last_handshake_time.tv_sec, - peer->last_handshake_time.tv_nsec); + nm_hash_update(h, peer->public_key, sizeof(peer->public_key)); + nm_hash_update(h, peer->preshared_key, sizeof(peer->preshared_key)); + nm_hash_update_vals(h, + peer->persistent_keepalive_interval, + peer->allowed_ips_len, + peer->rx_bytes, + peer->tx_bytes, + peer->last_handshake_time.tv_sec, + peer->last_handshake_time.tv_nsec); - nm_sock_addr_union_hash_update (&peer->endpoint, h); + nm_sock_addr_union_hash_update(&peer->endpoint, h); - for (i = 0; i < peer->allowed_ips_len; i++) - _wireguard_allowed_ip_hash_update (&peer->allowed_ips[i], h); + for (i = 0; i < peer->allowed_ips_len; i++) + _wireguard_allowed_ip_hash_update(&peer->allowed_ips[i], h); } static int -_wireguard_peer_cmp (const NMPWireGuardPeer *a, - const NMPWireGuardPeer *b) +_wireguard_peer_cmp(const NMPWireGuardPeer *a, const NMPWireGuardPeer *b) { - guint i; + guint i; - NM_CMP_SELF (a, b); + NM_CMP_SELF(a, b); - NM_CMP_FIELD (a, b, last_handshake_time.tv_sec); - NM_CMP_FIELD (a, b, last_handshake_time.tv_nsec); - NM_CMP_FIELD (a, b, rx_bytes); - NM_CMP_FIELD (a, b, tx_bytes); - NM_CMP_FIELD (a, b, allowed_ips_len); - NM_CMP_FIELD (a, b, persistent_keepalive_interval); - NM_CMP_FIELD (a, b, endpoint.sa.sa_family); - NM_CMP_FIELD_MEMCMP (a, b, public_key); - NM_CMP_FIELD_MEMCMP (a, b, preshared_key); + NM_CMP_FIELD(a, b, last_handshake_time.tv_sec); + NM_CMP_FIELD(a, b, last_handshake_time.tv_nsec); + NM_CMP_FIELD(a, b, rx_bytes); + NM_CMP_FIELD(a, b, tx_bytes); + NM_CMP_FIELD(a, b, allowed_ips_len); + NM_CMP_FIELD(a, b, persistent_keepalive_interval); + NM_CMP_FIELD(a, b, endpoint.sa.sa_family); + NM_CMP_FIELD_MEMCMP(a, b, public_key); + NM_CMP_FIELD_MEMCMP(a, b, preshared_key); - NM_CMP_RETURN (nm_sock_addr_union_cmp (&a->endpoint, &b->endpoint)); + NM_CMP_RETURN(nm_sock_addr_union_cmp(&a->endpoint, &b->endpoint)); - for (i = 0; i < a->allowed_ips_len; i++) { - NM_CMP_RETURN (_wireguard_allowed_ip_cmp (&a->allowed_ips[i], - &b->allowed_ips[i])); - } + for (i = 0; i < a->allowed_ips_len; i++) { + NM_CMP_RETURN(_wireguard_allowed_ip_cmp(&a->allowed_ips[i], &b->allowed_ips[i])); + } - return 0; + return 0; } /*****************************************************************************/ static const char * -_link_get_driver (struct udev_device *udevice, const char *kind, int ifindex) +_link_get_driver(struct udev_device *udevice, const char *kind, int ifindex) { - const char *driver = NULL; + const char *driver = NULL; - nm_assert (kind == g_intern_string (kind)); + nm_assert(kind == g_intern_string(kind)); - if (udevice) { - driver = nmp_utils_udev_get_driver (udevice); - if (driver) - return driver; - } + if (udevice) { + driver = nmp_utils_udev_get_driver(udevice); + if (driver) + return driver; + } - if (kind) - return kind; + if (kind) + return kind; - if (ifindex > 0) { - NMPUtilsEthtoolDriverInfo driver_info; + if (ifindex > 0) { + NMPUtilsEthtoolDriverInfo driver_info; - if (nmp_utils_ethtool_get_driver_info (ifindex, &driver_info)) { - if (driver_info.driver[0]) - return g_intern_string (driver_info.driver); - } - } + if (nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) { + if (driver_info.driver[0]) + return g_intern_string(driver_info.driver); + } + } - return "unknown"; + return "unknown"; } void -_nmp_object_fixup_link_udev_fields (NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev) -{ - const char *driver = NULL; - gboolean initialized = FALSE; - NMPObject *obj; - - nm_assert (obj_orig || *obj_new); - nm_assert (obj_new); - nm_assert (!obj_orig || NMP_OBJECT_GET_TYPE (obj_orig) == NMP_OBJECT_TYPE_LINK); - nm_assert (!*obj_new || NMP_OBJECT_GET_TYPE (*obj_new) == NMP_OBJECT_TYPE_LINK); - - obj = *obj_new ?: obj_orig; - - /* The link contains internal fields that are combined by - * properties from netlink and udev. Update those properties */ - - /* When a link is not in netlink, its udev fields don't matter. */ - if (obj->_link.netlink.is_in_netlink) { - driver = _link_get_driver (obj->_link.udev.device, - obj->link.kind, - obj->link.ifindex); - if (obj->_link.udev.device) - initialized = TRUE; - else if (!use_udev) { - /* If we don't use udev, we immediately mark the link as initialized. - * - * For that, we consult @use_udev argument, that is cached via - * nmp_cache_use_udev_get(). It is on purpose not to test - * for a writable /sys on every call. A minor reason for that is - * performance, but the real reason is reproducibility. - * */ - initialized = TRUE; - } - } - - if ( nm_streq0 (obj->link.driver, driver) - && obj->link.initialized == initialized) - return; - - if (!*obj_new) - obj = *obj_new = nmp_object_clone (obj, FALSE); - - obj->link.driver = driver; - obj->link.initialized = initialized; +_nmp_object_fixup_link_udev_fields(NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev) +{ + const char *driver = NULL; + gboolean initialized = FALSE; + NMPObject * obj; + + nm_assert(obj_orig || *obj_new); + nm_assert(obj_new); + nm_assert(!obj_orig || NMP_OBJECT_GET_TYPE(obj_orig) == NMP_OBJECT_TYPE_LINK); + nm_assert(!*obj_new || NMP_OBJECT_GET_TYPE(*obj_new) == NMP_OBJECT_TYPE_LINK); + + obj = *obj_new ?: obj_orig; + + /* The link contains internal fields that are combined by + * properties from netlink and udev. Update those properties */ + + /* When a link is not in netlink, its udev fields don't matter. */ + if (obj->_link.netlink.is_in_netlink) { + driver = _link_get_driver(obj->_link.udev.device, obj->link.kind, obj->link.ifindex); + if (obj->_link.udev.device) + initialized = TRUE; + else if (!use_udev) { + /* If we don't use udev, we immediately mark the link as initialized. + * + * For that, we consult @use_udev argument, that is cached via + * nmp_cache_use_udev_get(). It is on purpose not to test + * for a writable /sys on every call. A minor reason for that is + * performance, but the real reason is reproducibility. + * */ + initialized = TRUE; + } + } + + if (nm_streq0(obj->link.driver, driver) && obj->link.initialized == initialized) + return; + + if (!*obj_new) + obj = *obj_new = nmp_object_clone(obj, FALSE); + + obj->link.driver = driver; + obj->link.initialized = initialized; } static void -_nmp_object_fixup_link_master_connected (NMPObject **obj_new, NMPObject *obj_orig, const NMPCache *cache) +_nmp_object_fixup_link_master_connected(NMPObject ** obj_new, + NMPObject * obj_orig, + const NMPCache *cache) { - NMPObject *obj; + NMPObject *obj; - nm_assert (obj_orig || *obj_new); - nm_assert (obj_new); - nm_assert (!obj_orig || NMP_OBJECT_GET_TYPE (obj_orig) == NMP_OBJECT_TYPE_LINK); - nm_assert (!*obj_new || NMP_OBJECT_GET_TYPE (*obj_new) == NMP_OBJECT_TYPE_LINK); + nm_assert(obj_orig || *obj_new); + nm_assert(obj_new); + nm_assert(!obj_orig || NMP_OBJECT_GET_TYPE(obj_orig) == NMP_OBJECT_TYPE_LINK); + nm_assert(!*obj_new || NMP_OBJECT_GET_TYPE(*obj_new) == NMP_OBJECT_TYPE_LINK); - obj = *obj_new ?: obj_orig; + obj = *obj_new ?: obj_orig; - if (nmp_cache_link_connected_needs_toggle (cache, obj, NULL, NULL)) { - if (!*obj_new) - obj = *obj_new = nmp_object_clone (obj, FALSE); - obj->link.connected = !obj->link.connected; - } + if (nmp_cache_link_connected_needs_toggle(cache, obj, NULL, NULL)) { + if (!*obj_new) + obj = *obj_new = nmp_object_clone(obj, FALSE); + obj->link.connected = !obj->link.connected; + } } /*****************************************************************************/ static void -_vt_cmd_obj_dispose_link (NMPObject *obj) +_vt_cmd_obj_dispose_link(NMPObject *obj) { - if (obj->_link.udev.device) { - udev_device_unref (obj->_link.udev.device); - obj->_link.udev.device = NULL; - } - g_clear_object (&obj->_link.ext_data); - nmp_object_unref (obj->_link.netlink.lnk); + if (obj->_link.udev.device) { + udev_device_unref(obj->_link.udev.device); + obj->_link.udev.device = NULL; + } + g_clear_object(&obj->_link.ext_data); + nmp_object_unref(obj->_link.netlink.lnk); } static void -_vt_cmd_obj_dispose_lnk_vlan (NMPObject *obj) +_vt_cmd_obj_dispose_lnk_vlan(NMPObject *obj) { - g_free ((gpointer) obj->_lnk_vlan.ingress_qos_map); - g_free ((gpointer) obj->_lnk_vlan.egress_qos_map); + g_free((gpointer) obj->_lnk_vlan.ingress_qos_map); + g_free((gpointer) obj->_lnk_vlan.egress_qos_map); } static void -_wireguard_clear (NMPObjectLnkWireGuard *lnk) +_wireguard_clear(NMPObjectLnkWireGuard *lnk) { - guint i; + guint i; - nm_explicit_bzero (lnk->_public.private_key, - sizeof (lnk->_public.private_key)); - for (i = 0; i < lnk->peers_len; i++) { - NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &lnk->peers[i]; + nm_explicit_bzero(lnk->_public.private_key, sizeof(lnk->_public.private_key)); + for (i = 0; i < lnk->peers_len; i++) { + NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &lnk->peers[i]; - nm_explicit_bzero (peer->preshared_key, sizeof (peer->preshared_key)); - } - g_free ((gpointer) lnk->peers); - g_free ((gpointer) lnk->_allowed_ips_buf); + nm_explicit_bzero(peer->preshared_key, sizeof(peer->preshared_key)); + } + g_free((gpointer) lnk->peers); + g_free((gpointer) lnk->_allowed_ips_buf); } static void -_vt_cmd_obj_dispose_lnk_wireguard (NMPObject *obj) +_vt_cmd_obj_dispose_lnk_wireguard(NMPObject *obj) { - _wireguard_clear (&obj->_lnk_wireguard); + _wireguard_clear(&obj->_lnk_wireguard); } static NMPObject * -_nmp_object_new_from_class (const NMPClass *klass) +_nmp_object_new_from_class(const NMPClass *klass) { - NMPObject *obj; + NMPObject *obj; - nm_assert (klass); - nm_assert (klass->sizeof_data > 0); - nm_assert (klass->sizeof_public > 0 && klass->sizeof_public <= klass->sizeof_data); + nm_assert(klass); + nm_assert(klass->sizeof_data > 0); + nm_assert(klass->sizeof_public > 0 && klass->sizeof_public <= klass->sizeof_data); - obj = g_slice_alloc0 (klass->sizeof_data + G_STRUCT_OFFSET (NMPObject, object)); - obj->_class = klass; - obj->parent._ref_count = 1; - return obj; + obj = g_slice_alloc0(klass->sizeof_data + G_STRUCT_OFFSET(NMPObject, object)); + obj->_class = klass; + obj->parent._ref_count = 1; + return obj; } NMPObject * -nmp_object_new (NMPObjectType obj_type, gconstpointer plobj) +nmp_object_new(NMPObjectType obj_type, gconstpointer plobj) { - const NMPClass *klass = nmp_class_from_type (obj_type); - NMPObject *obj; + const NMPClass *klass = nmp_class_from_type(obj_type); + NMPObject * obj; - obj = _nmp_object_new_from_class (klass); - if (plobj) - memcpy (&obj->object, plobj, klass->sizeof_public); - return obj; + obj = _nmp_object_new_from_class(klass); + if (plobj) + memcpy(&obj->object, plobj, klass->sizeof_public); + return obj; } NMPObject * -nmp_object_new_link (int ifindex) +nmp_object_new_link(int ifindex) { - NMPObject *obj; + NMPObject *obj; - obj = nmp_object_new (NMP_OBJECT_TYPE_LINK, NULL); - obj->link.ifindex = ifindex; - return obj; + obj = nmp_object_new(NMP_OBJECT_TYPE_LINK, NULL); + obj->link.ifindex = ifindex; + return obj; } /*****************************************************************************/ static void -_nmp_object_stackinit_from_class (NMPObject *obj, const NMPClass *klass) +_nmp_object_stackinit_from_class(NMPObject *obj, const NMPClass *klass) { - nm_assert (obj); - nm_assert (klass); + nm_assert(obj); + nm_assert(klass); - *obj = (NMPObject) { - .parent = { - .klass = (const NMDedupMultiObjClass *) klass, - ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, - }, - }; + *obj = (NMPObject){ + .parent = + { + .klass = (const NMDedupMultiObjClass *) klass, + ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, + }, + }; } static NMPObject * -_nmp_object_stackinit_from_type (NMPObject *obj, NMPObjectType obj_type) +_nmp_object_stackinit_from_type(NMPObject *obj, NMPObjectType obj_type) { - const NMPClass *klass; + const NMPClass *klass; - nm_assert (obj); - klass = nmp_class_from_type (obj_type); - nm_assert (klass); + nm_assert(obj); + klass = nmp_class_from_type(obj_type); + nm_assert(klass); - *obj = (NMPObject) { - .parent = { - .klass = (const NMDedupMultiObjClass *) klass, - ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, - }, - }; - return obj; + *obj = (NMPObject){ + .parent = + { + .klass = (const NMDedupMultiObjClass *) klass, + ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, + }, + }; + return obj; } const NMPObject * -nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj) +nmp_object_stackinit(NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj) { - const NMPClass *klass = nmp_class_from_type (obj_type); + const NMPClass *klass = nmp_class_from_type(obj_type); - _nmp_object_stackinit_from_class (obj, klass); - if (plobj) - memcpy (&obj->object, plobj, klass->sizeof_public); - return obj; + _nmp_object_stackinit_from_class(obj, klass); + if (plobj) + memcpy(&obj->object, plobj, klass->sizeof_public); + return obj; } const NMPObject * -nmp_object_stackinit_id (NMPObject *obj, const NMPObject *src) +nmp_object_stackinit_id(NMPObject *obj, const NMPObject *src) { - const NMPClass *klass; + const NMPClass *klass; - nm_assert (NMP_OBJECT_IS_VALID (src)); - nm_assert (obj); + nm_assert(NMP_OBJECT_IS_VALID(src)); + nm_assert(obj); - klass = NMP_OBJECT_GET_CLASS (src); - _nmp_object_stackinit_from_class (obj, klass); - if (klass->cmd_plobj_id_copy) - klass->cmd_plobj_id_copy (&obj->object, &src->object); - return obj; + klass = NMP_OBJECT_GET_CLASS(src); + _nmp_object_stackinit_from_class(obj, klass); + if (klass->cmd_plobj_id_copy) + klass->cmd_plobj_id_copy(&obj->object, &src->object); + return obj; } const NMPObject * -nmp_object_stackinit_id_link (NMPObject *obj, int ifindex) +nmp_object_stackinit_id_link(NMPObject *obj, int ifindex) { - _nmp_object_stackinit_from_type (obj, NMP_OBJECT_TYPE_LINK); - obj->link.ifindex = ifindex; - return obj; + _nmp_object_stackinit_from_type(obj, NMP_OBJECT_TYPE_LINK); + obj->link.ifindex = ifindex; + return obj; } const NMPObject * -nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address) +nmp_object_stackinit_id_ip4_address(NMPObject *obj, + int ifindex, + guint32 address, + guint8 plen, + guint32 peer_address) { - _nmp_object_stackinit_from_type (obj, NMP_OBJECT_TYPE_IP4_ADDRESS); - obj->ip4_address.ifindex = ifindex; - obj->ip4_address.address = address; - obj->ip4_address.plen = plen; - obj->ip4_address.peer_address = peer_address; - return obj; + _nmp_object_stackinit_from_type(obj, NMP_OBJECT_TYPE_IP4_ADDRESS); + obj->ip4_address.ifindex = ifindex; + obj->ip4_address.address = address; + obj->ip4_address.plen = plen; + obj->ip4_address.peer_address = peer_address; + return obj; } const NMPObject * -nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address) +nmp_object_stackinit_id_ip6_address(NMPObject *obj, int ifindex, const struct in6_addr *address) { - _nmp_object_stackinit_from_type (obj, NMP_OBJECT_TYPE_IP6_ADDRESS); - obj->ip4_address.ifindex = ifindex; - if (address) - obj->ip6_address.address = *address; - return obj; + _nmp_object_stackinit_from_type(obj, NMP_OBJECT_TYPE_IP6_ADDRESS); + obj->ip4_address.ifindex = ifindex; + if (address) + obj->ip6_address.address = *address; + return obj; } /*****************************************************************************/ const char * -nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size) -{ - const NMPClass *klass; - char buf2[sizeof (_nm_utils_to_string_buffer)]; - - if (!nm_utils_to_string_buffer_init_null (obj, &buf, &buf_size)) - return buf; - - g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj), NULL); - - klass = NMP_OBJECT_GET_CLASS (obj); - - if (klass->cmd_obj_to_string) - return klass->cmd_obj_to_string (obj, to_string_mode, buf, buf_size); - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - if (!klass->cmd_plobj_to_string_id) { - g_snprintf (buf, buf_size, "%p", obj); - return buf; - } - return klass->cmd_plobj_to_string_id (&obj->object, buf, buf_size); - case NMP_OBJECT_TO_STRING_ALL: - g_snprintf (buf, buf_size, - "[%s,%p,%u,%calive,%cvisible; %s]", - klass->obj_type_name, obj, obj->parent._ref_count, - nmp_object_is_alive (obj) ? '+' : '-', - nmp_object_is_visible (obj) ? '+' : '-', - NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf2, sizeof (buf2))); - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf, buf_size); - return buf; - default: - g_return_val_if_reached ("ERROR"); - } +nmp_object_to_string(const NMPObject * obj, + NMPObjectToStringMode to_string_mode, + char * buf, + gsize buf_size) +{ + const NMPClass *klass; + char buf2[sizeof(_nm_utils_to_string_buffer)]; + + if (!nm_utils_to_string_buffer_init_null(obj, &buf, &buf_size)) + return buf; + + g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj), NULL); + + klass = NMP_OBJECT_GET_CLASS(obj); + + if (klass->cmd_obj_to_string) + return klass->cmd_obj_to_string(obj, to_string_mode, buf, buf_size); + + switch (to_string_mode) { + case NMP_OBJECT_TO_STRING_ID: + if (!klass->cmd_plobj_to_string_id) { + g_snprintf(buf, buf_size, "%p", obj); + return buf; + } + return klass->cmd_plobj_to_string_id(&obj->object, buf, buf_size); + case NMP_OBJECT_TO_STRING_ALL: + g_snprintf( + buf, + buf_size, + "[%s,%p,%u,%calive,%cvisible; %s]", + klass->obj_type_name, + obj, + obj->parent._ref_count, + nmp_object_is_alive(obj) ? '+' : '-', + nmp_object_is_visible(obj) ? '+' : '-', + NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf2, sizeof(buf2))); + return buf; + case NMP_OBJECT_TO_STRING_PUBLIC: + NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf, buf_size); + return buf; + default: + g_return_val_if_reached("ERROR"); + } } static const char * -_vt_cmd_obj_to_string_link (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size) -{ - const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj); - char *b = buf; - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - return klass->cmd_plobj_to_string_id (&obj->object, buf, buf_size); - case NMP_OBJECT_TO_STRING_ALL: - nm_utils_strbuf_append (&b, &buf_size, - "[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; ", - klass->obj_type_name, obj, obj->parent._ref_count, - nmp_object_is_alive (obj) ? '+' : '-', - nmp_object_is_visible (obj) ? '+' : '-', - obj->_link.netlink.is_in_netlink ? '+' : '-', - obj->_link.udev.device); - NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, b, buf_size); - nm_utils_strbuf_seek_end (&b, &buf_size); - if (obj->_link.netlink.lnk) { - nm_utils_strbuf_append_str (&b, &buf_size, "; "); - nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_ALL, b, buf_size); - nm_utils_strbuf_seek_end (&b, &buf_size); - } - nm_utils_strbuf_append_c (&b, &buf_size, ']'); - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, b, buf_size); - if (obj->_link.netlink.lnk) { - nm_utils_strbuf_seek_end (&b, &buf_size); - nm_utils_strbuf_append_str (&b, &buf_size, "; "); - nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_PUBLIC, b, buf_size); - } - return buf; - default: - g_return_val_if_reached ("ERROR"); - } +_vt_cmd_obj_to_string_link(const NMPObject * obj, + NMPObjectToStringMode to_string_mode, + char * buf, + gsize buf_size) +{ + const NMPClass *klass = NMP_OBJECT_GET_CLASS(obj); + char * b = buf; + + switch (to_string_mode) { + case NMP_OBJECT_TO_STRING_ID: + return klass->cmd_plobj_to_string_id(&obj->object, buf, buf_size); + case NMP_OBJECT_TO_STRING_ALL: + nm_utils_strbuf_append(&b, + &buf_size, + "[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; ", + klass->obj_type_name, + obj, + obj->parent._ref_count, + nmp_object_is_alive(obj) ? '+' : '-', + nmp_object_is_visible(obj) ? '+' : '-', + obj->_link.netlink.is_in_netlink ? '+' : '-', + obj->_link.udev.device); + NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, b, buf_size); + nm_utils_strbuf_seek_end(&b, &buf_size); + if (obj->_link.netlink.lnk) { + nm_utils_strbuf_append_str(&b, &buf_size, "; "); + nmp_object_to_string(obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_ALL, b, buf_size); + nm_utils_strbuf_seek_end(&b, &buf_size); + } + nm_utils_strbuf_append_c(&b, &buf_size, ']'); + return buf; + case NMP_OBJECT_TO_STRING_PUBLIC: + NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, b, buf_size); + if (obj->_link.netlink.lnk) { + nm_utils_strbuf_seek_end(&b, &buf_size); + nm_utils_strbuf_append_str(&b, &buf_size, "; "); + nmp_object_to_string(obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_PUBLIC, b, buf_size); + } + return buf; + default: + g_return_val_if_reached("ERROR"); + } } static const char * -_vt_cmd_obj_to_string_lnk_vlan (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size) -{ - const NMPClass *klass; - char buf2[sizeof (_nm_utils_to_string_buffer)]; - char *b; - gsize l; - - klass = NMP_OBJECT_GET_CLASS (obj); - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - g_snprintf (buf, buf_size, "%p", obj); - return buf; - case NMP_OBJECT_TO_STRING_ALL: - - g_snprintf (buf, buf_size, - "[%s,%p,%u,%calive,%cvisible; %s]", - klass->obj_type_name, obj, obj->parent._ref_count, - nmp_object_is_alive (obj) ? '+' : '-', - nmp_object_is_visible (obj) ? '+' : '-', - nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2))); - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf, buf_size); - - b = buf; - l = strlen (b); - b += l; - buf_size -= l; - - if (obj->_lnk_vlan.n_ingress_qos_map) { - nm_platform_vlan_qos_mapping_to_string (" ingress-qos-map", - obj->_lnk_vlan.ingress_qos_map, - obj->_lnk_vlan.n_ingress_qos_map, - b, - buf_size); - l = strlen (b); - b += l; - buf_size -= l; - } - if (obj->_lnk_vlan.n_egress_qos_map) { - nm_platform_vlan_qos_mapping_to_string (" egress-qos-map", - obj->_lnk_vlan.egress_qos_map, - obj->_lnk_vlan.n_egress_qos_map, - b, - buf_size); - l = strlen (b); - b += l; - buf_size -= l; - } - - return buf; - default: - g_return_val_if_reached ("ERROR"); - } +_vt_cmd_obj_to_string_lnk_vlan(const NMPObject * obj, + NMPObjectToStringMode to_string_mode, + char * buf, + gsize buf_size) +{ + const NMPClass *klass; + char buf2[sizeof(_nm_utils_to_string_buffer)]; + char * b; + gsize l; + + klass = NMP_OBJECT_GET_CLASS(obj); + + switch (to_string_mode) { + case NMP_OBJECT_TO_STRING_ID: + g_snprintf(buf, buf_size, "%p", obj); + return buf; + case NMP_OBJECT_TO_STRING_ALL: + + g_snprintf(buf, + buf_size, + "[%s,%p,%u,%calive,%cvisible; %s]", + klass->obj_type_name, + obj, + obj->parent._ref_count, + nmp_object_is_alive(obj) ? '+' : '-', + nmp_object_is_visible(obj) ? '+' : '-', + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof(buf2))); + return buf; + case NMP_OBJECT_TO_STRING_PUBLIC: + NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf, buf_size); + + b = buf; + l = strlen(b); + b += l; + buf_size -= l; + + if (obj->_lnk_vlan.n_ingress_qos_map) { + nm_platform_vlan_qos_mapping_to_string(" ingress-qos-map", + obj->_lnk_vlan.ingress_qos_map, + obj->_lnk_vlan.n_ingress_qos_map, + b, + buf_size); + l = strlen(b); + b += l; + buf_size -= l; + } + if (obj->_lnk_vlan.n_egress_qos_map) { + nm_platform_vlan_qos_mapping_to_string(" egress-qos-map", + obj->_lnk_vlan.egress_qos_map, + obj->_lnk_vlan.n_egress_qos_map, + b, + buf_size); + l = strlen(b); + b += l; + buf_size -= l; + } + + return buf; + default: + g_return_val_if_reached("ERROR"); + } } static const char * -_vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size) -{ - const NMPClass *klass; - char buf2[sizeof (_nm_utils_to_string_buffer)]; - char *b; - guint i; - - klass = NMP_OBJECT_GET_CLASS (obj); - - switch (to_string_mode) { - case NMP_OBJECT_TO_STRING_ID: - g_snprintf (buf, buf_size, "%p", obj); - return buf; - case NMP_OBJECT_TO_STRING_ALL: - b = buf; - - nm_utils_strbuf_append (&b, &buf_size, - "[%s,%p,%u,%calive,%cvisible; %s" - "%s", - klass->obj_type_name, obj, obj->parent._ref_count, - nmp_object_is_alive (obj) ? '+' : '-', - nmp_object_is_visible (obj) ? '+' : '-', - nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)), - obj->_lnk_wireguard.peers_len > 0 - ? " peers {" - : ""); - - for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) { - const NMPWireGuardPeer *peer = &obj->_lnk_wireguard.peers[i]; - - nm_utils_strbuf_append_str (&b, &buf_size, " { "); - nm_platform_wireguard_peer_to_string (peer, b, buf_size); - nm_utils_strbuf_seek_end (&b, &buf_size); - nm_utils_strbuf_append_str (&b, &buf_size, " }"); - } - if (obj->_lnk_wireguard.peers_len) - nm_utils_strbuf_append_str (&b, &buf_size, " }"); - - return buf; - case NMP_OBJECT_TO_STRING_PUBLIC: - NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf, buf_size); - - return buf; - default: - g_return_val_if_reached ("ERROR"); - } -} - -#define _vt_cmd_plobj_to_string_id(type, plat_type, ...) \ -static const char * \ -_vt_cmd_plobj_to_string_id_##type (const NMPlatformObject *_obj, char *buf, gsize buf_len) \ -{ \ - plat_type *const obj = (plat_type *) _obj; \ - _nm_unused char buf1[NM_UTILS_INET_ADDRSTRLEN]; \ - _nm_unused char buf2[NM_UTILS_INET_ADDRSTRLEN]; \ - \ - g_snprintf (buf, buf_len, \ - __VA_ARGS__); \ - return buf; \ -} -_vt_cmd_plobj_to_string_id (link, NMPlatformLink, "%d", obj->ifindex); -_vt_cmd_plobj_to_string_id (ip4_address, NMPlatformIP4Address, "%d: %s/%d%s%s", obj->ifindex, _nm_utils_inet4_ntop ( obj->address, buf1), obj->plen, - obj->peer_address != obj->address ? "," : "", - obj->peer_address != obj->address ? _nm_utils_inet4_ntop (nm_utils_ip4_address_clear_host_address (obj->peer_address, obj->plen), buf2) : ""); -_vt_cmd_plobj_to_string_id (ip6_address, NMPlatformIP6Address, "%d: %s", obj->ifindex, _nm_utils_inet6_ntop (&obj->address, buf1)); -_vt_cmd_plobj_to_string_id (qdisc, NMPlatformQdisc, "%d: %d", obj->ifindex, obj->parent); -_vt_cmd_plobj_to_string_id (tfilter, NMPlatformTfilter, "%d: %d", obj->ifindex, obj->parent); +_vt_cmd_obj_to_string_lnk_wireguard(const NMPObject * obj, + NMPObjectToStringMode to_string_mode, + char * buf, + gsize buf_size) +{ + const NMPClass *klass; + char buf2[sizeof(_nm_utils_to_string_buffer)]; + char * b; + guint i; + + klass = NMP_OBJECT_GET_CLASS(obj); + + switch (to_string_mode) { + case NMP_OBJECT_TO_STRING_ID: + g_snprintf(buf, buf_size, "%p", obj); + return buf; + case NMP_OBJECT_TO_STRING_ALL: + b = buf; + + nm_utils_strbuf_append( + &b, + &buf_size, + "[%s,%p,%u,%calive,%cvisible; %s" + "%s", + klass->obj_type_name, + obj, + obj->parent._ref_count, + nmp_object_is_alive(obj) ? '+' : '-', + nmp_object_is_visible(obj) ? '+' : '-', + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof(buf2)), + obj->_lnk_wireguard.peers_len > 0 ? " peers {" : ""); + + for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) { + const NMPWireGuardPeer *peer = &obj->_lnk_wireguard.peers[i]; + + nm_utils_strbuf_append_str(&b, &buf_size, " { "); + nm_platform_wireguard_peer_to_string(peer, b, buf_size); + nm_utils_strbuf_seek_end(&b, &buf_size); + nm_utils_strbuf_append_str(&b, &buf_size, " }"); + } + if (obj->_lnk_wireguard.peers_len) + nm_utils_strbuf_append_str(&b, &buf_size, " }"); + + return buf; + case NMP_OBJECT_TO_STRING_PUBLIC: + NMP_OBJECT_GET_CLASS(obj)->cmd_plobj_to_string(&obj->object, buf, buf_size); + + return buf; + default: + g_return_val_if_reached("ERROR"); + } +} + +#define _vt_cmd_plobj_to_string_id(type, plat_type, ...) \ + static const char *_vt_cmd_plobj_to_string_id_##type(const NMPlatformObject *_obj, \ + char * buf, \ + gsize buf_len) \ + { \ + plat_type *const obj = (plat_type *) _obj; \ + _nm_unused char buf1[NM_UTILS_INET_ADDRSTRLEN]; \ + _nm_unused char buf2[NM_UTILS_INET_ADDRSTRLEN]; \ + \ + g_snprintf(buf, buf_len, __VA_ARGS__); \ + return buf; \ + } \ + struct _dummy_struct_for_tailing_semicolon + +_vt_cmd_plobj_to_string_id(link, NMPlatformLink, "%d", obj->ifindex); + +_vt_cmd_plobj_to_string_id(ip4_address, + NMPlatformIP4Address, + "%d: %s/%d%s%s", + obj->ifindex, + _nm_utils_inet4_ntop(obj->address, buf1), + obj->plen, + obj->peer_address != obj->address ? "," : "", + obj->peer_address != obj->address ? _nm_utils_inet4_ntop( + nm_utils_ip4_address_clear_host_address(obj->peer_address, + obj->plen), + buf2) + : ""); + +_vt_cmd_plobj_to_string_id(ip6_address, + NMPlatformIP6Address, + "%d: %s", + obj->ifindex, + _nm_utils_inet6_ntop(&obj->address, buf1)); + +_vt_cmd_plobj_to_string_id(qdisc, NMPlatformQdisc, "%d: %d", obj->ifindex, obj->parent); + +_vt_cmd_plobj_to_string_id(tfilter, NMPlatformTfilter, "%d: %d", obj->ifindex, obj->parent); void -nmp_object_hash_update (const NMPObject *obj, NMHashState *h) +nmp_object_hash_update(const NMPObject *obj, NMHashState *h) { - const NMPClass *klass; + const NMPClass *klass; - g_return_if_fail (NMP_OBJECT_IS_VALID (obj)); + g_return_if_fail(NMP_OBJECT_IS_VALID(obj)); - klass = NMP_OBJECT_GET_CLASS (obj); + klass = NMP_OBJECT_GET_CLASS(obj); - nm_hash_update_val (h, klass->obj_type); - if (klass->cmd_obj_hash_update) - klass->cmd_obj_hash_update (obj, h); - else if (klass->cmd_plobj_hash_update) - klass->cmd_plobj_hash_update (&obj->object, h); - else - nm_hash_update_val (h, obj); + nm_hash_update_val(h, klass->obj_type); + if (klass->cmd_obj_hash_update) + klass->cmd_obj_hash_update(obj, h); + else if (klass->cmd_plobj_hash_update) + klass->cmd_plobj_hash_update(&obj->object, h); + else + nm_hash_update_val(h, obj); } static void -_vt_cmd_obj_hash_update_link (const NMPObject *obj, NMHashState *h) +_vt_cmd_obj_hash_update_link(const NMPObject *obj, NMHashState *h) { - nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LINK); + nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LINK); - nm_platform_link_hash_update (&obj->link, h); - nm_hash_update_vals (h, - obj->_link.netlink.is_in_netlink, - obj->_link.wireguard_family_id, - obj->_link.udev.device); - if (obj->_link.netlink.lnk) - nmp_object_hash_update (obj->_link.netlink.lnk, h); + nm_platform_link_hash_update(&obj->link, h); + nm_hash_update_vals(h, + obj->_link.netlink.is_in_netlink, + obj->_link.wireguard_family_id, + obj->_link.udev.device); + if (obj->_link.netlink.lnk) + nmp_object_hash_update(obj->_link.netlink.lnk, h); } static void -_vt_cmd_obj_hash_update_lnk_vlan (const NMPObject *obj, NMHashState *h) +_vt_cmd_obj_hash_update_lnk_vlan(const NMPObject *obj, NMHashState *h) { - nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LNK_VLAN); + nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LNK_VLAN); - nm_platform_lnk_vlan_hash_update (&obj->lnk_vlan, h); - _vlan_xgress_qos_mappings_hash_update (obj->_lnk_vlan.n_ingress_qos_map, - obj->_lnk_vlan.ingress_qos_map, - h); - _vlan_xgress_qos_mappings_hash_update (obj->_lnk_vlan.n_egress_qos_map, - obj->_lnk_vlan.egress_qos_map, - h); + nm_platform_lnk_vlan_hash_update(&obj->lnk_vlan, h); + _vlan_xgress_qos_mappings_hash_update(obj->_lnk_vlan.n_ingress_qos_map, + obj->_lnk_vlan.ingress_qos_map, + h); + _vlan_xgress_qos_mappings_hash_update(obj->_lnk_vlan.n_egress_qos_map, + obj->_lnk_vlan.egress_qos_map, + h); } static void -_vt_cmd_obj_hash_update_lnk_wireguard (const NMPObject *obj, NMHashState *h) +_vt_cmd_obj_hash_update_lnk_wireguard(const NMPObject *obj, NMHashState *h) { - guint i; + guint i; - nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD); + nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD); - nm_platform_lnk_wireguard_hash_update (&obj->lnk_wireguard, h); + nm_platform_lnk_wireguard_hash_update(&obj->lnk_wireguard, h); - nm_hash_update_val (h, obj->_lnk_wireguard.peers_len); - for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) - _wireguard_peer_hash_update (&obj->_lnk_wireguard.peers[i], h); + nm_hash_update_val(h, obj->_lnk_wireguard.peers_len); + for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) + _wireguard_peer_hash_update(&obj->_lnk_wireguard.peers[i], h); } int -nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2) +nmp_object_cmp(const NMPObject *obj1, const NMPObject *obj2) { - const NMPClass *klass1, *klass2; + const NMPClass *klass1, *klass2; - NM_CMP_SELF (obj1, obj2); + NM_CMP_SELF(obj1, obj2); - g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj1), -1); - g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj2), 1); + g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj1), -1); + g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj2), 1); - klass1 = NMP_OBJECT_GET_CLASS (obj1); - klass2 = NMP_OBJECT_GET_CLASS (obj2); + klass1 = NMP_OBJECT_GET_CLASS(obj1); + klass2 = NMP_OBJECT_GET_CLASS(obj2); - if (klass1 != klass2) { - nm_assert (klass1->obj_type != klass2->obj_type); - return klass1->obj_type < klass2->obj_type ? -1 : 1; - } + if (klass1 != klass2) { + nm_assert(klass1->obj_type != klass2->obj_type); + return klass1->obj_type < klass2->obj_type ? -1 : 1; + } - if (klass1->cmd_obj_cmp) - return klass1->cmd_obj_cmp (obj1, obj2); - return klass1->cmd_plobj_cmp (&obj1->object, &obj2->object); + if (klass1->cmd_obj_cmp) + return klass1->cmd_obj_cmp(obj1, obj2); + return klass1->cmd_plobj_cmp(&obj1->object, &obj2->object); } static int -_vt_cmd_obj_cmp_link (const NMPObject *obj1, const NMPObject *obj2) +_vt_cmd_obj_cmp_link(const NMPObject *obj1, const NMPObject *obj2) { - NM_CMP_RETURN (nm_platform_link_cmp (&obj1->link, &obj2->link)); - NM_CMP_DIRECT (obj1->_link.netlink.is_in_netlink, obj2->_link.netlink.is_in_netlink); - NM_CMP_RETURN (nmp_object_cmp (obj1->_link.netlink.lnk, obj2->_link.netlink.lnk)); - NM_CMP_DIRECT (obj1->_link.wireguard_family_id, obj2->_link.wireguard_family_id); + NM_CMP_RETURN(nm_platform_link_cmp(&obj1->link, &obj2->link)); + NM_CMP_DIRECT(obj1->_link.netlink.is_in_netlink, obj2->_link.netlink.is_in_netlink); + NM_CMP_RETURN(nmp_object_cmp(obj1->_link.netlink.lnk, obj2->_link.netlink.lnk)); + NM_CMP_DIRECT(obj1->_link.wireguard_family_id, obj2->_link.wireguard_family_id); - if (obj1->_link.udev.device != obj2->_link.udev.device) { - if (!obj1->_link.udev.device) - return -1; - if (!obj2->_link.udev.device) - return 1; + if (obj1->_link.udev.device != obj2->_link.udev.device) { + if (!obj1->_link.udev.device) + return -1; + if (!obj2->_link.udev.device) + return 1; - /* Only compare based on pointer values. That is ugly because it's not a - * stable sort order. - * - * Have this check as very last. */ - return (obj1->_link.udev.device < obj2->_link.udev.device) ? -1 : 1; - } + /* Only compare based on pointer values. That is ugly because it's not a + * stable sort order. + * + * Have this check as very last. */ + return (obj1->_link.udev.device < obj2->_link.udev.device) ? -1 : 1; + } - return 0; + return 0; } static int -_vt_cmd_obj_cmp_lnk_vlan (const NMPObject *obj1, const NMPObject *obj2) +_vt_cmd_obj_cmp_lnk_vlan(const NMPObject *obj1, const NMPObject *obj2) { - int c; + int c; - c = nm_platform_lnk_vlan_cmp (&obj1->lnk_vlan, &obj2->lnk_vlan); - if (c) - return c; + c = nm_platform_lnk_vlan_cmp(&obj1->lnk_vlan, &obj2->lnk_vlan); + if (c) + return c; - if (obj1->_lnk_vlan.n_ingress_qos_map != obj2->_lnk_vlan.n_ingress_qos_map) - return obj1->_lnk_vlan.n_ingress_qos_map < obj2->_lnk_vlan.n_ingress_qos_map ? -1 : 1; - if (obj1->_lnk_vlan.n_egress_qos_map != obj2->_lnk_vlan.n_egress_qos_map) - return obj1->_lnk_vlan.n_egress_qos_map < obj2->_lnk_vlan.n_egress_qos_map ? -1 : 1; + if (obj1->_lnk_vlan.n_ingress_qos_map != obj2->_lnk_vlan.n_ingress_qos_map) + return obj1->_lnk_vlan.n_ingress_qos_map < obj2->_lnk_vlan.n_ingress_qos_map ? -1 : 1; + if (obj1->_lnk_vlan.n_egress_qos_map != obj2->_lnk_vlan.n_egress_qos_map) + return obj1->_lnk_vlan.n_egress_qos_map < obj2->_lnk_vlan.n_egress_qos_map ? -1 : 1; - c = _vlan_xgress_qos_mappings_cmp (obj1->_lnk_vlan.n_ingress_qos_map, obj1->_lnk_vlan.ingress_qos_map, obj2->_lnk_vlan.ingress_qos_map); - if (c) - return c; - c = _vlan_xgress_qos_mappings_cmp (obj1->_lnk_vlan.n_egress_qos_map, obj1->_lnk_vlan.egress_qos_map, obj2->_lnk_vlan.egress_qos_map); + c = _vlan_xgress_qos_mappings_cmp(obj1->_lnk_vlan.n_ingress_qos_map, + obj1->_lnk_vlan.ingress_qos_map, + obj2->_lnk_vlan.ingress_qos_map); + if (c) + return c; + c = _vlan_xgress_qos_mappings_cmp(obj1->_lnk_vlan.n_egress_qos_map, + obj1->_lnk_vlan.egress_qos_map, + obj2->_lnk_vlan.egress_qos_map); - return c; + return c; } static int -_vt_cmd_obj_cmp_lnk_wireguard (const NMPObject *obj1, const NMPObject *obj2) +_vt_cmd_obj_cmp_lnk_wireguard(const NMPObject *obj1, const NMPObject *obj2) { - guint i; + guint i; - NM_CMP_RETURN (nm_platform_lnk_wireguard_cmp (&obj1->lnk_wireguard, &obj2->lnk_wireguard)); + NM_CMP_RETURN(nm_platform_lnk_wireguard_cmp(&obj1->lnk_wireguard, &obj2->lnk_wireguard)); - NM_CMP_FIELD (obj1, obj2, _lnk_wireguard.peers_len); + NM_CMP_FIELD(obj1, obj2, _lnk_wireguard.peers_len); - for (i = 0; i < obj1->_lnk_wireguard.peers_len; i++) - NM_CMP_RETURN (_wireguard_peer_cmp (&obj1->_lnk_wireguard.peers[i], &obj2->_lnk_wireguard.peers[i])); + for (i = 0; i < obj1->_lnk_wireguard.peers_len; i++) + NM_CMP_RETURN( + _wireguard_peer_cmp(&obj1->_lnk_wireguard.peers[i], &obj2->_lnk_wireguard.peers[i])); - return 0; + return 0; } /* @src is a const object, which is not entirely correct for link types, where @@ -1238,530 +1279,580 @@ _vt_cmd_obj_cmp_lnk_wireguard (const NMPObject *obj1, const NMPObject *obj2) * Hence, nmp_object_copy() can violate the const promise of @src. * */ void -nmp_object_copy (NMPObject *dst, const NMPObject *src, gboolean id_only) +nmp_object_copy(NMPObject *dst, const NMPObject *src, gboolean id_only) { - g_return_if_fail (NMP_OBJECT_IS_VALID (dst)); - g_return_if_fail (NMP_OBJECT_IS_VALID (src)); - g_return_if_fail (!NMP_OBJECT_IS_STACKINIT (dst)); + g_return_if_fail(NMP_OBJECT_IS_VALID(dst)); + g_return_if_fail(NMP_OBJECT_IS_VALID(src)); + g_return_if_fail(!NMP_OBJECT_IS_STACKINIT(dst)); - if (src != dst) { - const NMPClass *klass = NMP_OBJECT_GET_CLASS (dst); + if (src != dst) { + const NMPClass *klass = NMP_OBJECT_GET_CLASS(dst); - g_return_if_fail (klass == NMP_OBJECT_GET_CLASS (src)); + g_return_if_fail(klass == NMP_OBJECT_GET_CLASS(src)); - if (id_only) { - if (klass->cmd_plobj_id_copy) - klass->cmd_plobj_id_copy (&dst->object, &src->object); - } else if (klass->cmd_obj_copy) - klass->cmd_obj_copy (dst, src); - else - memcpy (&dst->object, &src->object, klass->sizeof_data); - } + if (id_only) { + if (klass->cmd_plobj_id_copy) + klass->cmd_plobj_id_copy(&dst->object, &src->object); + } else if (klass->cmd_obj_copy) + klass->cmd_obj_copy(dst, src); + else + memcpy(&dst->object, &src->object, klass->sizeof_data); + } } static void -_vt_cmd_obj_copy_link (NMPObject *dst, const NMPObject *src) -{ - if (dst->_link.udev.device != src->_link.udev.device) { - if (src->_link.udev.device) - udev_device_ref (src->_link.udev.device); - if (dst->_link.udev.device) - udev_device_unref (dst->_link.udev.device); - dst->_link.udev.device = src->_link.udev.device; - } - if (dst->_link.netlink.lnk != src->_link.netlink.lnk) { - if (src->_link.netlink.lnk) - nmp_object_ref (src->_link.netlink.lnk); - if (dst->_link.netlink.lnk) - nmp_object_unref (dst->_link.netlink.lnk); - dst->_link.netlink.lnk = src->_link.netlink.lnk; - } - if (dst->_link.ext_data != src->_link.ext_data) { - if (dst->_link.ext_data) - g_clear_object (&dst->_link.ext_data); - if (src->_link.ext_data) - dst->_link.ext_data = g_object_ref (src->_link.ext_data); - } - dst->_link = src->_link; +_vt_cmd_obj_copy_link(NMPObject *dst, const NMPObject *src) +{ + if (dst->_link.udev.device != src->_link.udev.device) { + if (src->_link.udev.device) + udev_device_ref(src->_link.udev.device); + if (dst->_link.udev.device) + udev_device_unref(dst->_link.udev.device); + dst->_link.udev.device = src->_link.udev.device; + } + if (dst->_link.netlink.lnk != src->_link.netlink.lnk) { + if (src->_link.netlink.lnk) + nmp_object_ref(src->_link.netlink.lnk); + if (dst->_link.netlink.lnk) + nmp_object_unref(dst->_link.netlink.lnk); + dst->_link.netlink.lnk = src->_link.netlink.lnk; + } + if (dst->_link.ext_data != src->_link.ext_data) { + if (dst->_link.ext_data) + g_clear_object(&dst->_link.ext_data); + if (src->_link.ext_data) + dst->_link.ext_data = g_object_ref(src->_link.ext_data); + } + dst->_link = src->_link; } static void -_vt_cmd_obj_copy_lnk_vlan (NMPObject *dst, const NMPObject *src) +_vt_cmd_obj_copy_lnk_vlan(NMPObject *dst, const NMPObject *src) { - dst->lnk_vlan = src->lnk_vlan; - _vlan_xgress_qos_mappings_cpy (&dst->_lnk_vlan.n_ingress_qos_map, - NM_UNCONST_PPTR (NMVlanQosMapping, &dst->_lnk_vlan.ingress_qos_map), - src->_lnk_vlan.n_ingress_qos_map, - src->_lnk_vlan.ingress_qos_map); - _vlan_xgress_qos_mappings_cpy (&dst->_lnk_vlan.n_egress_qos_map, - NM_UNCONST_PPTR (NMVlanQosMapping, &dst->_lnk_vlan.egress_qos_map), - src->_lnk_vlan.n_egress_qos_map, - src->_lnk_vlan.egress_qos_map); + dst->lnk_vlan = src->lnk_vlan; + _vlan_xgress_qos_mappings_cpy( + &dst->_lnk_vlan.n_ingress_qos_map, + NM_UNCONST_PPTR(NMVlanQosMapping, &dst->_lnk_vlan.ingress_qos_map), + src->_lnk_vlan.n_ingress_qos_map, + src->_lnk_vlan.ingress_qos_map); + _vlan_xgress_qos_mappings_cpy(&dst->_lnk_vlan.n_egress_qos_map, + NM_UNCONST_PPTR(NMVlanQosMapping, &dst->_lnk_vlan.egress_qos_map), + src->_lnk_vlan.n_egress_qos_map, + src->_lnk_vlan.egress_qos_map); } static void -_vt_cmd_obj_copy_lnk_wireguard (NMPObject *dst, const NMPObject *src) -{ - guint i; - - nm_assert (dst != src); - - _wireguard_clear (&dst->_lnk_wireguard); - - dst->_lnk_wireguard = src->_lnk_wireguard; - - dst->_lnk_wireguard.peers = nm_memdup (dst->_lnk_wireguard.peers, - sizeof (NMPWireGuardPeer) * dst->_lnk_wireguard.peers_len); - dst->_lnk_wireguard._allowed_ips_buf = nm_memdup (dst->_lnk_wireguard._allowed_ips_buf, - sizeof (NMPWireGuardAllowedIP) * dst->_lnk_wireguard._allowed_ips_buf_len); - - /* all the peers' pointers point into the buffer. They need to be readjusted. */ - for (i = 0; i < dst->_lnk_wireguard.peers_len; i++) { - NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &dst->_lnk_wireguard.peers[i]; - - if (peer->allowed_ips_len == 0) { - nm_assert (!peer->allowed_ips); - continue; - } - nm_assert (dst->_lnk_wireguard._allowed_ips_buf_len > 0); - nm_assert (src->_lnk_wireguard._allowed_ips_buf); - nm_assert (peer->allowed_ips >= src->_lnk_wireguard._allowed_ips_buf); - nm_assert (&peer->allowed_ips[peer->allowed_ips_len] <= &src->_lnk_wireguard._allowed_ips_buf[src->_lnk_wireguard._allowed_ips_buf_len]); - - peer->allowed_ips = &dst->_lnk_wireguard._allowed_ips_buf[peer->allowed_ips - src->_lnk_wireguard._allowed_ips_buf]; - } - - nm_assert (nmp_object_equal (src, dst)); -} - -#define _vt_cmd_plobj_id_copy(type, plat_type, cmd) \ -static void \ -_vt_cmd_plobj_id_copy_##type (NMPlatformObject *_dst, const NMPlatformObject *_src) \ -{ \ - plat_type *const dst = (plat_type *) _dst; \ - const plat_type *const src = (const plat_type *) _src; \ - { cmd } \ -} -_vt_cmd_plobj_id_copy (link, NMPlatformLink, { - dst->ifindex = src->ifindex; +_vt_cmd_obj_copy_lnk_wireguard(NMPObject *dst, const NMPObject *src) +{ + guint i; + + nm_assert(dst != src); + + _wireguard_clear(&dst->_lnk_wireguard); + + dst->_lnk_wireguard = src->_lnk_wireguard; + + dst->_lnk_wireguard.peers = nm_memdup(dst->_lnk_wireguard.peers, + sizeof(NMPWireGuardPeer) * dst->_lnk_wireguard.peers_len); + dst->_lnk_wireguard._allowed_ips_buf = + nm_memdup(dst->_lnk_wireguard._allowed_ips_buf, + sizeof(NMPWireGuardAllowedIP) * dst->_lnk_wireguard._allowed_ips_buf_len); + + /* all the peers' pointers point into the buffer. They need to be readjusted. */ + for (i = 0; i < dst->_lnk_wireguard.peers_len; i++) { + NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &dst->_lnk_wireguard.peers[i]; + + if (peer->allowed_ips_len == 0) { + nm_assert(!peer->allowed_ips); + continue; + } + nm_assert(dst->_lnk_wireguard._allowed_ips_buf_len > 0); + nm_assert(src->_lnk_wireguard._allowed_ips_buf); + nm_assert(peer->allowed_ips >= src->_lnk_wireguard._allowed_ips_buf); + nm_assert( + &peer->allowed_ips[peer->allowed_ips_len] + <= &src->_lnk_wireguard._allowed_ips_buf[src->_lnk_wireguard._allowed_ips_buf_len]); + + peer->allowed_ips = + &dst->_lnk_wireguard + ._allowed_ips_buf[peer->allowed_ips - src->_lnk_wireguard._allowed_ips_buf]; + } + + nm_assert(nmp_object_equal(src, dst)); +} + +#define _vt_cmd_plobj_id_copy(type, plat_type, cmd) \ + static void _vt_cmd_plobj_id_copy_##type(NMPlatformObject *_dst, const NMPlatformObject *_src) \ + { \ + plat_type *const dst = (plat_type *) _dst; \ + const plat_type *const src = (const plat_type *) _src; \ + { \ + cmd \ + } \ + } \ + struct _dummy_struct_for_tailing_semicolon + +_vt_cmd_plobj_id_copy(link, NMPlatformLink, { dst->ifindex = src->ifindex; }); + +_vt_cmd_plobj_id_copy(ip4_address, NMPlatformIP4Address, { + dst->ifindex = src->ifindex; + dst->plen = src->plen; + dst->address = src->address; + dst->peer_address = src->peer_address; }); -_vt_cmd_plobj_id_copy (ip4_address, NMPlatformIP4Address, { - dst->ifindex = src->ifindex; - dst->plen = src->plen; - dst->address = src->address; - dst->peer_address = src->peer_address; -}); -_vt_cmd_plobj_id_copy (ip6_address, NMPlatformIP6Address, { - dst->ifindex = src->ifindex; - dst->address = src->address; + +_vt_cmd_plobj_id_copy(ip6_address, NMPlatformIP6Address, { + dst->ifindex = src->ifindex; + dst->address = src->address; }); -_vt_cmd_plobj_id_copy (ip4_route, NMPlatformIP4Route, { - *dst = *src; - nm_assert (nm_platform_ip4_route_cmp (dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); + +_vt_cmd_plobj_id_copy(ip4_route, NMPlatformIP4Route, { + *dst = *src; + nm_assert(nm_platform_ip4_route_cmp(dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); }); -_vt_cmd_plobj_id_copy (ip6_route, NMPlatformIP6Route, { - *dst = *src; - nm_assert (nm_platform_ip6_route_cmp (dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); + +_vt_cmd_plobj_id_copy(ip6_route, NMPlatformIP6Route, { + *dst = *src; + nm_assert(nm_platform_ip6_route_cmp(dst, src, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) == 0); }); -_vt_cmd_plobj_id_copy (routing_rule, NMPlatformRoutingRule, { - *dst = *src; - nm_assert (nm_platform_routing_rule_cmp (dst, src, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0); + +_vt_cmd_plobj_id_copy(routing_rule, NMPlatformRoutingRule, { + *dst = *src; + nm_assert(nm_platform_routing_rule_cmp(dst, src, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0); }); /* Uses internally nmp_object_copy(), hence it also violates the const * promise for @obj. * */ NMPObject * -nmp_object_clone (const NMPObject *obj, gboolean id_only) +nmp_object_clone(const NMPObject *obj, gboolean id_only) { - NMPObject *dst; + NMPObject *dst; - if (!obj) - return NULL; + if (!obj) + return NULL; - g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj), NULL); + g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj), NULL); - dst = _nmp_object_new_from_class (NMP_OBJECT_GET_CLASS (obj)); - nmp_object_copy (dst, obj, id_only); - return dst; + dst = _nmp_object_new_from_class(NMP_OBJECT_GET_CLASS(obj)); + nmp_object_copy(dst, obj, id_only); + return dst; } int -nmp_object_id_cmp (const NMPObject *obj1, const NMPObject *obj2) -{ - const NMPClass *klass, *klass2; - - NM_CMP_SELF (obj1, obj2); - - g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj1), FALSE); - g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj2), FALSE); - - klass = NMP_OBJECT_GET_CLASS (obj1); - nm_assert (!klass->cmd_plobj_id_hash_update == !klass->cmd_plobj_id_cmp); - - klass2 = NMP_OBJECT_GET_CLASS (obj2); - nm_assert (klass); - if (klass != klass2) { - nm_assert (klass2); - NM_CMP_DIRECT (klass->obj_type, klass2->obj_type); - /* resort to pointer comparison */ - NM_CMP_DIRECT_PTR (klass, klass2); - return 0; - } - - if (!klass->cmd_plobj_id_cmp) { - /* the klass doesn't implement ID cmp(). That means, different objects - * never compare equal, but the cmp() according to their pointer value. */ - NM_CMP_DIRECT_PTR (obj1, obj2); - return 0; - } - - return klass->cmd_plobj_id_cmp (&obj1->object, &obj2->object); -} - -#define _vt_cmd_plobj_id_cmp(type, plat_type, cmd) \ -static int \ -_vt_cmd_plobj_id_cmp_##type (const NMPlatformObject *_obj1, const NMPlatformObject *_obj2) \ -{ \ - const plat_type *const obj1 = (const plat_type *) _obj1; \ - const plat_type *const obj2 = (const plat_type *) _obj2; \ - \ - NM_CMP_SELF (obj1, obj2); \ - { cmd; } \ - return 0; \ -} -_vt_cmd_plobj_id_cmp (link, NMPlatformLink, - NM_CMP_FIELD (obj1, obj2, ifindex); -) -_vt_cmd_plobj_id_cmp (ip4_address, NMPlatformIP4Address, - NM_CMP_FIELD (obj1, obj2, ifindex); - NM_CMP_FIELD (obj1, obj2, plen); - NM_CMP_FIELD (obj1, obj2, address); - /* for IPv4 addresses, you can add the same local address with differing peer-adddress - * (IFA_ADDRESS), provided that their net-part differs. */ - NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (obj1->peer_address, obj2->peer_address, obj1->plen); -) -_vt_cmd_plobj_id_cmp (ip6_address, NMPlatformIP6Address, - NM_CMP_FIELD (obj1, obj2, ifindex); - /* for IPv6 addresses, the prefix length is not part of the primary identifier. */ - NM_CMP_FIELD_IN6ADDR (obj1, obj2, address); -) -_vt_cmd_plobj_id_cmp (qdisc, NMPlatformQdisc, - NM_CMP_FIELD (obj1, obj2, ifindex); - NM_CMP_FIELD (obj1, obj2, parent); -) -_vt_cmd_plobj_id_cmp (tfilter, NMPlatformTfilter, - NM_CMP_FIELD (obj1, obj2, ifindex); - NM_CMP_FIELD (obj1, obj2, handle); -) +nmp_object_id_cmp(const NMPObject *obj1, const NMPObject *obj2) +{ + const NMPClass *klass, *klass2; + + NM_CMP_SELF(obj1, obj2); + + g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj1), FALSE); + g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj2), FALSE); + + klass = NMP_OBJECT_GET_CLASS(obj1); + nm_assert(!klass->cmd_plobj_id_hash_update == !klass->cmd_plobj_id_cmp); + + klass2 = NMP_OBJECT_GET_CLASS(obj2); + nm_assert(klass); + if (klass != klass2) { + nm_assert(klass2); + NM_CMP_DIRECT(klass->obj_type, klass2->obj_type); + /* resort to pointer comparison */ + NM_CMP_DIRECT_PTR(klass, klass2); + return 0; + } + + if (!klass->cmd_plobj_id_cmp) { + /* the klass doesn't implement ID cmp(). That means, different objects + * never compare equal, but the cmp() according to their pointer value. */ + NM_CMP_DIRECT_PTR(obj1, obj2); + return 0; + } + + return klass->cmd_plobj_id_cmp(&obj1->object, &obj2->object); +} + +#define _vt_cmd_plobj_id_cmp(type, plat_type, cmd) \ + static int _vt_cmd_plobj_id_cmp_##type(const NMPlatformObject *_obj1, \ + const NMPlatformObject *_obj2) \ + { \ + const plat_type *const obj1 = (const plat_type *) _obj1; \ + const plat_type *const obj2 = (const plat_type *) _obj2; \ + \ + NM_CMP_SELF(obj1, obj2); \ + { \ + cmd; \ + } \ + return 0; \ + } \ + struct _dummy_struct_for_tailing_semicolon + +_vt_cmd_plobj_id_cmp(link, NMPlatformLink, { NM_CMP_FIELD(obj1, obj2, ifindex); }); + +_vt_cmd_plobj_id_cmp(ip4_address, NMPlatformIP4Address, { + NM_CMP_FIELD(obj1, obj2, ifindex); + NM_CMP_FIELD(obj1, obj2, plen); + NM_CMP_FIELD(obj1, obj2, address); + /* for IPv4 addresses, you can add the same local address with differing peer-address + * (IFA_ADDRESS), provided that their net-part differs. */ + NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(obj1->peer_address, obj2->peer_address, obj1->plen); +}); + +_vt_cmd_plobj_id_cmp(ip6_address, NMPlatformIP6Address, { + NM_CMP_FIELD(obj1, obj2, ifindex); + /* for IPv6 addresses, the prefix length is not part of the primary identifier. */ + NM_CMP_FIELD_IN6ADDR(obj1, obj2, address); +}); + +_vt_cmd_plobj_id_cmp(qdisc, NMPlatformQdisc, { + NM_CMP_FIELD(obj1, obj2, ifindex); + NM_CMP_FIELD(obj1, obj2, parent); +}); + +_vt_cmd_plobj_id_cmp(tfilter, NMPlatformTfilter, { + NM_CMP_FIELD(obj1, obj2, ifindex); + NM_CMP_FIELD(obj1, obj2, handle); +}); static int -_vt_cmd_plobj_id_cmp_ip4_route (const NMPlatformObject *obj1, const NMPlatformObject *obj2) +_vt_cmd_plobj_id_cmp_ip4_route(const NMPlatformObject *obj1, const NMPlatformObject *obj2) { - return nm_platform_ip4_route_cmp ((NMPlatformIP4Route *) obj1, (NMPlatformIP4Route *) obj2, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID); + return nm_platform_ip4_route_cmp((NMPlatformIP4Route *) obj1, + (NMPlatformIP4Route *) obj2, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID); } static int -_vt_cmd_plobj_id_cmp_ip6_route (const NMPlatformObject *obj1, const NMPlatformObject *obj2) +_vt_cmd_plobj_id_cmp_ip6_route(const NMPlatformObject *obj1, const NMPlatformObject *obj2) { - return nm_platform_ip6_route_cmp ((NMPlatformIP6Route *) obj1, (NMPlatformIP6Route *) obj2, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID); + return nm_platform_ip6_route_cmp((NMPlatformIP6Route *) obj1, + (NMPlatformIP6Route *) obj2, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID); } static int -_vt_cmd_plobj_id_cmp_routing_rule (const NMPlatformObject *obj1, const NMPlatformObject *obj2) +_vt_cmd_plobj_id_cmp_routing_rule(const NMPlatformObject *obj1, const NMPlatformObject *obj2) { - return nm_platform_routing_rule_cmp ((NMPlatformRoutingRule *) obj1, (NMPlatformRoutingRule *) obj2, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID); + return nm_platform_routing_rule_cmp((NMPlatformRoutingRule *) obj1, + (NMPlatformRoutingRule *) obj2, + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID); } void -nmp_object_id_hash_update (const NMPObject *obj, NMHashState *h) +nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h) { - const NMPClass *klass; + const NMPClass *klass; - g_return_if_fail (NMP_OBJECT_IS_VALID (obj)); + g_return_if_fail(NMP_OBJECT_IS_VALID(obj)); - klass = NMP_OBJECT_GET_CLASS (obj); + klass = NMP_OBJECT_GET_CLASS(obj); - nm_assert (!klass->cmd_plobj_id_hash_update == !klass->cmd_plobj_id_cmp); + nm_assert(!klass->cmd_plobj_id_hash_update == !klass->cmd_plobj_id_cmp); - if (!klass->cmd_plobj_id_hash_update) { - /* The klass doesn't implement ID compare. It means, to use pointer - * equality. */ - nm_hash_update_val (h, obj); - return; - } + if (!klass->cmd_plobj_id_hash_update) { + /* The klass doesn't implement ID compare. It means, to use pointer + * equality. */ + nm_hash_update_val(h, obj); + return; + } - nm_hash_update_val (h, klass->obj_type); - klass->cmd_plobj_id_hash_update (&obj->object, h); + nm_hash_update_val(h, klass->obj_type); + klass->cmd_plobj_id_hash_update(&obj->object, h); } guint -nmp_object_id_hash (const NMPObject *obj) -{ - NMHashState h; - - if (!obj) - return nm_hash_static (914932607u); - - nm_hash_init (&h, 914932607u); - nmp_object_id_hash_update (obj, &h); - return nm_hash_complete (&h); -} - -#define _vt_cmd_plobj_id_hash_update(type, plat_type, cmd) \ -static void \ -_vt_cmd_plobj_id_hash_update_##type (const NMPlatformObject *_obj, NMHashState *h) \ -{ \ - const plat_type *const obj = (const plat_type *) _obj; \ - { cmd; } \ -} -_vt_cmd_plobj_id_hash_update (link, NMPlatformLink, { - nm_hash_update_val (h, obj->ifindex); -}) -_vt_cmd_plobj_id_hash_update (ip4_address, NMPlatformIP4Address, { - nm_hash_update_vals (h, - obj->ifindex, - obj->plen, - obj->address, - /* for IPv4 we must also consider the net-part of the peer-address (IFA_ADDRESS) */ - nm_utils_ip4_address_clear_host_address (obj->peer_address, obj->plen)); -}) -_vt_cmd_plobj_id_hash_update (ip6_address, NMPlatformIP6Address, { - nm_hash_update_vals (h, - obj->ifindex, - /* for IPv6 addresses, the prefix length is not part of the primary identifier. */ - obj->address); -}) -_vt_cmd_plobj_id_hash_update (ip4_route, NMPlatformIP4Route, { - nm_platform_ip4_route_hash_update (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, h); -}) -_vt_cmd_plobj_id_hash_update (ip6_route, NMPlatformIP6Route, { - nm_platform_ip6_route_hash_update (obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, h); -}) -_vt_cmd_plobj_id_hash_update (routing_rule, NMPlatformRoutingRule, { - nm_platform_routing_rule_hash_update (obj, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, h); -}) -_vt_cmd_plobj_id_hash_update (qdisc, NMPlatformQdisc, { - nm_hash_update_vals (h, - obj->ifindex, - obj->parent); -}) -_vt_cmd_plobj_id_hash_update (tfilter, NMPlatformTfilter, { - nm_hash_update_vals (h, - obj->ifindex, - obj->handle); -}) +nmp_object_id_hash(const NMPObject *obj) +{ + NMHashState h; + + if (!obj) + return nm_hash_static(914932607u); + + nm_hash_init(&h, 914932607u); + nmp_object_id_hash_update(obj, &h); + return nm_hash_complete(&h); +} + +#define _vt_cmd_plobj_id_hash_update(type, plat_type, cmd) \ + static void _vt_cmd_plobj_id_hash_update_##type(const NMPlatformObject *_obj, NMHashState *h) \ + { \ + const plat_type *const obj = (const plat_type *) _obj; \ + { \ + cmd; \ + } \ + } \ + struct _dummy_struct_for_tailing_semicolon + +_vt_cmd_plobj_id_hash_update(link, NMPlatformLink, { nm_hash_update_val(h, obj->ifindex); }); + +_vt_cmd_plobj_id_hash_update(ip4_address, NMPlatformIP4Address, { + nm_hash_update_vals( + h, + obj->ifindex, + obj->plen, + obj->address, + /* for IPv4 we must also consider the net-part of the peer-address (IFA_ADDRESS) */ + nm_utils_ip4_address_clear_host_address(obj->peer_address, obj->plen)); +}); + +_vt_cmd_plobj_id_hash_update(ip6_address, NMPlatformIP6Address, { + nm_hash_update_vals( + h, + obj->ifindex, + /* for IPv6 addresses, the prefix length is not part of the primary identifier. */ + obj->address); +}); + +_vt_cmd_plobj_id_hash_update(ip4_route, NMPlatformIP4Route, { + nm_platform_ip4_route_hash_update(obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, h); +}); + +_vt_cmd_plobj_id_hash_update(ip6_route, NMPlatformIP6Route, { + nm_platform_ip6_route_hash_update(obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, h); +}); + +_vt_cmd_plobj_id_hash_update(routing_rule, NMPlatformRoutingRule, { + nm_platform_routing_rule_hash_update(obj, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, h); +}); + +_vt_cmd_plobj_id_hash_update(qdisc, NMPlatformQdisc, { + nm_hash_update_vals(h, obj->ifindex, obj->parent); +}); + +_vt_cmd_plobj_id_hash_update(tfilter, NMPlatformTfilter, { + nm_hash_update_vals(h, obj->ifindex, obj->handle); +}); static void -_vt_cmd_plobj_hash_update_ip4_route (const NMPlatformObject *obj, NMHashState *h) +_vt_cmd_plobj_hash_update_ip4_route(const NMPlatformObject *obj, NMHashState *h) { - return nm_platform_ip4_route_hash_update ((const NMPlatformIP4Route *) obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, h); + return nm_platform_ip4_route_hash_update((const NMPlatformIP4Route *) obj, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, + h); } static void -_vt_cmd_plobj_hash_update_ip6_route (const NMPlatformObject *obj, NMHashState *h) +_vt_cmd_plobj_hash_update_ip6_route(const NMPlatformObject *obj, NMHashState *h) { - return nm_platform_ip6_route_hash_update ((const NMPlatformIP6Route *) obj, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, h); + return nm_platform_ip6_route_hash_update((const NMPlatformIP6Route *) obj, + NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL, + h); } static void -_vt_cmd_plobj_hash_update_routing_rule (const NMPlatformObject *obj, NMHashState *h) +_vt_cmd_plobj_hash_update_routing_rule(const NMPlatformObject *obj, NMHashState *h) +{ + return nm_platform_routing_rule_hash_update((const NMPlatformRoutingRule *) obj, + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL, + h); +} + +guint +nmp_object_indirect_id_hash(gconstpointer a) { - return nm_platform_routing_rule_hash_update ((const NMPlatformRoutingRule *) obj, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL, h); + const NMPObject *const *p_obj = a; + + return nmp_object_id_hash(*p_obj); +} + +gboolean +nmp_object_indirect_id_equal(gconstpointer a, gconstpointer b) +{ + const NMPObject *const *p_obj_a = a; + const NMPObject *const *p_obj_b = b; + + return nmp_object_id_equal(*p_obj_a, *p_obj_b); } +/*****************************************************************************/ + gboolean -nmp_object_is_alive (const NMPObject *obj) +nmp_object_is_alive(const NMPObject *obj) { - const NMPClass *klass; + const NMPClass *klass; - /* for convenience, allow NULL. */ - if (!obj) - return FALSE; + /* for convenience, allow NULL. */ + if (!obj) + return FALSE; - klass = NMP_OBJECT_GET_CLASS (obj); - return !klass->cmd_obj_is_alive - || klass->cmd_obj_is_alive (obj); + klass = NMP_OBJECT_GET_CLASS(obj); + return !klass->cmd_obj_is_alive || klass->cmd_obj_is_alive(obj); } static gboolean -_vt_cmd_obj_is_alive_link (const NMPObject *obj) +_vt_cmd_obj_is_alive_link(const NMPObject *obj) { - return NMP_OBJECT_CAST_LINK (obj)->ifindex > 0 - && (obj->_link.netlink.is_in_netlink || obj->_link.udev.device); + return NMP_OBJECT_CAST_LINK(obj)->ifindex > 0 + && (obj->_link.netlink.is_in_netlink || obj->_link.udev.device); } static gboolean -_vt_cmd_obj_is_alive_ipx_address (const NMPObject *obj) +_vt_cmd_obj_is_alive_ipx_address(const NMPObject *obj) { - return NMP_OBJECT_CAST_IP_ADDRESS (obj)->ifindex > 0; + return NMP_OBJECT_CAST_IP_ADDRESS(obj)->ifindex > 0; } static gboolean -_vt_cmd_obj_is_alive_ipx_route (const NMPObject *obj) -{ - /* We want to ignore routes that are RTM_F_CLONED but we still - * let nmp_object_from_nl() create such route objects, instead of - * returning NULL right away. - * - * The idea is, that if we have the same route (according to its id) - * in the cache with !RTM_F_CLONED, an update that changes the route - * to be RTM_F_CLONED must remove the instance. - * - * If nmp_object_from_nl() would just return NULL, we couldn't look - * into the cache to see if it contains a route that now disappears - * (because it changed to be cloned). - * - * Instead we create a dead object, and nmp_cache_update_netlink() - * will remove the old version of the update. - **/ - return NMP_OBJECT_CAST_IP_ROUTE (obj)->ifindex > 0 - && !NM_FLAGS_HAS (obj->ip_route.r_rtm_flags, RTM_F_CLONED); +_vt_cmd_obj_is_alive_ipx_route(const NMPObject *obj) +{ + /* We want to ignore routes that are RTM_F_CLONED but we still + * let nmp_object_from_nl() create such route objects, instead of + * returning NULL right away. + * + * The idea is, that if we have the same route (according to its id) + * in the cache with !RTM_F_CLONED, an update that changes the route + * to be RTM_F_CLONED must remove the instance. + * + * If nmp_object_from_nl() would just return NULL, we couldn't look + * into the cache to see if it contains a route that now disappears + * (because it changed to be cloned). + * + * Instead we create a dead object, and nmp_cache_update_netlink() + * will remove the old version of the update. + **/ + return NMP_OBJECT_CAST_IP_ROUTE(obj)->ifindex > 0 + && !NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, RTM_F_CLONED); } static gboolean -_vt_cmd_obj_is_alive_routing_rule (const NMPObject *obj) +_vt_cmd_obj_is_alive_routing_rule(const NMPObject *obj) { - return NM_IN_SET (obj->routing_rule.addr_family, AF_INET, AF_INET6); + return NM_IN_SET(obj->routing_rule.addr_family, AF_INET, AF_INET6); } static gboolean -_vt_cmd_obj_is_alive_qdisc (const NMPObject *obj) +_vt_cmd_obj_is_alive_qdisc(const NMPObject *obj) { - return NMP_OBJECT_CAST_QDISC (obj)->ifindex > 0; + return NMP_OBJECT_CAST_QDISC(obj)->ifindex > 0; } static gboolean -_vt_cmd_obj_is_alive_tfilter (const NMPObject *obj) +_vt_cmd_obj_is_alive_tfilter(const NMPObject *obj) { - return NMP_OBJECT_CAST_TFILTER (obj)->ifindex > 0; + return NMP_OBJECT_CAST_TFILTER(obj)->ifindex > 0; } gboolean -nmp_object_is_visible (const NMPObject *obj) +nmp_object_is_visible(const NMPObject *obj) { - const NMPClass *klass; + const NMPClass *klass; - /* for convenience, allow NULL. */ - if (!obj) - return FALSE; + /* for convenience, allow NULL. */ + if (!obj) + return FALSE; - klass = NMP_OBJECT_GET_CLASS (obj); + klass = NMP_OBJECT_GET_CLASS(obj); - /* a dead object is never visible. */ - if ( klass->cmd_obj_is_alive - && !klass->cmd_obj_is_alive (obj)) - return FALSE; + /* a dead object is never visible. */ + if (klass->cmd_obj_is_alive && !klass->cmd_obj_is_alive(obj)) + return FALSE; - return !klass->cmd_obj_is_visible - || klass->cmd_obj_is_visible (obj); + return !klass->cmd_obj_is_visible || klass->cmd_obj_is_visible(obj); } static gboolean -_vt_cmd_obj_is_visible_link (const NMPObject *obj) +_vt_cmd_obj_is_visible_link(const NMPObject *obj) { - return obj->_link.netlink.is_in_netlink - && obj->link.name[0]; + return obj->_link.netlink.is_in_netlink && obj->link.name[0]; } /*****************************************************************************/ static const guint8 _supported_cache_ids_object[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - 0, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, + 0, }; static const guint8 _supported_cache_ids_link[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_LINK_BY_IFNAME, - 0, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + NMP_CACHE_ID_TYPE_LINK_BY_IFNAME, + 0, }; static const guint8 _supported_cache_ids_ipx_address[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - 0, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, + 0, }; static const guint8 _supported_cache_ids_ipx_route[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - NMP_CACHE_ID_TYPE_DEFAULT_ROUTES, - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - 0, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, + NMP_CACHE_ID_TYPE_DEFAULT_ROUTES, + NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, + 0, }; static const guint8 _supported_cache_ids_routing_rules[] = { - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY, - 0, + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY, + 0, }; /*****************************************************************************/ static void -_vt_dedup_obj_destroy (NMDedupMultiObj *obj) +_vt_dedup_obj_destroy(NMDedupMultiObj *obj) { - NMPObject *o = (NMPObject *) obj; - const NMPClass *klass; + NMPObject * o = (NMPObject *) obj; + const NMPClass *klass; - nm_assert (o->parent._ref_count == 0); - nm_assert (!o->parent._multi_idx); + nm_assert(o->parent._ref_count == 0); + nm_assert(!o->parent._multi_idx); - klass = o->_class; - if (klass->cmd_obj_dispose) - klass->cmd_obj_dispose (o); - g_slice_free1 (klass->sizeof_data + G_STRUCT_OFFSET (NMPObject, object), o); + klass = o->_class; + if (klass->cmd_obj_dispose) + klass->cmd_obj_dispose(o); + g_slice_free1(klass->sizeof_data + G_STRUCT_OFFSET(NMPObject, object), o); } static const NMDedupMultiObj * -_vt_dedup_obj_clone (const NMDedupMultiObj *obj) +_vt_dedup_obj_clone(const NMDedupMultiObj *obj) { - return (const NMDedupMultiObj *) nmp_object_clone ((const NMPObject *) obj, FALSE); + return (const NMDedupMultiObj *) nmp_object_clone((const NMPObject *) obj, FALSE); } -#define DEDUP_MULTI_OBJ_CLASS_INIT() \ - { \ - .obj_clone = _vt_dedup_obj_clone, \ - .obj_destroy = _vt_dedup_obj_destroy, \ - .obj_full_hash_update = (void (*)(const NMDedupMultiObj *obj, NMHashState *h)) nmp_object_hash_update, \ - .obj_full_equal = (gboolean (*)(const NMDedupMultiObj *obj_a, const NMDedupMultiObj *obj_b)) nmp_object_equal, \ - } +#define DEDUP_MULTI_OBJ_CLASS_INIT() \ + { \ + .obj_clone = _vt_dedup_obj_clone, .obj_destroy = _vt_dedup_obj_destroy, \ + .obj_full_hash_update = \ + (void (*)(const NMDedupMultiObj *obj, NMHashState *h)) nmp_object_hash_update, \ + .obj_full_equal = (gboolean(*)(const NMDedupMultiObj *obj_a, \ + const NMDedupMultiObj *obj_b)) nmp_object_equal, \ + } /*****************************************************************************/ static NMDedupMultiIdxType * -_idx_type_get (const NMPCache *cache, NMPCacheIdType cache_id_type) +_idx_type_get(const NMPCache *cache, NMPCacheIdType cache_id_type) { - nm_assert (cache); - nm_assert (cache_id_type > NMP_CACHE_ID_TYPE_NONE); - nm_assert (cache_id_type <= NMP_CACHE_ID_TYPE_MAX); - nm_assert ((int) cache_id_type - 1 >= 0); - nm_assert ((int) cache_id_type - 1 < G_N_ELEMENTS (cache->idx_types)); + nm_assert(cache); + nm_assert(cache_id_type > NMP_CACHE_ID_TYPE_NONE); + nm_assert(cache_id_type <= NMP_CACHE_ID_TYPE_MAX); + nm_assert((int) cache_id_type - 1 >= 0); + nm_assert((int) cache_id_type - 1 < G_N_ELEMENTS(cache->idx_types)); - return (NMDedupMultiIdxType *) &cache->idx_types[cache_id_type - 1]; + return (NMDedupMultiIdxType *) &cache->idx_types[cache_id_type - 1]; } gboolean -nmp_cache_use_udev_get (const NMPCache *cache) +nmp_cache_use_udev_get(const NMPCache *cache) { - g_return_val_if_fail (cache, TRUE); + g_return_val_if_fail(cache, TRUE); - return cache->use_udev; + return cache->use_udev; } /*****************************************************************************/ gboolean -nmp_cache_link_connected_for_slave (int ifindex_master, const NMPObject *slave) +nmp_cache_link_connected_for_slave(int ifindex_master, const NMPObject *slave) { - nm_assert (NMP_OBJECT_GET_TYPE (slave) == NMP_OBJECT_TYPE_LINK); + nm_assert(NMP_OBJECT_GET_TYPE(slave) == NMP_OBJECT_TYPE_LINK); - return ifindex_master > 0 - && slave->link.master == ifindex_master - && slave->link.connected - && nmp_object_is_visible (slave); + return ifindex_master > 0 && slave->link.master == ifindex_master && slave->link.connected + && nmp_object_is_visible(slave); } /** @@ -1786,49 +1877,49 @@ nmp_cache_link_connected_for_slave (int ifindex_master, const NMPObject *slave) * Returns: %TRUE, if @master->link.connected should be flipped/toggled. **/ gboolean -nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *master, const NMPObject *potential_slave, const NMPObject *ignore_slave) -{ - gboolean is_lower_up = FALSE; - - if ( !master - || NMP_OBJECT_GET_TYPE (master) != NMP_OBJECT_TYPE_LINK - || master->link.ifindex <= 0 - || !nmp_object_is_visible (master) - || !NM_IN_SET (master->link.type, NM_LINK_TYPE_BRIDGE, NM_LINK_TYPE_BOND)) - return FALSE; - - /* if native IFF_LOWER_UP is down, link.connected must also be down - * regardless of the slaves. */ - if (!NM_FLAGS_HAS (master->link.n_ifi_flags, IFF_LOWER_UP)) - return !!master->link.connected; - - if (potential_slave && NMP_OBJECT_GET_TYPE (potential_slave) != NMP_OBJECT_TYPE_LINK) - potential_slave = NULL; - - if ( potential_slave - && nmp_cache_link_connected_for_slave (master->link.ifindex, potential_slave)) - is_lower_up = TRUE; - else { - NMPLookup lookup; - NMDedupMultiIter iter; - const NMPlatformLink *link = NULL; - - nmp_cache_iter_for_each_link (&iter, - nmp_cache_lookup (cache, - nmp_lookup_init_obj_type (&lookup, - NMP_OBJECT_TYPE_LINK)), - &link) { - const NMPObject *obj = NMP_OBJECT_UP_CAST ((NMPlatformObject *) link); - - if ( (!potential_slave || potential_slave->link.ifindex != link->ifindex) - && ignore_slave != obj - && nmp_cache_link_connected_for_slave (master->link.ifindex, obj)) { - is_lower_up = TRUE; - break; - } - } - } - return !!master->link.connected != is_lower_up; +nmp_cache_link_connected_needs_toggle(const NMPCache * cache, + const NMPObject *master, + const NMPObject *potential_slave, + const NMPObject *ignore_slave) +{ + gboolean is_lower_up = FALSE; + + if (!master || NMP_OBJECT_GET_TYPE(master) != NMP_OBJECT_TYPE_LINK || master->link.ifindex <= 0 + || !nmp_object_is_visible(master) + || !NM_IN_SET(master->link.type, NM_LINK_TYPE_BRIDGE, NM_LINK_TYPE_BOND)) + return FALSE; + + /* if native IFF_LOWER_UP is down, link.connected must also be down + * regardless of the slaves. */ + if (!NM_FLAGS_HAS(master->link.n_ifi_flags, IFF_LOWER_UP)) + return !!master->link.connected; + + if (potential_slave && NMP_OBJECT_GET_TYPE(potential_slave) != NMP_OBJECT_TYPE_LINK) + potential_slave = NULL; + + if (potential_slave + && nmp_cache_link_connected_for_slave(master->link.ifindex, potential_slave)) + is_lower_up = TRUE; + else { + NMPLookup lookup; + NMDedupMultiIter iter; + const NMPlatformLink *link = NULL; + + nmp_cache_iter_for_each_link ( + &iter, + nmp_cache_lookup(cache, nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK)), + &link) { + const NMPObject *obj = NMP_OBJECT_UP_CAST((NMPlatformObject *) link); + + if ((!potential_slave || potential_slave->link.ifindex != link->ifindex) + && ignore_slave != obj + && nmp_cache_link_connected_for_slave(master->link.ifindex, obj)) { + is_lower_up = TRUE; + break; + } + } + } + return !!master->link.connected != is_lower_up; } /** @@ -1851,703 +1942,683 @@ nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *m * The connected flag of that master should be toggled. */ const NMPObject * -nmp_cache_link_connected_needs_toggle_by_ifindex (const NMPCache *cache, int master_ifindex, const NMPObject *potential_slave, const NMPObject *ignore_slave) +nmp_cache_link_connected_needs_toggle_by_ifindex(const NMPCache * cache, + int master_ifindex, + const NMPObject *potential_slave, + const NMPObject *ignore_slave) { - const NMPObject *master; + const NMPObject *master; - if (master_ifindex > 0) { - master = nmp_cache_lookup_link (cache, master_ifindex); - if (nmp_cache_link_connected_needs_toggle (cache, master, potential_slave, ignore_slave)) - return master; - } - return NULL; + if (master_ifindex > 0) { + master = nmp_cache_lookup_link(cache, master_ifindex); + if (nmp_cache_link_connected_needs_toggle(cache, master, potential_slave, ignore_slave)) + return master; + } + return NULL; } /*****************************************************************************/ static const NMDedupMultiEntry * -_lookup_entry_with_idx_type (const NMPCache *cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj) +_lookup_entry_with_idx_type(const NMPCache * cache, + NMPCacheIdType cache_id_type, + const NMPObject *obj) { - const NMDedupMultiEntry *entry; + const NMDedupMultiEntry *entry; - nm_assert (cache); - nm_assert (NMP_OBJECT_IS_VALID (obj)); + nm_assert(cache); + nm_assert(NMP_OBJECT_IS_VALID(obj)); - entry = nm_dedup_multi_index_lookup_obj (cache->multi_idx, - _idx_type_get (cache, cache_id_type), - obj); - nm_assert (!entry - || ( NMP_OBJECT_IS_VALID (entry->obj) - && NMP_OBJECT_GET_CLASS (entry->obj) == NMP_OBJECT_GET_CLASS (obj))); - return entry; + entry = + nm_dedup_multi_index_lookup_obj(cache->multi_idx, _idx_type_get(cache, cache_id_type), obj); + nm_assert(!entry + || (NMP_OBJECT_IS_VALID(entry->obj) + && NMP_OBJECT_GET_CLASS(entry->obj) == NMP_OBJECT_GET_CLASS(obj))); + return entry; } static const NMDedupMultiEntry * -_lookup_entry (const NMPCache *cache, const NMPObject *obj) +_lookup_entry(const NMPCache *cache, const NMPObject *obj) { - return _lookup_entry_with_idx_type (cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj); + return _lookup_entry_with_idx_type(cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj); } const NMDedupMultiEntry * -nmp_cache_lookup_entry_with_idx_type (const NMPCache *cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj) +nmp_cache_lookup_entry_with_idx_type(const NMPCache * cache, + NMPCacheIdType cache_id_type, + const NMPObject *obj) { - g_return_val_if_fail (cache, NULL); - g_return_val_if_fail (obj, NULL); - g_return_val_if_fail (cache_id_type > NMP_CACHE_ID_TYPE_NONE && cache_id_type <= NMP_CACHE_ID_TYPE_MAX, NULL); + g_return_val_if_fail(cache, NULL); + g_return_val_if_fail(obj, NULL); + g_return_val_if_fail(cache_id_type > NMP_CACHE_ID_TYPE_NONE + && cache_id_type <= NMP_CACHE_ID_TYPE_MAX, + NULL); - return _lookup_entry_with_idx_type (cache, cache_id_type, obj); + return _lookup_entry_with_idx_type(cache, cache_id_type, obj); } const NMDedupMultiEntry * -nmp_cache_lookup_entry (const NMPCache *cache, const NMPObject *obj) +nmp_cache_lookup_entry(const NMPCache *cache, const NMPObject *obj) { - g_return_val_if_fail (cache, NULL); - g_return_val_if_fail (obj, NULL); + g_return_val_if_fail(cache, NULL); + g_return_val_if_fail(obj, NULL); - return _lookup_entry (cache, obj); + return _lookup_entry(cache, obj); } const NMDedupMultiEntry * -nmp_cache_lookup_entry_link (const NMPCache *cache, int ifindex) +nmp_cache_lookup_entry_link(const NMPCache *cache, int ifindex) { - NMPObject obj_needle; + NMPObject obj_needle; - g_return_val_if_fail (cache, NULL); - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail(cache, NULL); + g_return_val_if_fail(ifindex > 0, NULL); - nmp_object_stackinit_id_link (&obj_needle, ifindex); - return _lookup_entry (cache, &obj_needle); + nmp_object_stackinit_id_link(&obj_needle, ifindex); + return _lookup_entry(cache, &obj_needle); } const NMPObject * -nmp_cache_lookup_obj (const NMPCache *cache, const NMPObject *obj) +nmp_cache_lookup_obj(const NMPCache *cache, const NMPObject *obj) { - return nm_dedup_multi_entry_get_obj (nmp_cache_lookup_entry (cache, obj)); + return nm_dedup_multi_entry_get_obj(nmp_cache_lookup_entry(cache, obj)); } const NMPObject * -nmp_cache_lookup_link (const NMPCache *cache, int ifindex) +nmp_cache_lookup_link(const NMPCache *cache, int ifindex) { - return nm_dedup_multi_entry_get_obj (nmp_cache_lookup_entry_link (cache, ifindex)); + return nm_dedup_multi_entry_get_obj(nmp_cache_lookup_entry_link(cache, ifindex)); } /*****************************************************************************/ const NMDedupMultiHeadEntry * -nmp_cache_lookup_all (const NMPCache *cache, - NMPCacheIdType cache_id_type, - const NMPObject *select_obj) +nmp_cache_lookup_all(const NMPCache * cache, + NMPCacheIdType cache_id_type, + const NMPObject *select_obj) { - nm_assert (cache); - nm_assert (NMP_OBJECT_IS_VALID (select_obj)); + nm_assert(cache); + nm_assert(NMP_OBJECT_IS_VALID(select_obj)); - return nm_dedup_multi_index_lookup_head (cache->multi_idx, - _idx_type_get (cache, cache_id_type), - select_obj); + return nm_dedup_multi_index_lookup_head(cache->multi_idx, + _idx_type_get(cache, cache_id_type), + select_obj); } static const NMPLookup * -_L (const NMPLookup *lookup) +_L(const NMPLookup *lookup) { #if NM_MORE_ASSERTS - DedupMultiIdxType idx_type; + DedupMultiIdxType idx_type; - nm_assert (lookup); - _dedup_multi_idx_type_init (&idx_type, lookup->cache_id_type); - nm_assert (idx_type.parent.klass->idx_obj_partitionable ((NMDedupMultiIdxType *) &idx_type, (NMDedupMultiObj *) &lookup->selector_obj)); + nm_assert(lookup); + _dedup_multi_idx_type_init(&idx_type, lookup->cache_id_type); + nm_assert( + idx_type.parent.klass->idx_obj_partitionable((NMDedupMultiIdxType *) &idx_type, + (NMDedupMultiObj *) &lookup->selector_obj)); #endif - return lookup; + return lookup; } const NMPLookup * -nmp_lookup_init_obj_type (NMPLookup *lookup, - NMPObjectType obj_type) -{ - nm_assert (lookup); - - switch (obj_type) { - case NMP_OBJECT_TYPE_LINK: - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - case NMP_OBJECT_TYPE_ROUTING_RULE: - case NMP_OBJECT_TYPE_QDISC: - case NMP_OBJECT_TYPE_TFILTER: - _nmp_object_stackinit_from_type (&lookup->selector_obj, obj_type); - lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_TYPE; - return _L (lookup); - default: - nm_assert_not_reached (); - return NULL; - } +nmp_lookup_init_obj_type(NMPLookup *lookup, NMPObjectType obj_type) +{ + nm_assert(lookup); + + switch (obj_type) { + case NMP_OBJECT_TYPE_LINK: + case NMP_OBJECT_TYPE_IP4_ADDRESS: + case NMP_OBJECT_TYPE_IP6_ADDRESS: + case NMP_OBJECT_TYPE_IP4_ROUTE: + case NMP_OBJECT_TYPE_IP6_ROUTE: + case NMP_OBJECT_TYPE_ROUTING_RULE: + case NMP_OBJECT_TYPE_QDISC: + case NMP_OBJECT_TYPE_TFILTER: + _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); + lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_TYPE; + return _L(lookup); + default: + nm_assert_not_reached(); + return NULL; + } } const NMPLookup * -nmp_lookup_init_link_by_ifname (NMPLookup *lookup, - const char *ifname) +nmp_lookup_init_link_by_ifname(NMPLookup *lookup, const char *ifname) { - NMPObject *o; + NMPObject *o; - nm_assert (lookup); - nm_assert (ifname); - nm_assert (strlen (ifname) < IFNAMSIZ); + nm_assert(lookup); + nm_assert(ifname); + nm_assert(strlen(ifname) < IFNAMSIZ); - o = _nmp_object_stackinit_from_type (&lookup->selector_obj, NMP_OBJECT_TYPE_LINK); - if (g_strlcpy (o->link.name, ifname, sizeof (o->link.name)) >= sizeof (o->link.name)) - g_return_val_if_reached (NULL); - lookup->cache_id_type = NMP_CACHE_ID_TYPE_LINK_BY_IFNAME; - return _L (lookup); + o = _nmp_object_stackinit_from_type(&lookup->selector_obj, NMP_OBJECT_TYPE_LINK); + if (g_strlcpy(o->link.name, ifname, sizeof(o->link.name)) >= sizeof(o->link.name)) + g_return_val_if_reached(NULL); + lookup->cache_id_type = NMP_CACHE_ID_TYPE_LINK_BY_IFNAME; + return _L(lookup); } const NMPLookup * -nmp_lookup_init_object (NMPLookup *lookup, - NMPObjectType obj_type, - int ifindex) +nmp_lookup_init_object(NMPLookup *lookup, NMPObjectType obj_type, int ifindex) { - NMPObject *o; + NMPObject *o; - nm_assert (lookup); - nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS, - NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE, - NMP_OBJECT_TYPE_QDISC, - NMP_OBJECT_TYPE_TFILTER)); + nm_assert(lookup); + nm_assert(NM_IN_SET(obj_type, + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS, + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE, + NMP_OBJECT_TYPE_QDISC, + NMP_OBJECT_TYPE_TFILTER)); - if (ifindex <= 0) { - return nmp_lookup_init_obj_type (lookup, - obj_type); - } + if (ifindex <= 0) { + return nmp_lookup_init_obj_type(lookup, obj_type); + } - o = _nmp_object_stackinit_from_type (&lookup->selector_obj, obj_type); - o->obj_with_ifindex.ifindex = ifindex; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX; - return _L (lookup); + o = _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); + o->obj_with_ifindex.ifindex = ifindex; + lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX; + return _L(lookup); } const NMPLookup * -nmp_lookup_init_route_default (NMPLookup *lookup, - NMPObjectType obj_type) +nmp_lookup_init_route_default(NMPLookup *lookup, NMPObjectType obj_type) { - NMPObject *o; + NMPObject *o; - nm_assert (lookup); - nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); + nm_assert(lookup); + nm_assert(NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); - o = _nmp_object_stackinit_from_type (&lookup->selector_obj, obj_type); - o->ip_route.ifindex = 1; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_DEFAULT_ROUTES; - return _L (lookup); + o = _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); + o->ip_route.ifindex = 1; + lookup->cache_id_type = NMP_CACHE_ID_TYPE_DEFAULT_ROUTES; + return _L(lookup); } const NMPLookup * -nmp_lookup_init_route_by_weak_id (NMPLookup *lookup, - const NMPObject *obj) -{ - const NMPlatformIP4Route *r4; - const NMPlatformIP6Route *r6; - - nm_assert (lookup); - - switch (NMP_OBJECT_GET_TYPE (obj)) { - case NMP_OBJECT_TYPE_IP4_ROUTE: - r4 = NMP_OBJECT_CAST_IP4_ROUTE (obj); - return nmp_lookup_init_ip4_route_by_weak_id (lookup, - r4->network, - r4->plen, - r4->metric, - r4->tos); - case NMP_OBJECT_TYPE_IP6_ROUTE: - r6 = NMP_OBJECT_CAST_IP6_ROUTE (obj); - return nmp_lookup_init_ip6_route_by_weak_id (lookup, - &r6->network, - r6->plen, - r6->metric, - &r6->src, - r6->src_plen); - default: - nm_assert_not_reached (); - return NULL; - } +nmp_lookup_init_route_by_weak_id(NMPLookup *lookup, const NMPObject *obj) +{ + const NMPlatformIP4Route *r4; + const NMPlatformIP6Route *r6; + + nm_assert(lookup); + + switch (NMP_OBJECT_GET_TYPE(obj)) { + case NMP_OBJECT_TYPE_IP4_ROUTE: + r4 = NMP_OBJECT_CAST_IP4_ROUTE(obj); + return nmp_lookup_init_ip4_route_by_weak_id(lookup, + r4->network, + r4->plen, + r4->metric, + r4->tos); + case NMP_OBJECT_TYPE_IP6_ROUTE: + r6 = NMP_OBJECT_CAST_IP6_ROUTE(obj); + return nmp_lookup_init_ip6_route_by_weak_id(lookup, + &r6->network, + r6->plen, + r6->metric, + &r6->src, + r6->src_plen); + default: + nm_assert_not_reached(); + return NULL; + } } const NMPLookup * -nmp_lookup_init_ip4_route_by_weak_id (NMPLookup *lookup, - in_addr_t network, - guint plen, - guint32 metric, - guint8 tos) +nmp_lookup_init_ip4_route_by_weak_id(NMPLookup *lookup, + in_addr_t network, + guint plen, + guint32 metric, + guint8 tos) { - NMPObject *o; + NMPObject *o; - nm_assert (lookup); + nm_assert(lookup); - o = _nmp_object_stackinit_from_type (&lookup->selector_obj, NMP_OBJECT_TYPE_IP4_ROUTE); - o->ip4_route.ifindex = 1; - o->ip4_route.plen = plen; - o->ip4_route.metric = metric; - if (network) - o->ip4_route.network = network; - o->ip4_route.tos = tos; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID; - return _L (lookup); + o = _nmp_object_stackinit_from_type(&lookup->selector_obj, NMP_OBJECT_TYPE_IP4_ROUTE); + o->ip4_route.ifindex = 1; + o->ip4_route.plen = plen; + o->ip4_route.metric = metric; + if (network) + o->ip4_route.network = network; + o->ip4_route.tos = tos; + lookup->cache_id_type = NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID; + return _L(lookup); } const NMPLookup * -nmp_lookup_init_ip6_route_by_weak_id (NMPLookup *lookup, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen) -{ - NMPObject *o; - - nm_assert (lookup); - - o = _nmp_object_stackinit_from_type (&lookup->selector_obj, NMP_OBJECT_TYPE_IP6_ROUTE); - o->ip6_route.ifindex = 1; - o->ip6_route.plen = plen; - o->ip6_route.metric = metric; - if (network) - o->ip6_route.network = *network; - if (src) - o->ip6_route.src = *src; - o->ip6_route.src_plen = src_plen; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID; - return _L (lookup); +nmp_lookup_init_ip6_route_by_weak_id(NMPLookup * lookup, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen) +{ + NMPObject *o; + + nm_assert(lookup); + + o = _nmp_object_stackinit_from_type(&lookup->selector_obj, NMP_OBJECT_TYPE_IP6_ROUTE); + o->ip6_route.ifindex = 1; + o->ip6_route.plen = plen; + o->ip6_route.metric = metric; + if (network) + o->ip6_route.network = *network; + if (src) + o->ip6_route.src = *src; + o->ip6_route.src_plen = src_plen; + lookup->cache_id_type = NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID; + return _L(lookup); } const NMPLookup * -nmp_lookup_init_object_by_addr_family (NMPLookup *lookup, - NMPObjectType obj_type, - int addr_family) +nmp_lookup_init_object_by_addr_family(NMPLookup *lookup, NMPObjectType obj_type, int addr_family) { - NMPObject *o; + NMPObject *o; - nm_assert (lookup); - nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_ROUTING_RULE)); + nm_assert(lookup); + nm_assert(NM_IN_SET(obj_type, NMP_OBJECT_TYPE_ROUTING_RULE)); - if (addr_family == AF_UNSPEC) - return nmp_lookup_init_obj_type (lookup, obj_type); + if (addr_family == AF_UNSPEC) + return nmp_lookup_init_obj_type(lookup, obj_type); - nm_assert_addr_family (addr_family); - o = _nmp_object_stackinit_from_type (&lookup->selector_obj, obj_type); - NMP_OBJECT_CAST_ROUTING_RULE (o)->addr_family = addr_family; - lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY; - return _L (lookup); + nm_assert_addr_family(addr_family); + o = _nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type); + NMP_OBJECT_CAST_ROUTING_RULE(o)->addr_family = addr_family; + lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY; + return _L(lookup); } /*****************************************************************************/ GArray * -nmp_cache_lookup_to_array (const NMDedupMultiHeadEntry *head_entry, - NMPObjectType obj_type, - gboolean visible_only) -{ - const NMPClass *klass = nmp_class_from_type (obj_type); - NMDedupMultiIter iter; - const NMPObject *o; - GArray *array; - - g_return_val_if_fail (klass, NULL); - - array = g_array_sized_new (FALSE, FALSE, - klass->sizeof_public, - head_entry ? head_entry->len : 0); - nmp_cache_iter_for_each (&iter, - head_entry, - &o) { - nm_assert (NMP_OBJECT_GET_CLASS (o) == klass); - if ( visible_only - && !nmp_object_is_visible (o)) - continue; - g_array_append_vals (array, &o->object, 1); - } - return array; +nmp_cache_lookup_to_array(const NMDedupMultiHeadEntry *head_entry, + NMPObjectType obj_type, + gboolean visible_only) +{ + const NMPClass * klass = nmp_class_from_type(obj_type); + NMDedupMultiIter iter; + const NMPObject *o; + GArray * array; + + g_return_val_if_fail(klass, NULL); + + array = g_array_sized_new(FALSE, FALSE, klass->sizeof_public, head_entry ? head_entry->len : 0); + nmp_cache_iter_for_each (&iter, head_entry, &o) { + nm_assert(NMP_OBJECT_GET_CLASS(o) == klass); + if (visible_only && !nmp_object_is_visible(o)) + continue; + g_array_append_vals(array, &o->object, 1); + } + return array; } /*****************************************************************************/ const NMPObject * -nmp_cache_lookup_link_full (const NMPCache *cache, - int ifindex, - const char *ifname, - gboolean visible_only, - NMLinkType link_type, - NMPObjectMatchFn match_fn, - gpointer user_data) -{ - NMPObject obj_needle; - const NMPObject *obj; - NMDedupMultiIter iter; - const NMDedupMultiHeadEntry *head_entry; - const NMPlatformLink *link = NULL; - NMPLookup lookup; - - if (ifindex > 0) { - obj = nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&obj_needle, ifindex)); - - if ( !obj - || (visible_only && !nmp_object_is_visible (obj)) - || (link_type != NM_LINK_TYPE_NONE && obj->link.type != link_type) - || (ifname && strcmp (obj->link.name, ifname)) - || (match_fn && !match_fn (obj, user_data))) - return NULL; - return obj; - } else if (!ifname && !match_fn) - return NULL; - else { - const NMPObject *obj_best = NULL; - - if (ifname) { - if (strlen (ifname) >= IFNAMSIZ) - return NULL; - nmp_lookup_init_link_by_ifname (&lookup, ifname); - } else - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK); - - head_entry = nmp_cache_lookup (cache, &lookup); - nmp_cache_iter_for_each_link (&iter, head_entry, &link) { - obj = NMP_OBJECT_UP_CAST (link); - - if (link_type != NM_LINK_TYPE_NONE && obj->link.type != link_type) - continue; - if (visible_only && !nmp_object_is_visible (obj)) - continue; - if (match_fn && !match_fn (obj, user_data)) - continue; - - /* if there are multiple candidates, prefer the visible ones. */ - if ( visible_only - || nmp_object_is_visible (obj)) - return obj; - if (!obj_best) - obj_best = obj; - } - return obj_best; - } +nmp_cache_lookup_link_full(const NMPCache * cache, + int ifindex, + const char * ifname, + gboolean visible_only, + NMLinkType link_type, + NMPObjectMatchFn match_fn, + gpointer user_data) +{ + NMPObject obj_needle; + const NMPObject * obj; + NMDedupMultiIter iter; + const NMDedupMultiHeadEntry *head_entry; + const NMPlatformLink * link = NULL; + NMPLookup lookup; + + if (ifindex > 0) { + obj = nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&obj_needle, ifindex)); + + if (!obj || (visible_only && !nmp_object_is_visible(obj)) + || (link_type != NM_LINK_TYPE_NONE && obj->link.type != link_type) + || (ifname && strcmp(obj->link.name, ifname)) + || (match_fn && !match_fn(obj, user_data))) + return NULL; + return obj; + } else if (!ifname && !match_fn) + return NULL; + else { + const NMPObject *obj_best = NULL; + + if (ifname) { + if (strlen(ifname) >= IFNAMSIZ) + return NULL; + nmp_lookup_init_link_by_ifname(&lookup, ifname); + } else + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); + + head_entry = nmp_cache_lookup(cache, &lookup); + nmp_cache_iter_for_each_link (&iter, head_entry, &link) { + obj = NMP_OBJECT_UP_CAST(link); + + if (link_type != NM_LINK_TYPE_NONE && obj->link.type != link_type) + continue; + if (visible_only && !nmp_object_is_visible(obj)) + continue; + if (match_fn && !match_fn(obj, user_data)) + continue; + + /* if there are multiple candidates, prefer the visible ones. */ + if (visible_only || nmp_object_is_visible(obj)) + return obj; + if (!obj_best) + obj_best = obj; + } + return obj_best; + } } /*****************************************************************************/ static NMDedupMultiIdxMode -_obj_get_add_mode (const NMPObject *obj) -{ - /* new objects are usually appended to the list. Except for - * addresses, which are prepended during `ip address add`. - * - * Actually, for routes it is more complicated, because depending on - * `ip route append`, `ip route replace`, `ip route prepend`, the object - * will be added at the tail, at the front, or even replace an element - * in the list. However, that is handled separately by nmp_cache_update_netlink_route() - * and of no concern here. */ - if (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), - NMP_OBJECT_TYPE_IP4_ADDRESS, - NMP_OBJECT_TYPE_IP6_ADDRESS)) - return NM_DEDUP_MULTI_IDX_MODE_PREPEND; - return NM_DEDUP_MULTI_IDX_MODE_APPEND; +_obj_get_add_mode(const NMPObject *obj) +{ + /* new objects are usually appended to the list. Except for + * addresses, which are prepended during `ip address add`. + * + * Actually, for routes it is more complicated, because depending on + * `ip route append`, `ip route replace`, `ip route prepend`, the object + * will be added at the tail, at the front, or even replace an element + * in the list. However, that is handled separately by nmp_cache_update_netlink_route() + * and of no concern here. */ + if (NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), + NMP_OBJECT_TYPE_IP4_ADDRESS, + NMP_OBJECT_TYPE_IP6_ADDRESS)) + return NM_DEDUP_MULTI_IDX_MODE_PREPEND; + return NM_DEDUP_MULTI_IDX_MODE_APPEND; } static void -_idxcache_update_order_for_dump (NMPCache *cache, - const NMDedupMultiEntry *entry) +_idxcache_update_order_for_dump(NMPCache *cache, const NMDedupMultiEntry *entry) { - const NMPClass *klass; - const guint8 *i_idx_type; - const NMDedupMultiEntry *entry2; + const NMPClass * klass; + const guint8 * i_idx_type; + const NMDedupMultiEntry *entry2; - nm_dedup_multi_entry_reorder (entry, NULL, TRUE); + nm_dedup_multi_entry_reorder(entry, NULL, TRUE); - klass = NMP_OBJECT_GET_CLASS (entry->obj); - for (i_idx_type = klass->supported_cache_ids; *i_idx_type; i_idx_type++) { - NMPCacheIdType id_type = *i_idx_type; + klass = NMP_OBJECT_GET_CLASS(entry->obj); + for (i_idx_type = klass->supported_cache_ids; *i_idx_type; i_idx_type++) { + NMPCacheIdType id_type = *i_idx_type; - if (id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) - continue; + if (id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) + continue; - entry2 = nm_dedup_multi_index_lookup_obj (cache->multi_idx, - _idx_type_get (cache, id_type), - entry->obj); - if (!entry2) - continue; + entry2 = nm_dedup_multi_index_lookup_obj(cache->multi_idx, + _idx_type_get(cache, id_type), + entry->obj); + if (!entry2) + continue; - nm_assert (entry2 != entry); - nm_assert (entry2->obj == entry->obj); + nm_assert(entry2 != entry); + nm_assert(entry2->obj == entry->obj); - nm_dedup_multi_entry_reorder (entry2, NULL, TRUE); - } + nm_dedup_multi_entry_reorder(entry2, NULL, TRUE); + } } static void -_idxcache_update_other_cache_ids (NMPCache *cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj_old, - const NMPObject *obj_new, - gboolean is_dump) -{ - const NMDedupMultiEntry *entry_new; - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_order; - NMDedupMultiIdxType *idx_type; - - nm_assert (obj_new || obj_old); - nm_assert (!obj_new || NMP_OBJECT_GET_TYPE (obj_new) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert (!obj_old || NMP_OBJECT_GET_TYPE (obj_old) != NMP_OBJECT_TYPE_UNKNOWN); - nm_assert (!obj_old || !obj_new || NMP_OBJECT_GET_CLASS (obj_new) == NMP_OBJECT_GET_CLASS (obj_old)); - nm_assert (!obj_old || !obj_new || !nmp_object_equal (obj_new, obj_old)); - nm_assert (!obj_new || obj_new == nm_dedup_multi_index_obj_find (cache->multi_idx, obj_new)); - nm_assert (!obj_old || obj_old == nm_dedup_multi_index_obj_find (cache->multi_idx, obj_old)); - - idx_type = _idx_type_get (cache, cache_id_type); - - if (obj_old) { - entry_old = nm_dedup_multi_index_lookup_obj (cache->multi_idx, - idx_type, - obj_old); - if (!obj_new) { - if (entry_old) - nm_dedup_multi_index_remove_entry (cache->multi_idx, entry_old); - return; - } - } else - entry_old = NULL; - - if (obj_new) { - if ( obj_old - && nm_dedup_multi_idx_type_id_equal (idx_type, obj_old, obj_new) - && nm_dedup_multi_idx_type_partition_equal (idx_type, obj_old, obj_new)) { - /* optimize. We just looked up the @obj_old entry and @obj_new compares equal - * according to idx_obj_id_equal(). entry_new is the same as entry_old. */ - entry_new = entry_old; - } else { - entry_new = nm_dedup_multi_index_lookup_obj (cache->multi_idx, - idx_type, - obj_new); - } - - if (entry_new) - entry_order = entry_new; - else if ( entry_old - && nm_dedup_multi_idx_type_partition_equal (idx_type, entry_old->obj, obj_new)) - entry_order = entry_old; - else - entry_order = NULL; - nm_dedup_multi_index_add_full (cache->multi_idx, - idx_type, - obj_new, - is_dump - ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE - : _obj_get_add_mode (obj_new), - is_dump - ? NULL - : entry_order, - entry_new ?: NM_DEDUP_MULTI_ENTRY_MISSING, - entry_new ? entry_new->head : (entry_order ? entry_order->head : NULL), - &entry_new, - NULL); +_idxcache_update_other_cache_ids(NMPCache * cache, + NMPCacheIdType cache_id_type, + const NMPObject *obj_old, + const NMPObject *obj_new, + gboolean is_dump) +{ + const NMDedupMultiEntry *entry_new; + const NMDedupMultiEntry *entry_old; + const NMDedupMultiEntry *entry_order; + NMDedupMultiIdxType * idx_type; + + nm_assert(obj_new || obj_old); + nm_assert(!obj_new || NMP_OBJECT_GET_TYPE(obj_new) != NMP_OBJECT_TYPE_UNKNOWN); + nm_assert(!obj_old || NMP_OBJECT_GET_TYPE(obj_old) != NMP_OBJECT_TYPE_UNKNOWN); + nm_assert(!obj_old || !obj_new + || NMP_OBJECT_GET_CLASS(obj_new) == NMP_OBJECT_GET_CLASS(obj_old)); + nm_assert(!obj_old || !obj_new || !nmp_object_equal(obj_new, obj_old)); + nm_assert(!obj_new || obj_new == nm_dedup_multi_index_obj_find(cache->multi_idx, obj_new)); + nm_assert(!obj_old || obj_old == nm_dedup_multi_index_obj_find(cache->multi_idx, obj_old)); + + idx_type = _idx_type_get(cache, cache_id_type); + + if (obj_old) { + entry_old = nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type, obj_old); + if (!obj_new) { + if (entry_old) + nm_dedup_multi_index_remove_entry(cache->multi_idx, entry_old); + return; + } + } else + entry_old = NULL; + + if (obj_new) { + if (obj_old && nm_dedup_multi_idx_type_id_equal(idx_type, obj_old, obj_new) + && nm_dedup_multi_idx_type_partition_equal(idx_type, obj_old, obj_new)) { + /* optimize. We just looked up the @obj_old entry and @obj_new compares equal + * according to idx_obj_id_equal(). entry_new is the same as entry_old. */ + entry_new = entry_old; + } else { + entry_new = nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type, obj_new); + } + + if (entry_new) + entry_order = entry_new; + else if (entry_old + && nm_dedup_multi_idx_type_partition_equal(idx_type, entry_old->obj, obj_new)) + entry_order = entry_old; + else + entry_order = NULL; + nm_dedup_multi_index_add_full( + cache->multi_idx, + idx_type, + obj_new, + is_dump ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE : _obj_get_add_mode(obj_new), + is_dump ? NULL : entry_order, + entry_new ?: NM_DEDUP_MULTI_ENTRY_MISSING, + entry_new ? entry_new->head : (entry_order ? entry_order->head : NULL), + &entry_new, + NULL); #if NM_MORE_ASSERTS - if (entry_new) { - nm_assert (idx_type->klass->idx_obj_partitionable); - nm_assert (idx_type->klass->idx_obj_partition_equal); - nm_assert (idx_type->klass->idx_obj_partitionable (idx_type, entry_new->obj)); - nm_assert (idx_type->klass->idx_obj_partition_equal (idx_type, (gpointer) obj_new, entry_new->obj)); - } + if (entry_new) { + nm_assert(idx_type->klass->idx_obj_partitionable); + nm_assert(idx_type->klass->idx_obj_partition_equal); + nm_assert(idx_type->klass->idx_obj_partitionable(idx_type, entry_new->obj)); + nm_assert(idx_type->klass->idx_obj_partition_equal(idx_type, + (gpointer) obj_new, + entry_new->obj)); + } #endif - } else - entry_new = NULL; + } else + entry_new = NULL; - if ( entry_old - && entry_old != entry_new) - nm_dedup_multi_index_remove_entry (cache->multi_idx, entry_old); + if (entry_old && entry_old != entry_new) + nm_dedup_multi_index_remove_entry(cache->multi_idx, entry_old); } static void -_idxcache_update (NMPCache *cache, - const NMDedupMultiEntry *entry_old, - NMPObject *obj_new, - gboolean is_dump, - const NMDedupMultiEntry **out_entry_new) -{ - const NMPClass *klass; - const guint8 *i_idx_type; - NMDedupMultiIdxType *idx_type_o = _idx_type_get (cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE); - const NMDedupMultiEntry *entry_new = NULL; - nm_auto_nmpobj const NMPObject *obj_old = NULL; - - /* we update an object in the cache. - * - * Note that @entry_old MUST be what is currently tracked in multi_idx, and it must - * have the same ID as @obj_new. */ - - nm_assert (cache); - nm_assert (entry_old || obj_new); - nm_assert (!obj_new || nmp_object_is_alive (obj_new)); - nm_assert (!entry_old || entry_old == nm_dedup_multi_index_lookup_obj (cache->multi_idx, idx_type_o, entry_old->obj)); - nm_assert (!obj_new || entry_old == nm_dedup_multi_index_lookup_obj (cache->multi_idx, idx_type_o, obj_new)); - nm_assert (!entry_old || entry_old->head->idx_type == idx_type_o); - nm_assert ( !entry_old - || !obj_new - || nm_dedup_multi_idx_type_partition_equal (idx_type_o, entry_old->obj, obj_new)); - nm_assert ( !entry_old - || !obj_new - || nm_dedup_multi_idx_type_id_equal (idx_type_o, entry_old->obj, obj_new)); - nm_assert ( !entry_old - || !obj_new - || ( obj_new->parent.klass == ((const NMPObject *) entry_old->obj)->parent.klass - && !obj_new->parent.klass->obj_full_equal ((NMDedupMultiObj *) obj_new, entry_old->obj))); - - /* keep a reference to the pre-existing entry */ - if (entry_old) - obj_old = nmp_object_ref (entry_old->obj); - - /* first update the main index NMP_CACHE_ID_TYPE_OBJECT_TYPE. - * We already know the pre-existing @entry old, so all that - * nm_dedup_multi_index_add_full() effectively does, is update the - * obj reference. - * - * We also get the new boxed object, which we need below. */ - if (obj_new) { - nm_auto_nmpobj NMPObject *obj_old2 = NULL; - - nm_dedup_multi_index_add_full (cache->multi_idx, - idx_type_o, - obj_new, - is_dump - ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE - : _obj_get_add_mode (obj_new), - NULL, - entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING, - NULL, - &entry_new, - (const NMDedupMultiObj **) &obj_old2); - nm_assert (entry_new); - nm_assert (obj_old == obj_old2); - nm_assert (!entry_old || entry_old == entry_new); - } else - nm_dedup_multi_index_remove_entry (cache->multi_idx, entry_old); - - /* now update all other indexes. We know the previously boxed entry, and the - * newly boxed one. */ - klass = NMP_OBJECT_GET_CLASS (entry_new ? entry_new->obj : obj_old); - for (i_idx_type = klass->supported_cache_ids; *i_idx_type; i_idx_type++) { - NMPCacheIdType id_type = *i_idx_type; - - if (id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) - continue; - _idxcache_update_other_cache_ids (cache, id_type, - obj_old, - entry_new ? entry_new->obj : NULL, - is_dump); - } - - NM_SET_OUT (out_entry_new, entry_new); +_idxcache_update(NMPCache * cache, + const NMDedupMultiEntry * entry_old, + NMPObject * obj_new, + gboolean is_dump, + const NMDedupMultiEntry **out_entry_new) +{ + const NMPClass * klass; + const guint8 * i_idx_type; + NMDedupMultiIdxType * idx_type_o = _idx_type_get(cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE); + const NMDedupMultiEntry *entry_new = NULL; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + + /* we update an object in the cache. + * + * Note that @entry_old MUST be what is currently tracked in multi_idx, and it must + * have the same ID as @obj_new. */ + + nm_assert(cache); + nm_assert(entry_old || obj_new); + nm_assert(!obj_new || nmp_object_is_alive(obj_new)); + nm_assert( + !entry_old + || entry_old + == nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type_o, entry_old->obj)); + nm_assert(!obj_new + || entry_old + == nm_dedup_multi_index_lookup_obj(cache->multi_idx, idx_type_o, obj_new)); + nm_assert(!entry_old || entry_old->head->idx_type == idx_type_o); + nm_assert(!entry_old || !obj_new + || nm_dedup_multi_idx_type_partition_equal(idx_type_o, entry_old->obj, obj_new)); + nm_assert(!entry_old || !obj_new + || nm_dedup_multi_idx_type_id_equal(idx_type_o, entry_old->obj, obj_new)); + nm_assert(!entry_old || !obj_new + || (obj_new->parent.klass == ((const NMPObject *) entry_old->obj)->parent.klass + && !obj_new->parent.klass->obj_full_equal((NMDedupMultiObj *) obj_new, + entry_old->obj))); + + /* keep a reference to the pre-existing entry */ + if (entry_old) + obj_old = nmp_object_ref(entry_old->obj); + + /* first update the main index NMP_CACHE_ID_TYPE_OBJECT_TYPE. + * We already know the pre-existing @entry old, so all that + * nm_dedup_multi_index_add_full() effectively does, is update the + * obj reference. + * + * We also get the new boxed object, which we need below. */ + if (obj_new) { + nm_auto_nmpobj NMPObject *obj_old2 = NULL; + + nm_dedup_multi_index_add_full(cache->multi_idx, + idx_type_o, + obj_new, + is_dump ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE + : _obj_get_add_mode(obj_new), + NULL, + entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING, + NULL, + &entry_new, + (const NMDedupMultiObj **) &obj_old2); + nm_assert(entry_new); + nm_assert(obj_old == obj_old2); + nm_assert(!entry_old || entry_old == entry_new); + } else + nm_dedup_multi_index_remove_entry(cache->multi_idx, entry_old); + + /* now update all other indexes. We know the previously boxed entry, and the + * newly boxed one. */ + klass = NMP_OBJECT_GET_CLASS(entry_new ? entry_new->obj : obj_old); + for (i_idx_type = klass->supported_cache_ids; *i_idx_type; i_idx_type++) { + NMPCacheIdType id_type = *i_idx_type; + + if (id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) + continue; + _idxcache_update_other_cache_ids(cache, + id_type, + obj_old, + entry_new ? entry_new->obj : NULL, + is_dump); + } + + NM_SET_OUT(out_entry_new, entry_new); } NMPCacheOpsType -nmp_cache_remove (NMPCache *cache, - const NMPObject *obj_needle, - gboolean equals_by_ptr, - gboolean only_dirty, - const NMPObject **out_obj_old) +nmp_cache_remove(NMPCache * cache, + const NMPObject * obj_needle, + gboolean equals_by_ptr, + gboolean only_dirty, + const NMPObject **out_obj_old) { - const NMDedupMultiEntry *entry_old; - const NMPObject *obj_old; + const NMDedupMultiEntry *entry_old; + const NMPObject * obj_old; - entry_old = _lookup_entry (cache, obj_needle); + entry_old = _lookup_entry(cache, obj_needle); - if (!entry_old) { - NM_SET_OUT (out_obj_old, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } + if (!entry_old) { + NM_SET_OUT(out_obj_old, NULL); + return NMP_CACHE_OPS_UNCHANGED; + } - obj_old = entry_old->obj; + obj_old = entry_old->obj; - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); - if ( equals_by_ptr - && obj_old != obj_needle) { - /* We found an identical object, but we only delete it if it's the same pointer as - * @obj_needle. */ - return NMP_CACHE_OPS_UNCHANGED; - } - if ( only_dirty - && !entry_old->dirty) { - /* the entry is not dirty. Skip. */ - return NMP_CACHE_OPS_UNCHANGED; - } - _idxcache_update (cache, entry_old, NULL, FALSE, NULL); - return NMP_CACHE_OPS_REMOVED; + if (equals_by_ptr && obj_old != obj_needle) { + /* We found an identical object, but we only delete it if it's the same pointer as + * @obj_needle. */ + return NMP_CACHE_OPS_UNCHANGED; + } + if (only_dirty && !entry_old->dirty) { + /* the entry is not dirty. Skip. */ + return NMP_CACHE_OPS_UNCHANGED; + } + _idxcache_update(cache, entry_old, NULL, FALSE, NULL); + return NMP_CACHE_OPS_REMOVED; } NMPCacheOpsType -nmp_cache_remove_netlink (NMPCache *cache, - const NMPObject *obj_needle, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new) -{ - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new = NULL; - const NMPObject *obj_old; - nm_auto_nmpobj NMPObject *obj_new = NULL; - - entry_old = _lookup_entry (cache, obj_needle); - - if (!entry_old) { - NM_SET_OUT (out_obj_old, NULL); - NM_SET_OUT (out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - obj_old = entry_old->obj; - - if (NMP_OBJECT_GET_TYPE (obj_needle) == NMP_OBJECT_TYPE_LINK) { - /* For nmp_cache_remove_netlink() we have an incomplete @obj_needle instance to be - * removed from netlink. Link objects are alive without being in netlink when they - * have a udev-device. All we want to do in this case is clear the netlink.is_in_netlink - * flag. */ - - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); - - if (!obj_old->_link.netlink.is_in_netlink) { - nm_assert (obj_old->_link.udev.device); - NM_SET_OUT (out_obj_new, nmp_object_ref (obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - - if (!obj_old->_link.udev.device) { - /* the update would make @obj_old invalid. Remove it. */ - _idxcache_update (cache, entry_old, NULL, FALSE, NULL); - NM_SET_OUT (out_obj_new, NULL); - return NMP_CACHE_OPS_REMOVED; - } - - obj_new = nmp_object_clone (obj_old, FALSE); - obj_new->_link.netlink.is_in_netlink = FALSE; - - _nmp_object_fixup_link_master_connected (&obj_new, NULL, cache); - _nmp_object_fixup_link_udev_fields (&obj_new, NULL, cache->use_udev); - - _idxcache_update (cache, - entry_old, - obj_new, - FALSE, - &entry_new); - NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; - } - - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); - NM_SET_OUT (out_obj_new, NULL); - _idxcache_update (cache, entry_old, NULL, FALSE, NULL); - return NMP_CACHE_OPS_REMOVED; +nmp_cache_remove_netlink(NMPCache * cache, + const NMPObject * obj_needle, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new) +{ + const NMDedupMultiEntry *entry_old; + const NMDedupMultiEntry *entry_new = NULL; + const NMPObject * obj_old; + nm_auto_nmpobj NMPObject *obj_new = NULL; + + entry_old = _lookup_entry(cache, obj_needle); + + if (!entry_old) { + NM_SET_OUT(out_obj_old, NULL); + NM_SET_OUT(out_obj_new, NULL); + return NMP_CACHE_OPS_UNCHANGED; + } + + obj_old = entry_old->obj; + + if (NMP_OBJECT_GET_TYPE(obj_needle) == NMP_OBJECT_TYPE_LINK) { + /* For nmp_cache_remove_netlink() we have an incomplete @obj_needle instance to be + * removed from netlink. Link objects are alive without being in netlink when they + * have a udev-device. All we want to do in this case is clear the netlink.is_in_netlink + * flag. */ + + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); + + if (!obj_old->_link.netlink.is_in_netlink) { + nm_assert(obj_old->_link.udev.device); + NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); + return NMP_CACHE_OPS_UNCHANGED; + } + + if (!obj_old->_link.udev.device) { + /* the update would make @obj_old invalid. Remove it. */ + _idxcache_update(cache, entry_old, NULL, FALSE, NULL); + NM_SET_OUT(out_obj_new, NULL); + return NMP_CACHE_OPS_REMOVED; + } + + obj_new = nmp_object_clone(obj_old, FALSE); + obj_new->_link.netlink.is_in_netlink = FALSE; + + _nmp_object_fixup_link_master_connected(&obj_new, NULL, cache); + _nmp_object_fixup_link_udev_fields(&obj_new, NULL, cache->use_udev); + + _idxcache_update(cache, entry_old, obj_new, FALSE, &entry_new); + NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); + return NMP_CACHE_OPS_UPDATED; + } + + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); + NM_SET_OUT(out_obj_new, NULL); + _idxcache_update(cache, entry_old, NULL, FALSE, NULL); + return NMP_CACHE_OPS_REMOVED; } /** @@ -2578,801 +2649,809 @@ nmp_cache_remove_netlink (NMPCache *cache, * and @out_obj_new will be set accordingly. **/ NMPCacheOpsType -nmp_cache_update_netlink (NMPCache *cache, - NMPObject *obj_hand_over, - gboolean is_dump, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new) -{ - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new; - const NMPObject *obj_old; - gboolean is_alive; - - nm_assert (cache); - nm_assert (NMP_OBJECT_IS_VALID (obj_hand_over)); - nm_assert (!NMP_OBJECT_IS_STACKINIT (obj_hand_over)); - /* A link object from netlink must have the udev related fields unset. - * We could implement to handle that, but there is no need to support such - * a use-case */ - nm_assert (NMP_OBJECT_GET_TYPE (obj_hand_over) != NMP_OBJECT_TYPE_LINK || - ( !obj_hand_over->_link.udev.device - && !obj_hand_over->link.driver)); - nm_assert (nm_dedup_multi_index_obj_find (cache->multi_idx, obj_hand_over) != obj_hand_over); - - entry_old = _lookup_entry (cache, obj_hand_over); - - if (!entry_old) { - - NM_SET_OUT (out_obj_old, NULL); - - if (!nmp_object_is_alive (obj_hand_over)) { - NM_SET_OUT (out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - if (NMP_OBJECT_GET_TYPE (obj_hand_over) == NMP_OBJECT_TYPE_LINK) { - _nmp_object_fixup_link_master_connected (&obj_hand_over, NULL, cache); - _nmp_object_fixup_link_udev_fields (&obj_hand_over, NULL, cache->use_udev); - } - - _idxcache_update (cache, - entry_old, - obj_hand_over, - is_dump, - &entry_new); - NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj)); - return NMP_CACHE_OPS_ADDED; - } - - obj_old = entry_old->obj; - - if (NMP_OBJECT_GET_TYPE (obj_hand_over) == NMP_OBJECT_TYPE_LINK) { - if (!obj_hand_over->_link.netlink.is_in_netlink) { - if (!obj_old->_link.netlink.is_in_netlink) { - nm_assert (obj_old->_link.udev.device); - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); - NM_SET_OUT (out_obj_new, nmp_object_ref (obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - if (obj_old->_link.udev.device) { - /* @obj_hand_over is not in netlink. - * - * This is similar to nmp_cache_remove_netlink(), but there we preserve the - * preexisting netlink properties. The use case of that is when kernel_get_object() - * cannot load an object (based on the id of a needle). - * - * Here we keep the data provided from @obj_hand_over. The usecase is when receiving - * a valid @obj_hand_over instance from netlink with RTM_DELROUTE. - */ - is_alive = TRUE; - } else - is_alive = FALSE; - } else - is_alive = TRUE; - - if (is_alive) { - _nmp_object_fixup_link_master_connected (&obj_hand_over, NULL, cache); - - /* Merge the netlink parts with what we have from udev. */ - udev_device_unref (obj_hand_over->_link.udev.device); - obj_hand_over->_link.udev.device = obj_old->_link.udev.device ? udev_device_ref (obj_old->_link.udev.device) : NULL; - _nmp_object_fixup_link_udev_fields (&obj_hand_over, NULL, cache->use_udev); - - if (obj_hand_over->_link.netlink.lnk) { - nm_auto_nmpobj const NMPObject *lnk_old = obj_hand_over->_link.netlink.lnk; - - /* let's dedup/intern the lnk object. */ - obj_hand_over->_link.netlink.lnk = nm_dedup_multi_index_obj_intern (cache->multi_idx, lnk_old); - } - } - } else - is_alive = nmp_object_is_alive (obj_hand_over); - - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); - - if (!is_alive) { - /* the update would make @obj_old invalid. Remove it. */ - _idxcache_update (cache, entry_old, NULL, FALSE, NULL); - NM_SET_OUT (out_obj_new, NULL); - return NMP_CACHE_OPS_REMOVED; - } - - if (nmp_object_equal (obj_old, obj_hand_over)) { - if (is_dump) - _idxcache_update_order_for_dump (cache, entry_old); - nm_dedup_multi_entry_set_dirty (entry_old, FALSE); - NM_SET_OUT (out_obj_new, nmp_object_ref (obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - - _idxcache_update (cache, - entry_old, - obj_hand_over, - is_dump, - &entry_new); - NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; +nmp_cache_update_netlink(NMPCache * cache, + NMPObject * obj_hand_over, + gboolean is_dump, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new) +{ + const NMDedupMultiEntry *entry_old; + const NMDedupMultiEntry *entry_new; + const NMPObject * obj_old; + gboolean is_alive; + + nm_assert(cache); + nm_assert(NMP_OBJECT_IS_VALID(obj_hand_over)); + nm_assert(!NMP_OBJECT_IS_STACKINIT(obj_hand_over)); + /* A link object from netlink must have the udev related fields unset. + * We could implement to handle that, but there is no need to support such + * a use-case */ + nm_assert(NMP_OBJECT_GET_TYPE(obj_hand_over) != NMP_OBJECT_TYPE_LINK + || (!obj_hand_over->_link.udev.device && !obj_hand_over->link.driver)); + nm_assert(nm_dedup_multi_index_obj_find(cache->multi_idx, obj_hand_over) != obj_hand_over); + + entry_old = _lookup_entry(cache, obj_hand_over); + + if (!entry_old) { + NM_SET_OUT(out_obj_old, NULL); + + if (!nmp_object_is_alive(obj_hand_over)) { + NM_SET_OUT(out_obj_new, NULL); + return NMP_CACHE_OPS_UNCHANGED; + } + + if (NMP_OBJECT_GET_TYPE(obj_hand_over) == NMP_OBJECT_TYPE_LINK) { + _nmp_object_fixup_link_master_connected(&obj_hand_over, NULL, cache); + _nmp_object_fixup_link_udev_fields(&obj_hand_over, NULL, cache->use_udev); + } + + _idxcache_update(cache, entry_old, obj_hand_over, is_dump, &entry_new); + NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); + return NMP_CACHE_OPS_ADDED; + } + + obj_old = entry_old->obj; + + if (NMP_OBJECT_GET_TYPE(obj_hand_over) == NMP_OBJECT_TYPE_LINK) { + if (!obj_hand_over->_link.netlink.is_in_netlink) { + if (!obj_old->_link.netlink.is_in_netlink) { + nm_assert(obj_old->_link.udev.device); + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); + NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); + return NMP_CACHE_OPS_UNCHANGED; + } + if (obj_old->_link.udev.device) { + /* @obj_hand_over is not in netlink. + * + * This is similar to nmp_cache_remove_netlink(), but there we preserve the + * preexisting netlink properties. The use case of that is when kernel_get_object() + * cannot load an object (based on the id of a needle). + * + * Here we keep the data provided from @obj_hand_over. The usecase is when receiving + * a valid @obj_hand_over instance from netlink with RTM_DELROUTE. + */ + is_alive = TRUE; + } else + is_alive = FALSE; + } else + is_alive = TRUE; + + if (is_alive) { + _nmp_object_fixup_link_master_connected(&obj_hand_over, NULL, cache); + + /* Merge the netlink parts with what we have from udev. */ + udev_device_unref(obj_hand_over->_link.udev.device); + obj_hand_over->_link.udev.device = + obj_old->_link.udev.device ? udev_device_ref(obj_old->_link.udev.device) : NULL; + _nmp_object_fixup_link_udev_fields(&obj_hand_over, NULL, cache->use_udev); + + if (obj_hand_over->_link.netlink.lnk) { + nm_auto_nmpobj const NMPObject *lnk_old = obj_hand_over->_link.netlink.lnk; + + /* let's dedup/intern the lnk object. */ + obj_hand_over->_link.netlink.lnk = + nm_dedup_multi_index_obj_intern(cache->multi_idx, lnk_old); + } + } + } else + is_alive = nmp_object_is_alive(obj_hand_over); + + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); + + if (!is_alive) { + /* the update would make @obj_old invalid. Remove it. */ + _idxcache_update(cache, entry_old, NULL, FALSE, NULL); + NM_SET_OUT(out_obj_new, NULL); + return NMP_CACHE_OPS_REMOVED; + } + + if (nmp_object_equal(obj_old, obj_hand_over)) { + if (is_dump) + _idxcache_update_order_for_dump(cache, entry_old); + nm_dedup_multi_entry_set_dirty(entry_old, FALSE); + NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); + return NMP_CACHE_OPS_UNCHANGED; + } + + _idxcache_update(cache, entry_old, obj_hand_over, is_dump, &entry_new); + NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); + return NMP_CACHE_OPS_UPDATED; } NMPCacheOpsType -nmp_cache_update_netlink_route (NMPCache *cache, - NMPObject *obj_hand_over, - gboolean is_dump, - guint16 nlmsgflags, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new, - const NMPObject **out_obj_replace, - gboolean *out_resync_required) -{ - NMDedupMultiIter iter; - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new; - const NMDedupMultiEntry *entry_cur; - const NMDedupMultiEntry *entry_replace; - const NMDedupMultiHeadEntry *head_entry; - gboolean is_alive; - NMPCacheOpsType ops_type = NMP_CACHE_OPS_UNCHANGED; - gboolean resync_required; - - nm_assert (cache); - nm_assert (NMP_OBJECT_IS_VALID (obj_hand_over)); - nm_assert (!NMP_OBJECT_IS_STACKINIT (obj_hand_over)); - /* A link object from netlink must have the udev related fields unset. - * We could implement to handle that, but there is no need to support such - * a use-case */ - nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_hand_over), NMP_OBJECT_TYPE_IP4_ROUTE, - NMP_OBJECT_TYPE_IP6_ROUTE)); - nm_assert (nm_dedup_multi_index_obj_find (cache->multi_idx, obj_hand_over) != obj_hand_over); - - entry_old = _lookup_entry (cache, obj_hand_over); - entry_new = NULL; - - NM_SET_OUT (out_obj_old, nmp_object_ref (nm_dedup_multi_entry_get_obj (entry_old))); - - if (!entry_old) { - - if (!nmp_object_is_alive (obj_hand_over)) - goto update_done; - - _idxcache_update (cache, - NULL, - obj_hand_over, - is_dump, - &entry_new); - ops_type = NMP_CACHE_OPS_ADDED; - goto update_done; - } - - is_alive = nmp_object_is_alive (obj_hand_over); - - if (!is_alive) { - /* the update would make @entry_old invalid. Remove it. */ - _idxcache_update (cache, entry_old, NULL, FALSE, NULL); - ops_type = NMP_CACHE_OPS_REMOVED; - goto update_done; - } - - if (nmp_object_equal (entry_old->obj, obj_hand_over)) { - if (is_dump) - _idxcache_update_order_for_dump (cache, entry_old); - nm_dedup_multi_entry_set_dirty (entry_old, FALSE); - goto update_done; - } - - _idxcache_update (cache, - entry_old, - obj_hand_over, - is_dump, - &entry_new); - ops_type = NMP_CACHE_OPS_UPDATED; +nmp_cache_update_netlink_route(NMPCache * cache, + NMPObject * obj_hand_over, + gboolean is_dump, + guint16 nlmsgflags, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new, + const NMPObject **out_obj_replace, + gboolean * out_resync_required) +{ + NMDedupMultiIter iter; + const NMDedupMultiEntry * entry_old; + const NMDedupMultiEntry * entry_new; + const NMDedupMultiEntry * entry_cur; + const NMDedupMultiEntry * entry_replace; + const NMDedupMultiHeadEntry *head_entry; + gboolean is_alive; + NMPCacheOpsType ops_type = NMP_CACHE_OPS_UNCHANGED; + gboolean resync_required; + + nm_assert(cache); + nm_assert(NMP_OBJECT_IS_VALID(obj_hand_over)); + nm_assert(!NMP_OBJECT_IS_STACKINIT(obj_hand_over)); + /* A link object from netlink must have the udev related fields unset. + * We could implement to handle that, but there is no need to support such + * a use-case */ + nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_hand_over), + NMP_OBJECT_TYPE_IP4_ROUTE, + NMP_OBJECT_TYPE_IP6_ROUTE)); + nm_assert(nm_dedup_multi_index_obj_find(cache->multi_idx, obj_hand_over) != obj_hand_over); + + entry_old = _lookup_entry(cache, obj_hand_over); + entry_new = NULL; + + NM_SET_OUT(out_obj_old, nmp_object_ref(nm_dedup_multi_entry_get_obj(entry_old))); + + if (!entry_old) { + if (!nmp_object_is_alive(obj_hand_over)) + goto update_done; + + _idxcache_update(cache, NULL, obj_hand_over, is_dump, &entry_new); + ops_type = NMP_CACHE_OPS_ADDED; + goto update_done; + } + + is_alive = nmp_object_is_alive(obj_hand_over); + + if (!is_alive) { + /* the update would make @entry_old invalid. Remove it. */ + _idxcache_update(cache, entry_old, NULL, FALSE, NULL); + ops_type = NMP_CACHE_OPS_REMOVED; + goto update_done; + } + + if (nmp_object_equal(entry_old->obj, obj_hand_over)) { + if (is_dump) + _idxcache_update_order_for_dump(cache, entry_old); + nm_dedup_multi_entry_set_dirty(entry_old, FALSE); + goto update_done; + } + + _idxcache_update(cache, entry_old, obj_hand_over, is_dump, &entry_new); + ops_type = NMP_CACHE_OPS_UPDATED; update_done: - NM_SET_OUT (out_obj_new, nmp_object_ref (nm_dedup_multi_entry_get_obj (entry_new))); - - /* a RTM_GETROUTE event may signal that another object was replaced. - * Find out whether that is the case and return it as @obj_replaced. - * - * Also, fixup the order of @entry_new within NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID - * index. For most parts, we don't care about the order of objects (including routes). - * But NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID we must keep in the correct order, to - * properly find @obj_replaced. */ - resync_required = FALSE; - entry_replace = NULL; - if (is_dump) - goto out; - - if (!entry_new) { - if ( NM_FLAGS_HAS (nlmsgflags, NLM_F_REPLACE) - && nmp_cache_lookup_all (cache, - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - obj_hand_over)) { - /* hm. @obj_hand_over was not added, meaning it was not alive. - * However, we track some other objects with the same weak-id. - * It's unclear what that means. To be sure, resync. */ - resync_required = TRUE; - } - goto out; - } - - /* FIXME: for routes, we only maintain the order correctly for the BY_WEAK_ID - * index. For all other indexes their order becomes messed up. */ - entry_cur = _lookup_entry_with_idx_type (cache, - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - entry_new->obj); - if (!entry_cur) { - nm_assert_not_reached (); - goto out; - } - nm_assert (entry_cur->obj == entry_new->obj); - - head_entry = entry_cur->head; - nm_assert (head_entry == nmp_cache_lookup_all (cache, - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - entry_cur->obj)); - - if (head_entry->len == 1) { - /* there is only one object, and we expect it to be @obj_new. */ - nm_assert (nm_dedup_multi_head_entry_get_idx (head_entry, 0) == entry_cur); - goto out; - } - - switch (nlmsgflags & (NLM_F_REPLACE | NLM_F_EXCL | NLM_F_CREATE | NLM_F_APPEND)) { - case NLM_F_REPLACE: - /* ip route change */ - - /* get the first element (but skip @obj_new). */ - nm_dedup_multi_iter_init (&iter, head_entry); - if (!nm_dedup_multi_iter_next (&iter)) - nm_assert_not_reached (); - if (iter.current == entry_cur) { - if (!nm_dedup_multi_iter_next (&iter)) - nm_assert_not_reached (); - } - entry_replace = iter.current; - - nm_assert ( entry_replace - && entry_cur != entry_replace); - - nm_dedup_multi_entry_reorder (entry_cur, entry_replace, FALSE); - break; - case NLM_F_CREATE | NLM_F_APPEND: - /* ip route append */ - nm_dedup_multi_entry_reorder (entry_cur, NULL, TRUE); - break; - case NLM_F_CREATE: - /* ip route prepend */ - nm_dedup_multi_entry_reorder (entry_cur, NULL, FALSE); - break; - default: - /* this is an unexpected case, probably a bug that we need to handle better. */ - resync_required = TRUE; - break; - } + NM_SET_OUT(out_obj_new, nmp_object_ref(nm_dedup_multi_entry_get_obj(entry_new))); + + /* a RTM_GETROUTE event may signal that another object was replaced. + * Find out whether that is the case and return it as @obj_replaced. + * + * Also, fixup the order of @entry_new within NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID + * index. For most parts, we don't care about the order of objects (including routes). + * But NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID we must keep in the correct order, to + * properly find @obj_replaced. */ + resync_required = FALSE; + entry_replace = NULL; + if (is_dump) + goto out; + + if (!entry_new) { + if (NM_FLAGS_HAS(nlmsgflags, NLM_F_REPLACE) + && nmp_cache_lookup_all(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, obj_hand_over)) { + /* hm. @obj_hand_over was not added, meaning it was not alive. + * However, we track some other objects with the same weak-id. + * It's unclear what that means. To be sure, resync. */ + resync_required = TRUE; + } + goto out; + } + + /* FIXME: for routes, we only maintain the order correctly for the BY_WEAK_ID + * index. For all other indexes their order becomes messed up. */ + entry_cur = + _lookup_entry_with_idx_type(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, entry_new->obj); + if (!entry_cur) { + nm_assert_not_reached(); + goto out; + } + nm_assert(entry_cur->obj == entry_new->obj); + + head_entry = entry_cur->head; + nm_assert(head_entry + == nmp_cache_lookup_all(cache, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, entry_cur->obj)); + + if (head_entry->len == 1) { + /* there is only one object, and we expect it to be @obj_new. */ + nm_assert(nm_dedup_multi_head_entry_get_idx(head_entry, 0) == entry_cur); + goto out; + } + + switch (nlmsgflags & (NLM_F_REPLACE | NLM_F_EXCL | NLM_F_CREATE | NLM_F_APPEND)) { + case NLM_F_REPLACE: + /* ip route change */ + + /* get the first element (but skip @obj_new). */ + nm_dedup_multi_iter_init(&iter, head_entry); + if (!nm_dedup_multi_iter_next(&iter)) + nm_assert_not_reached(); + if (iter.current == entry_cur) { + if (!nm_dedup_multi_iter_next(&iter)) + nm_assert_not_reached(); + } + entry_replace = iter.current; + + nm_assert(entry_replace && entry_cur != entry_replace); + + nm_dedup_multi_entry_reorder(entry_cur, entry_replace, FALSE); + break; + case NLM_F_CREATE | NLM_F_APPEND: + /* ip route append */ + nm_dedup_multi_entry_reorder(entry_cur, NULL, TRUE); + break; + case NLM_F_CREATE: + /* ip route prepend */ + nm_dedup_multi_entry_reorder(entry_cur, NULL, FALSE); + break; + default: + /* this is an unexpected case, probably a bug that we need to handle better. */ + resync_required = TRUE; + break; + } out: - NM_SET_OUT (out_obj_replace, nmp_object_ref (nm_dedup_multi_entry_get_obj (entry_replace))); - NM_SET_OUT (out_resync_required, resync_required); - return ops_type; + NM_SET_OUT(out_obj_replace, nmp_object_ref(nm_dedup_multi_entry_get_obj(entry_replace))); + NM_SET_OUT(out_resync_required, resync_required); + return ops_type; } NMPCacheOpsType -nmp_cache_update_link_udev (NMPCache *cache, - int ifindex, - struct udev_device *udevice, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new) -{ - const NMPObject *obj_old; - nm_auto_nmpobj NMPObject *obj_new = NULL; - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new; - - entry_old = nmp_cache_lookup_entry_link (cache, ifindex); - - if (!entry_old) { - if (!udevice) { - NM_SET_OUT (out_obj_old, NULL); - NM_SET_OUT (out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } - - obj_new = nmp_object_new (NMP_OBJECT_TYPE_LINK, NULL); - obj_new->link.ifindex = ifindex; - obj_new->_link.udev.device = udev_device_ref (udevice); - - _nmp_object_fixup_link_udev_fields (&obj_new, NULL, cache->use_udev); - - _idxcache_update (cache, - NULL, - obj_new, - FALSE, - &entry_new); - NM_SET_OUT (out_obj_old, NULL); - NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj)); - return NMP_CACHE_OPS_ADDED; - } else { - obj_old = entry_old->obj; - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); - - if (obj_old->_link.udev.device == udevice) { - NM_SET_OUT (out_obj_new, nmp_object_ref (obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } - - if (!udevice && !obj_old->_link.netlink.is_in_netlink) { - /* the update would make @obj_old invalid. Remove it. */ - _idxcache_update (cache, entry_old, NULL, FALSE, NULL); - NM_SET_OUT (out_obj_new, NULL); - return NMP_CACHE_OPS_REMOVED; - } - - obj_new = nmp_object_clone (obj_old, FALSE); - - udev_device_unref (obj_new->_link.udev.device); - obj_new->_link.udev.device = udevice ? udev_device_ref (udevice) : NULL; - - _nmp_object_fixup_link_udev_fields (&obj_new, NULL, cache->use_udev); - - _idxcache_update (cache, - entry_old, - obj_new, - FALSE, - &entry_new); - NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; - } +nmp_cache_update_link_udev(NMPCache * cache, + int ifindex, + struct udev_device *udevice, + const NMPObject ** out_obj_old, + const NMPObject ** out_obj_new) +{ + const NMPObject *obj_old; + nm_auto_nmpobj NMPObject *obj_new = NULL; + const NMDedupMultiEntry * entry_old; + const NMDedupMultiEntry * entry_new; + + entry_old = nmp_cache_lookup_entry_link(cache, ifindex); + + if (!entry_old) { + if (!udevice) { + NM_SET_OUT(out_obj_old, NULL); + NM_SET_OUT(out_obj_new, NULL); + return NMP_CACHE_OPS_UNCHANGED; + } + + obj_new = nmp_object_new(NMP_OBJECT_TYPE_LINK, NULL); + obj_new->link.ifindex = ifindex; + obj_new->_link.udev.device = udev_device_ref(udevice); + + _nmp_object_fixup_link_udev_fields(&obj_new, NULL, cache->use_udev); + + _idxcache_update(cache, NULL, obj_new, FALSE, &entry_new); + NM_SET_OUT(out_obj_old, NULL); + NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); + return NMP_CACHE_OPS_ADDED; + } else { + obj_old = entry_old->obj; + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); + + if (obj_old->_link.udev.device == udevice) { + NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); + return NMP_CACHE_OPS_UNCHANGED; + } + + if (!udevice && !obj_old->_link.netlink.is_in_netlink) { + /* the update would make @obj_old invalid. Remove it. */ + _idxcache_update(cache, entry_old, NULL, FALSE, NULL); + NM_SET_OUT(out_obj_new, NULL); + return NMP_CACHE_OPS_REMOVED; + } + + obj_new = nmp_object_clone(obj_old, FALSE); + + udev_device_unref(obj_new->_link.udev.device); + obj_new->_link.udev.device = udevice ? udev_device_ref(udevice) : NULL; + + _nmp_object_fixup_link_udev_fields(&obj_new, NULL, cache->use_udev); + + _idxcache_update(cache, entry_old, obj_new, FALSE, &entry_new); + NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); + return NMP_CACHE_OPS_UPDATED; + } } NMPCacheOpsType -nmp_cache_update_link_master_connected (NMPCache *cache, - int ifindex, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new) +nmp_cache_update_link_master_connected(NMPCache * cache, + int ifindex, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new) { - const NMDedupMultiEntry *entry_old; - const NMDedupMultiEntry *entry_new = NULL; - const NMPObject *obj_old; - nm_auto_nmpobj NMPObject *obj_new = NULL; + const NMDedupMultiEntry *entry_old; + const NMDedupMultiEntry *entry_new = NULL; + const NMPObject * obj_old; + nm_auto_nmpobj NMPObject *obj_new = NULL; - entry_old = nmp_cache_lookup_entry_link (cache, ifindex); + entry_old = nmp_cache_lookup_entry_link(cache, ifindex); - if (!entry_old) { - NM_SET_OUT (out_obj_old, NULL); - NM_SET_OUT (out_obj_new, NULL); - return NMP_CACHE_OPS_UNCHANGED; - } + if (!entry_old) { + NM_SET_OUT(out_obj_old, NULL); + NM_SET_OUT(out_obj_new, NULL); + return NMP_CACHE_OPS_UNCHANGED; + } - obj_old = entry_old->obj; + obj_old = entry_old->obj; - if (!nmp_cache_link_connected_needs_toggle (cache, obj_old, NULL, NULL)) { - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); - NM_SET_OUT (out_obj_new, nmp_object_ref (obj_old)); - return NMP_CACHE_OPS_UNCHANGED; - } + if (!nmp_cache_link_connected_needs_toggle(cache, obj_old, NULL, NULL)) { + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); + NM_SET_OUT(out_obj_new, nmp_object_ref(obj_old)); + return NMP_CACHE_OPS_UNCHANGED; + } - obj_new = nmp_object_clone (obj_old, FALSE); - obj_new->link.connected = !obj_old->link.connected; + obj_new = nmp_object_clone(obj_old, FALSE); + obj_new->link.connected = !obj_old->link.connected; - NM_SET_OUT (out_obj_old, nmp_object_ref (obj_old)); - _idxcache_update (cache, - entry_old, - obj_new, - FALSE, - &entry_new); - NM_SET_OUT (out_obj_new, nmp_object_ref (entry_new->obj)); - return NMP_CACHE_OPS_UPDATED; + NM_SET_OUT(out_obj_old, nmp_object_ref(obj_old)); + _idxcache_update(cache, entry_old, obj_new, FALSE, &entry_new); + NM_SET_OUT(out_obj_new, nmp_object_ref(entry_new->obj)); + return NMP_CACHE_OPS_UPDATED; } /*****************************************************************************/ void -nmp_cache_dirty_set_all_main (NMPCache *cache, - const NMPLookup *lookup) +nmp_cache_dirty_set_all_main(NMPCache *cache, const NMPLookup *lookup) { - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; + const NMDedupMultiHeadEntry *head_entry; + NMDedupMultiIter iter; - nm_assert (cache); - nm_assert (lookup); + nm_assert(cache); + nm_assert(lookup); - head_entry = nmp_cache_lookup (cache, lookup); + head_entry = nmp_cache_lookup(cache, lookup); - nm_dedup_multi_iter_init (&iter, head_entry); - while (nm_dedup_multi_iter_next (&iter)) { - const NMDedupMultiEntry *main_entry; + nm_dedup_multi_iter_init(&iter, head_entry); + while (nm_dedup_multi_iter_next(&iter)) { + const NMDedupMultiEntry *main_entry; - main_entry = nmp_cache_reresolve_main_entry (cache, iter.current, lookup); + main_entry = nmp_cache_reresolve_main_entry(cache, iter.current, lookup); - nm_dedup_multi_entry_set_dirty (main_entry, TRUE); - } + nm_dedup_multi_entry_set_dirty(main_entry, TRUE); + } } /*****************************************************************************/ NMPCache * -nmp_cache_new (NMDedupMultiIndex *multi_idx, gboolean use_udev) +nmp_cache_new(NMDedupMultiIndex *multi_idx, gboolean use_udev) { - NMPCache *cache = g_slice_new0 (NMPCache); - guint i; + NMPCache *cache = g_slice_new0(NMPCache); + guint i; - for (i = NMP_CACHE_ID_TYPE_NONE + 1; i <= NMP_CACHE_ID_TYPE_MAX; i++) - _dedup_multi_idx_type_init ((DedupMultiIdxType *) _idx_type_get (cache, i), i); + for (i = NMP_CACHE_ID_TYPE_NONE + 1; i <= NMP_CACHE_ID_TYPE_MAX; i++) + _dedup_multi_idx_type_init((DedupMultiIdxType *) _idx_type_get(cache, i), i); - cache->multi_idx = nm_dedup_multi_index_ref (multi_idx); + cache->multi_idx = nm_dedup_multi_index_ref(multi_idx); - cache->use_udev = !!use_udev; - return cache; + cache->use_udev = !!use_udev; + return cache; } void -nmp_cache_free (NMPCache *cache) +nmp_cache_free(NMPCache *cache) { - guint i; + guint i; - for (i = NMP_CACHE_ID_TYPE_NONE + 1; i <= NMP_CACHE_ID_TYPE_MAX; i++) - nm_dedup_multi_index_remove_idx (cache->multi_idx, _idx_type_get (cache, i)); + for (i = NMP_CACHE_ID_TYPE_NONE + 1; i <= NMP_CACHE_ID_TYPE_MAX; i++) + nm_dedup_multi_index_remove_idx(cache->multi_idx, _idx_type_get(cache, i)); - nm_dedup_multi_index_unref (cache->multi_idx); + nm_dedup_multi_index_unref(cache->multi_idx); - g_slice_free (NMPCache, cache); + g_slice_free(NMPCache, cache); } /*****************************************************************************/ void -ASSERT_nmp_cache_is_consistent (const NMPCache *cache) -{ -} +nmtst_assert_nmp_cache_is_consistent(const NMPCache *cache) +{} /*****************************************************************************/ +/* below, ensure that addr_family get's automatically initialize to AF_UNSPEC. */ +G_STATIC_ASSERT(AF_UNSPEC == 0); + +typedef const char *(*CmdPlobjToStringFunc)(const NMPlatformObject *obj, char *buf, gsize len); +typedef const char *(*CmdPlobjToStringIdFunc)(const NMPlatformObject *obj, char *buf, gsize len); +typedef void (*CmdPlobjHashUpdateFunc)(const NMPlatformObject *obj, NMHashState *h); +typedef int (*CmdPlobjCmpFunc)(const NMPlatformObject *obj1, const NMPlatformObject *obj2); + const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { - [NMP_OBJECT_TYPE_LINK - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LINK, - .sizeof_data = sizeof (NMPObjectLink), - .sizeof_public = sizeof (NMPlatformLink), - .obj_type_name = "link", - .rtm_gettype = RTM_GETLINK, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK, - .signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED, - .supported_cache_ids = _supported_cache_ids_link, - .cmd_obj_hash_update = _vt_cmd_obj_hash_update_link, - .cmd_obj_cmp = _vt_cmd_obj_cmp_link, - .cmd_obj_copy = _vt_cmd_obj_copy_link, - .cmd_obj_dispose = _vt_cmd_obj_dispose_link, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_link, - .cmd_obj_is_visible = _vt_cmd_obj_is_visible_link, - .cmd_obj_to_string = _vt_cmd_obj_to_string_link, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_link, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_link, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_link, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_link, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_link_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_link_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_link_cmp, - }, - [NMP_OBJECT_TYPE_IP4_ADDRESS - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP4_ADDRESS, - .sizeof_data = sizeof (NMPObjectIP4Address), - .sizeof_public = sizeof (NMPlatformIP4Address), - .obj_type_name = "ip4-address", - .addr_family = AF_INET, - .rtm_gettype = RTM_GETADDR, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, - .signal_type = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_address, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_address, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip4_address, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip4_address, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip4_address, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip4_address_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_ip4_address_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip4_address_cmp, - }, - [NMP_OBJECT_TYPE_IP6_ADDRESS - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS, - .sizeof_data = sizeof (NMPObjectIP6Address), - .sizeof_public = sizeof (NMPlatformIP6Address), - .obj_type_name = "ip6-address", - .addr_family = AF_INET6, - .rtm_gettype = RTM_GETADDR, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, - .signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_address, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_address, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_address, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_address, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip6_address, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip6_address_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_ip6_address_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_address_cmp - }, - [NMP_OBJECT_TYPE_IP4_ROUTE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP4_ROUTE, - .sizeof_data = sizeof (NMPObjectIP4Route), - .sizeof_public = sizeof (NMPlatformIP4Route), - .obj_type_name = "ip4-route", - .addr_family = AF_INET, - .rtm_gettype = RTM_GETROUTE, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, - .signal_type = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_route, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_route, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip4_route, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip4_route, - .cmd_plobj_to_string_id = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip4_route_to_string, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip4_route_to_string, - .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_ip4_route, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip4_route_cmp_full, - }, - [NMP_OBJECT_TYPE_IP6_ROUTE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_IP6_ROUTE, - .sizeof_data = sizeof (NMPObjectIP6Route), - .sizeof_public = sizeof (NMPlatformIP6Route), - .obj_type_name = "ip6-route", - .addr_family = AF_INET6, - .rtm_gettype = RTM_GETROUTE, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, - .signal_type = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, - .supported_cache_ids = _supported_cache_ids_ipx_route, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_route, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_route, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_route, - .cmd_plobj_to_string_id = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip6_route_to_string, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_ip6_route_to_string, - .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_ip6_route, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_route_cmp_full, - }, - [NMP_OBJECT_TYPE_ROUTING_RULE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_ROUTING_RULE, - .sizeof_data = sizeof (NMPObjectRoutingRule), - .sizeof_public = sizeof (NMPlatformRoutingRule), - .obj_type_name = "routing-rule", - .rtm_gettype = RTM_GETRULE, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, - .signal_type = NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED, - .supported_cache_ids = _supported_cache_ids_routing_rules, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_routing_rule, - .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_routing_rule, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_routing_rule, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_routing_rule, - .cmd_plobj_to_string_id = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_routing_rule_to_string, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_routing_rule_to_string, - .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_routing_rule, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_routing_rule_cmp_full, - }, - [NMP_OBJECT_TYPE_QDISC - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_QDISC, - .sizeof_data = sizeof (NMPObjectQdisc), - .sizeof_public = sizeof (NMPlatformQdisc), - .obj_type_name = "qdisc", - .rtm_gettype = RTM_GETQDISC, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_QDISC, - .signal_type = NM_PLATFORM_SIGNAL_QDISC_CHANGED, - .supported_cache_ids = _supported_cache_ids_object, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_qdisc, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_qdisc, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_qdisc, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_qdisc, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_qdisc_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_qdisc_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_qdisc_cmp, - }, - [NMP_OBJECT_TYPE_TFILTER - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_TFILTER, - .sizeof_data = sizeof (NMPObjectTfilter), - .sizeof_public = sizeof (NMPlatformTfilter), - .obj_type_name = "tfilter", - .rtm_gettype = RTM_GETTFILTER, - .signal_type_id = NM_PLATFORM_SIGNAL_ID_TFILTER, - .signal_type = NM_PLATFORM_SIGNAL_TFILTER_CHANGED, - .supported_cache_ids = _supported_cache_ids_object, - .cmd_obj_is_alive = _vt_cmd_obj_is_alive_tfilter, - .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_tfilter, - .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_tfilter, - .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_tfilter, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_tfilter_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_tfilter_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_tfilter_cmp, - }, - [NMP_OBJECT_TYPE_LNK_GRE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_GRE, - .sizeof_data = sizeof (NMPObjectLnkGre), - .sizeof_public = sizeof (NMPlatformLnkGre), - .obj_type_name = "gre", - .lnk_link_type = NM_LINK_TYPE_GRE, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_gre_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp, - }, - [NMP_OBJECT_TYPE_LNK_GRETAP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_GRETAP, - .sizeof_data = sizeof (NMPObjectLnkGre), - .sizeof_public = sizeof (NMPlatformLnkGre), - .obj_type_name = "gretap", - .lnk_link_type = NM_LINK_TYPE_GRETAP, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_gre_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp, - }, - [NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_INFINIBAND, - .sizeof_data = sizeof (NMPObjectLnkInfiniband), - .sizeof_public = sizeof (NMPlatformLnkInfiniband), - .obj_type_name = "infiniband", - .lnk_link_type = NM_LINK_TYPE_INFINIBAND, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_infiniband_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_infiniband_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_infiniband_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IP6TNL - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IP6TNL, - .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), - .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), - .obj_type_name = "ip6tnl", - .lnk_link_type = NM_LINK_TYPE_IP6TNL, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IP6GRE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRE, - .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), - .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), - .obj_type_name = "ip6gre", - .lnk_link_type = NM_LINK_TYPE_IP6GRE, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IP6GRETAP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRETAP, - .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), - .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), - .obj_type_name = "ip6gretap", - .lnk_link_type = NM_LINK_TYPE_IP6GRETAP, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, - }, - [NMP_OBJECT_TYPE_LNK_IPIP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_IPIP, - .sizeof_data = sizeof (NMPObjectLnkIpIp), - .sizeof_public = sizeof (NMPlatformLnkIpIp), - .obj_type_name = "ipip", - .lnk_link_type = NM_LINK_TYPE_IPIP, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ipip_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ipip_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ipip_cmp, - }, - [NMP_OBJECT_TYPE_LNK_MACSEC - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_MACSEC, - .sizeof_data = sizeof (NMPObjectLnkMacsec), - .sizeof_public = sizeof (NMPlatformLnkMacsec), - .obj_type_name = "macsec", - .lnk_link_type = NM_LINK_TYPE_MACSEC, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_macsec_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_macsec_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macsec_cmp, - }, - [NMP_OBJECT_TYPE_LNK_MACVLAN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_MACVLAN, - .sizeof_data = sizeof (NMPObjectLnkMacvlan), - .sizeof_public = sizeof (NMPlatformLnkMacvlan), - .obj_type_name = "macvlan", - .lnk_link_type = NM_LINK_TYPE_MACVLAN, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_macvlan_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_macvlan_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_MACVTAP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_MACVTAP, - .sizeof_data = sizeof (NMPObjectLnkMacvtap), - .sizeof_public = sizeof (NMPlatformLnkMacvlan), - .obj_type_name = "macvtap", - .lnk_link_type = NM_LINK_TYPE_MACVTAP, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_macvlan_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_macvlan_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_SIT - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_SIT, - .sizeof_data = sizeof (NMPObjectLnkSit), - .sizeof_public = sizeof (NMPlatformLnkSit), - .obj_type_name = "sit", - .lnk_link_type = NM_LINK_TYPE_SIT, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_sit_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_sit_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_sit_cmp, - }, - [NMP_OBJECT_TYPE_LNK_TUN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_TUN, - .sizeof_data = sizeof (NMPObjectLnkTun), - .sizeof_public = sizeof (NMPlatformLnkTun), - .obj_type_name = "tun", - .lnk_link_type = NM_LINK_TYPE_TUN, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_tun_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_tun_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_tun_cmp, - }, - [NMP_OBJECT_TYPE_LNK_VLAN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_VLAN, - .sizeof_data = sizeof (NMPObjectLnkVlan), - .sizeof_public = sizeof (NMPlatformLnkVlan), - .obj_type_name = "vlan", - .lnk_link_type = NM_LINK_TYPE_VLAN, - .cmd_obj_hash_update = _vt_cmd_obj_hash_update_lnk_vlan, - .cmd_obj_cmp = _vt_cmd_obj_cmp_lnk_vlan, - .cmd_obj_copy = _vt_cmd_obj_copy_lnk_vlan, - .cmd_obj_dispose = _vt_cmd_obj_dispose_lnk_vlan, - .cmd_obj_to_string = _vt_cmd_obj_to_string_lnk_vlan, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_vlan_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vlan_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_VRF - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_VRF, - .sizeof_data = sizeof (NMPObjectLnkVrf), - .sizeof_public = sizeof (NMPlatformLnkVrf), - .obj_type_name = "vrf", - .lnk_link_type = NM_LINK_TYPE_VRF, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_vrf_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vrf_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vrf_cmp, - }, - - [NMP_OBJECT_TYPE_LNK_VXLAN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_VXLAN, - .sizeof_data = sizeof (NMPObjectLnkVxlan), - .sizeof_public = sizeof (NMPlatformLnkVxlan), - .obj_type_name = "vxlan", - .lnk_link_type = NM_LINK_TYPE_VXLAN, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_vxlan_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vxlan_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vxlan_cmp, - }, - [NMP_OBJECT_TYPE_LNK_WIREGUARD - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), - .obj_type = NMP_OBJECT_TYPE_LNK_WIREGUARD, - .sizeof_data = sizeof (NMPObjectLnkWireGuard), - .sizeof_public = sizeof (NMPlatformLnkWireGuard), - .obj_type_name = "wireguard", - .lnk_link_type = NM_LINK_TYPE_WIREGUARD, - .cmd_obj_hash_update = _vt_cmd_obj_hash_update_lnk_wireguard, - .cmd_obj_cmp = _vt_cmd_obj_cmp_lnk_wireguard, - .cmd_obj_copy = _vt_cmd_obj_copy_lnk_wireguard, - .cmd_obj_dispose = _vt_cmd_obj_dispose_lnk_wireguard, - .cmd_obj_to_string = _vt_cmd_obj_to_string_lnk_wireguard, - .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_wireguard_to_string, - .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_wireguard_hash_update, - .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_wireguard_cmp, - }, + [NMP_OBJECT_TYPE_LINK - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LINK, + .sizeof_data = sizeof(NMPObjectLink), + .sizeof_public = sizeof(NMPlatformLink), + .obj_type_name = "link", + .rtm_gettype = RTM_GETLINK, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK, + .signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED, + .supported_cache_ids = _supported_cache_ids_link, + .cmd_obj_hash_update = _vt_cmd_obj_hash_update_link, + .cmd_obj_cmp = _vt_cmd_obj_cmp_link, + .cmd_obj_copy = _vt_cmd_obj_copy_link, + .cmd_obj_dispose = _vt_cmd_obj_dispose_link, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_link, + .cmd_obj_is_visible = _vt_cmd_obj_is_visible_link, + .cmd_obj_to_string = _vt_cmd_obj_to_string_link, + .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_link, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_link, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_link, + .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_link, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_link_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_link_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_link_cmp, + }, + [NMP_OBJECT_TYPE_IP4_ADDRESS - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_IP4_ADDRESS, + .sizeof_data = sizeof(NMPObjectIP4Address), + .sizeof_public = sizeof(NMPlatformIP4Address), + .obj_type_name = "ip4-address", + .addr_family = AF_INET, + .rtm_gettype = RTM_GETADDR, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, + .signal_type = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + .supported_cache_ids = _supported_cache_ids_ipx_address, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address, + .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_address, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip4_address, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip4_address, + .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip4_address, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip4_address_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_ip4_address_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip4_address_cmp, + }, + [NMP_OBJECT_TYPE_IP6_ADDRESS + - 1] = {.parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS, + .sizeof_data = sizeof(NMPObjectIP6Address), + .sizeof_public = sizeof(NMPlatformIP6Address), + .obj_type_name = "ip6-address", + .addr_family = AF_INET6, + .rtm_gettype = RTM_GETADDR, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, + .signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + .supported_cache_ids = _supported_cache_ids_ipx_address, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address, + .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_address, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_address, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_address, + .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip6_address, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip6_address_to_string, + .cmd_plobj_hash_update = + (CmdPlobjHashUpdateFunc) nm_platform_ip6_address_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip6_address_cmp}, + [NMP_OBJECT_TYPE_IP4_ROUTE - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_IP4_ROUTE, + .sizeof_data = sizeof(NMPObjectIP4Route), + .sizeof_public = sizeof(NMPlatformIP4Route), + .obj_type_name = "ip4-route", + .addr_family = AF_INET, + .rtm_gettype = RTM_GETROUTE, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, + .signal_type = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + .supported_cache_ids = _supported_cache_ids_ipx_route, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, + .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_route, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip4_route, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip4_route, + .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_ip4_route_to_string, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip4_route_to_string, + .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_ip4_route, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip4_route_cmp_full, + }, + [NMP_OBJECT_TYPE_IP6_ROUTE - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_IP6_ROUTE, + .sizeof_data = sizeof(NMPObjectIP6Route), + .sizeof_public = sizeof(NMPlatformIP6Route), + .obj_type_name = "ip6-route", + .addr_family = AF_INET6, + .rtm_gettype = RTM_GETROUTE, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, + .signal_type = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, + .supported_cache_ids = _supported_cache_ids_ipx_route, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route, + .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_route, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_route, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_route, + .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_ip6_route_to_string, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip6_route_to_string, + .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_ip6_route, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip6_route_cmp_full, + }, + [NMP_OBJECT_TYPE_ROUTING_RULE - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_ROUTING_RULE, + .sizeof_data = sizeof(NMPObjectRoutingRule), + .sizeof_public = sizeof(NMPlatformRoutingRule), + .obj_type_name = "routing-rule", + .rtm_gettype = RTM_GETRULE, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_ROUTING_RULE, + .signal_type = NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED, + .supported_cache_ids = _supported_cache_ids_routing_rules, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_routing_rule, + .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_routing_rule, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_routing_rule, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_routing_rule, + .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_routing_rule_to_string, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_routing_rule_to_string, + .cmd_plobj_hash_update = _vt_cmd_plobj_hash_update_routing_rule, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_routing_rule_cmp_full, + }, + [NMP_OBJECT_TYPE_QDISC - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_QDISC, + .sizeof_data = sizeof(NMPObjectQdisc), + .sizeof_public = sizeof(NMPlatformQdisc), + .obj_type_name = "qdisc", + .rtm_gettype = RTM_GETQDISC, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_QDISC, + .signal_type = NM_PLATFORM_SIGNAL_QDISC_CHANGED, + .supported_cache_ids = _supported_cache_ids_object, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_qdisc, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_qdisc, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_qdisc, + .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_qdisc, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_qdisc_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_qdisc_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_qdisc_cmp, + }, + [NMP_OBJECT_TYPE_TFILTER - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_TFILTER, + .sizeof_data = sizeof(NMPObjectTfilter), + .sizeof_public = sizeof(NMPlatformTfilter), + .obj_type_name = "tfilter", + .rtm_gettype = RTM_GETTFILTER, + .signal_type_id = NM_PLATFORM_SIGNAL_ID_TFILTER, + .signal_type = NM_PLATFORM_SIGNAL_TFILTER_CHANGED, + .supported_cache_ids = _supported_cache_ids_object, + .cmd_obj_is_alive = _vt_cmd_obj_is_alive_tfilter, + .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_tfilter, + .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_tfilter, + .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_tfilter, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_tfilter_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_tfilter_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_tfilter_cmp, + }, + [NMP_OBJECT_TYPE_LNK_BRIDGE - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_BRIDGE, + .sizeof_data = sizeof(NMPObjectLnkBridge), + .sizeof_public = sizeof(NMPlatformLnkBridge), + .obj_type_name = "bridge", + .lnk_link_type = NM_LINK_TYPE_BRIDGE, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_bridge_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_bridge_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_bridge_cmp, + }, + [NMP_OBJECT_TYPE_LNK_GRE - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_GRE, + .sizeof_data = sizeof(NMPObjectLnkGre), + .sizeof_public = sizeof(NMPlatformLnkGre), + .obj_type_name = "gre", + .lnk_link_type = NM_LINK_TYPE_GRE, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_gre_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_gre_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_gre_cmp, + }, + [NMP_OBJECT_TYPE_LNK_GRETAP - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_GRETAP, + .sizeof_data = sizeof(NMPObjectLnkGre), + .sizeof_public = sizeof(NMPlatformLnkGre), + .obj_type_name = "gretap", + .lnk_link_type = NM_LINK_TYPE_GRETAP, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_gre_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_gre_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_gre_cmp, + }, + [NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_INFINIBAND, + .sizeof_data = sizeof(NMPObjectLnkInfiniband), + .sizeof_public = sizeof(NMPlatformLnkInfiniband), + .obj_type_name = "infiniband", + .lnk_link_type = NM_LINK_TYPE_INFINIBAND, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_infiniband_to_string, + .cmd_plobj_hash_update = + (CmdPlobjHashUpdateFunc) nm_platform_lnk_infiniband_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_infiniband_cmp, + }, + [NMP_OBJECT_TYPE_LNK_IP6TNL - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_IP6TNL, + .sizeof_data = sizeof(NMPObjectLnkIp6Tnl), + .sizeof_public = sizeof(NMPlatformLnkIp6Tnl), + .obj_type_name = "ip6tnl", + .lnk_link_type = NM_LINK_TYPE_IP6TNL, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ip6tnl_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ip6tnl_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ip6tnl_cmp, + }, + [NMP_OBJECT_TYPE_LNK_IP6GRE - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRE, + .sizeof_data = sizeof(NMPObjectLnkIp6Tnl), + .sizeof_public = sizeof(NMPlatformLnkIp6Tnl), + .obj_type_name = "ip6gre", + .lnk_link_type = NM_LINK_TYPE_IP6GRE, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ip6tnl_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ip6tnl_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ip6tnl_cmp, + }, + [NMP_OBJECT_TYPE_LNK_IP6GRETAP - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRETAP, + .sizeof_data = sizeof(NMPObjectLnkIp6Tnl), + .sizeof_public = sizeof(NMPlatformLnkIp6Tnl), + .obj_type_name = "ip6gretap", + .lnk_link_type = NM_LINK_TYPE_IP6GRETAP, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ip6tnl_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ip6tnl_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ip6tnl_cmp, + }, + [NMP_OBJECT_TYPE_LNK_IPIP - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_IPIP, + .sizeof_data = sizeof(NMPObjectLnkIpIp), + .sizeof_public = sizeof(NMPlatformLnkIpIp), + .obj_type_name = "ipip", + .lnk_link_type = NM_LINK_TYPE_IPIP, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_ipip_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_ipip_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_ipip_cmp, + }, + [NMP_OBJECT_TYPE_LNK_MACSEC - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_MACSEC, + .sizeof_data = sizeof(NMPObjectLnkMacsec), + .sizeof_public = sizeof(NMPlatformLnkMacsec), + .obj_type_name = "macsec", + .lnk_link_type = NM_LINK_TYPE_MACSEC, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_macsec_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_macsec_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_macsec_cmp, + }, + [NMP_OBJECT_TYPE_LNK_MACVLAN - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_MACVLAN, + .sizeof_data = sizeof(NMPObjectLnkMacvlan), + .sizeof_public = sizeof(NMPlatformLnkMacvlan), + .obj_type_name = "macvlan", + .lnk_link_type = NM_LINK_TYPE_MACVLAN, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_macvlan_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_macvlan_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_macvlan_cmp, + }, + [NMP_OBJECT_TYPE_LNK_MACVTAP - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_MACVTAP, + .sizeof_data = sizeof(NMPObjectLnkMacvtap), + .sizeof_public = sizeof(NMPlatformLnkMacvlan), + .obj_type_name = "macvtap", + .lnk_link_type = NM_LINK_TYPE_MACVTAP, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_macvlan_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_macvlan_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_macvlan_cmp, + }, + [NMP_OBJECT_TYPE_LNK_SIT - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_SIT, + .sizeof_data = sizeof(NMPObjectLnkSit), + .sizeof_public = sizeof(NMPlatformLnkSit), + .obj_type_name = "sit", + .lnk_link_type = NM_LINK_TYPE_SIT, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_sit_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_sit_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_sit_cmp, + }, + [NMP_OBJECT_TYPE_LNK_TUN - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_TUN, + .sizeof_data = sizeof(NMPObjectLnkTun), + .sizeof_public = sizeof(NMPlatformLnkTun), + .obj_type_name = "tun", + .lnk_link_type = NM_LINK_TYPE_TUN, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_tun_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_tun_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_tun_cmp, + }, + [NMP_OBJECT_TYPE_LNK_VLAN - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_VLAN, + .sizeof_data = sizeof(NMPObjectLnkVlan), + .sizeof_public = sizeof(NMPlatformLnkVlan), + .obj_type_name = "vlan", + .lnk_link_type = NM_LINK_TYPE_VLAN, + .cmd_obj_hash_update = _vt_cmd_obj_hash_update_lnk_vlan, + .cmd_obj_cmp = _vt_cmd_obj_cmp_lnk_vlan, + .cmd_obj_copy = _vt_cmd_obj_copy_lnk_vlan, + .cmd_obj_dispose = _vt_cmd_obj_dispose_lnk_vlan, + .cmd_obj_to_string = _vt_cmd_obj_to_string_lnk_vlan, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_vlan_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_vlan_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_vlan_cmp, + }, + [NMP_OBJECT_TYPE_LNK_VRF - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_VRF, + .sizeof_data = sizeof(NMPObjectLnkVrf), + .sizeof_public = sizeof(NMPlatformLnkVrf), + .obj_type_name = "vrf", + .lnk_link_type = NM_LINK_TYPE_VRF, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_vrf_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_vrf_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_vrf_cmp, + }, + [NMP_OBJECT_TYPE_LNK_VXLAN - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_VXLAN, + .sizeof_data = sizeof(NMPObjectLnkVxlan), + .sizeof_public = sizeof(NMPlatformLnkVxlan), + .obj_type_name = "vxlan", + .lnk_link_type = NM_LINK_TYPE_VXLAN, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_vxlan_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_vxlan_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_vxlan_cmp, + }, + [NMP_OBJECT_TYPE_LNK_WIREGUARD - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_WIREGUARD, + .sizeof_data = sizeof(NMPObjectLnkWireGuard), + .sizeof_public = sizeof(NMPlatformLnkWireGuard), + .obj_type_name = "wireguard", + .lnk_link_type = NM_LINK_TYPE_WIREGUARD, + .cmd_obj_hash_update = _vt_cmd_obj_hash_update_lnk_wireguard, + .cmd_obj_cmp = _vt_cmd_obj_cmp_lnk_wireguard, + .cmd_obj_copy = _vt_cmd_obj_copy_lnk_wireguard, + .cmd_obj_dispose = _vt_cmd_obj_dispose_lnk_wireguard, + .cmd_obj_to_string = _vt_cmd_obj_to_string_lnk_wireguard, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_wireguard_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_wireguard_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_wireguard_cmp, + }, }; diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 44525ed0..58f54dbe 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ @@ -18,90 +18,86 @@ struct udev_device; /* "struct __kernel_timespec" uses "long long", but we use gint64. In practice, * these are the same types. */ -G_STATIC_ASSERT (sizeof (long long) == sizeof (gint64)); +G_STATIC_ASSERT(sizeof(long long) == sizeof(gint64)); typedef struct { - /* like "struct __kernel_timespec". */ - gint64 tv_sec; - gint64 tv_nsec; + /* like "struct __kernel_timespec". */ + gint64 tv_sec; + gint64 tv_nsec; } NMPTimespec64; /*****************************************************************************/ typedef union { - struct sockaddr sa; - struct sockaddr_in in; - struct sockaddr_in6 in6; + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; } NMSockAddrUnion; #define NM_SOCK_ADDR_UNION_INIT_UNSPEC \ - { \ - .sa = { \ - .sa_family = AF_UNSPEC, \ - }, \ - } + { \ + .sa = { \ + .sa_family = AF_UNSPEC, \ + }, \ + } -int nm_sock_addr_union_cmp (const NMSockAddrUnion *a, - const NMSockAddrUnion *b); +int nm_sock_addr_union_cmp(const NMSockAddrUnion *a, const NMSockAddrUnion *b); -void nm_sock_addr_union_hash_update (const NMSockAddrUnion *a, - NMHashState *h); +void nm_sock_addr_union_hash_update(const NMSockAddrUnion *a, NMHashState *h); -void nm_sock_addr_union_cpy (NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */); +void nm_sock_addr_union_cpy(NMSockAddrUnion *dst, + gconstpointer src /* unaligned (const NMSockAddrUnion *) */); -void nm_sock_addr_union_cpy_untrusted (NMSockAddrUnion *dst, - gconstpointer src /* unaligned (const NMSockAddrUnion *) */, - gsize src_len); +void nm_sock_addr_union_cpy_untrusted(NMSockAddrUnion *dst, + gconstpointer src /* unaligned (const NMSockAddrUnion *) */, + gsize src_len); -const char *nm_sock_addr_union_to_string (const NMSockAddrUnion *sa, - char *buf, - gsize len); +const char *nm_sock_addr_union_to_string(const NMSockAddrUnion *sa, char *buf, gsize len); /*****************************************************************************/ typedef struct { - NMIPAddr addr; - guint8 family; - guint8 mask; + NMIPAddr addr; + guint8 family; + guint8 mask; } NMPWireGuardAllowedIP; typedef struct _NMPWireGuardPeer { - NMSockAddrUnion endpoint; + NMSockAddrUnion endpoint; - NMPTimespec64 last_handshake_time; + NMPTimespec64 last_handshake_time; - guint64 rx_bytes; - guint64 tx_bytes; + guint64 rx_bytes; + guint64 tx_bytes; - union { - const NMPWireGuardAllowedIP *allowed_ips; - guint _construct_idx_start; - }; - union { - guint allowed_ips_len; - guint _construct_idx_end; - }; + union { + const NMPWireGuardAllowedIP *allowed_ips; + guint _construct_idx_start; + }; + union { + guint allowed_ips_len; + guint _construct_idx_end; + }; - guint16 persistent_keepalive_interval; + guint16 persistent_keepalive_interval; - guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; - guint8 preshared_key[NMP_WIREGUARD_SYMMETRIC_KEY_LEN]; + guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN]; + guint8 preshared_key[NMP_WIREGUARD_SYMMETRIC_KEY_LEN]; } NMPWireGuardPeer; /*****************************************************************************/ typedef enum { /*< skip >*/ - NMP_OBJECT_TO_STRING_ID, - NMP_OBJECT_TO_STRING_PUBLIC, - NMP_OBJECT_TO_STRING_ALL, + NMP_OBJECT_TO_STRING_ID, + NMP_OBJECT_TO_STRING_PUBLIC, + NMP_OBJECT_TO_STRING_ALL, } NMPObjectToStringMode; typedef enum { /*< skip >*/ - NMP_CACHE_OPS_UNCHANGED = NM_PLATFORM_SIGNAL_NONE, - NMP_CACHE_OPS_ADDED = NM_PLATFORM_SIGNAL_ADDED, - NMP_CACHE_OPS_UPDATED = NM_PLATFORM_SIGNAL_CHANGED, - NMP_CACHE_OPS_REMOVED = NM_PLATFORM_SIGNAL_REMOVED, + NMP_CACHE_OPS_UNCHANGED = NM_PLATFORM_SIGNAL_NONE, + NMP_CACHE_OPS_ADDED = NM_PLATFORM_SIGNAL_ADDED, + NMP_CACHE_OPS_UPDATED = NM_PLATFORM_SIGNAL_CHANGED, + NMP_CACHE_OPS_REMOVED = NM_PLATFORM_SIGNAL_REMOVED, } NMPCacheOpsType; /* The NMPCacheIdType are the different index types. @@ -121,878 +117,1012 @@ typedef enum { /*< skip >*/ * matching v4/v6 and ifindex -- or maybe not at all if it isn't visible. * */ typedef enum { /*< skip >*/ - NMP_CACHE_ID_TYPE_NONE, - - /* all the objects of a certain type. - * - * This index is special. It is the only one that contains *all* object. - * Other indexes may consider some object as non "partitionable", hence - * they don't track all objects. - * - * Hence, this index type is used when looking at all objects (still - * partitioned by type). - * - * Also, note that links may be considered invisible. This index type - * expose all links, even invisible ones. For addresses/routes, this - * distinction doesn't exist, as all addresses/routes that are alive - * are visible as well. */ - NMP_CACHE_ID_TYPE_OBJECT_TYPE, - - /* index for the link objects by ifname. */ - NMP_CACHE_ID_TYPE_LINK_BY_IFNAME, - - /* indices for the visible default-routes, ignoring ifindex. - * This index only contains two partitions: all visible default-routes, - * separate for IPv4 and IPv6. */ - NMP_CACHE_ID_TYPE_DEFAULT_ROUTES, - - /* all the objects that have an ifindex (by object-type) for an ifindex. */ - NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, - - /* Consider all the destination fields of a route, that is, the ID without the ifindex - * and gateway (meaning: network/plen,metric). - * The reason for this is that `ip route change` can replace an existing route - * and modify its ifindex/gateway. Effectively, that means it deletes an existing - * route and adds a different one (as the ID of the route changes). However, it only - * sends one RTM_NEWADDR notification without notifying about the deletion. We detect - * that by having this index to contain overlapping routes which require special - * cache-resync. */ - NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, - - /* a filter for objects that track an explicit address family. - * - * Note that currently on NMPObjectRoutingRule is indexed by this filter. */ - NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY, - - __NMP_CACHE_ID_TYPE_MAX, - NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1, + NMP_CACHE_ID_TYPE_NONE, + + /* all the objects of a certain type. + * + * This index is special. It is the only one that contains *all* object. + * Other indexes may consider some object as non "partitionable", hence + * they don't track all objects. + * + * Hence, this index type is used when looking at all objects (still + * partitioned by type). + * + * Also, note that links may be considered invisible. This index type + * expose all links, even invisible ones. For addresses/routes, this + * distinction doesn't exist, as all addresses/routes that are alive + * are visible as well. */ + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + + /* index for the link objects by ifname. */ + NMP_CACHE_ID_TYPE_LINK_BY_IFNAME, + + /* indices for the visible default-routes, ignoring ifindex. + * This index only contains two partitions: all visible default-routes, + * separate for IPv4 and IPv6. */ + NMP_CACHE_ID_TYPE_DEFAULT_ROUTES, + + /* all the objects that have an ifindex (by object-type) for an ifindex. */ + NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX, + + /* Consider all the destination fields of a route, that is, the ID without the ifindex + * and gateway (meaning: network/plen,metric). + * The reason for this is that `ip route change` can replace an existing route + * and modify its ifindex/gateway. Effectively, that means it deletes an existing + * route and adds a different one (as the ID of the route changes). However, it only + * sends one RTM_NEWADDR notification without notifying about the deletion. We detect + * that by having this index to contain overlapping routes which require special + * cache-resync. */ + NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, + + /* a filter for objects that track an explicit address family. + * + * Note that currently on NMPObjectRoutingRule is indexed by this filter. */ + NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY, + + __NMP_CACHE_ID_TYPE_MAX, + NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1, } NMPCacheIdType; typedef struct { - NMDedupMultiObjClass parent; - const char *obj_type_name; - int sizeof_data; - int sizeof_public; - NMPObjectType obj_type; - int addr_family; - int rtm_gettype; - NMPlatformSignalIdType signal_type_id; - const char *signal_type; - - const guint8 *supported_cache_ids; - - /* Only for NMPObjectLnk* types. */ - NMLinkType lnk_link_type; - - void (*cmd_obj_hash_update) (const NMPObject *obj, NMHashState *h); - int (*cmd_obj_cmp) (const NMPObject *obj1, const NMPObject *obj2); - void (*cmd_obj_copy) (NMPObject *dst, const NMPObject *src); - void (*cmd_obj_dispose) (NMPObject *obj); - gboolean (*cmd_obj_is_alive) (const NMPObject *obj); - gboolean (*cmd_obj_is_visible) (const NMPObject *obj); - const char *(*cmd_obj_to_string) (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size); - - /* functions that operate on NMPlatformObject */ - void (*cmd_plobj_id_copy) (NMPlatformObject *dst, const NMPlatformObject *src); - int (*cmd_plobj_id_cmp) (const NMPlatformObject *obj1, const NMPlatformObject *obj2); - void (*cmd_plobj_id_hash_update) (const NMPlatformObject *obj, NMHashState *h); - const char *(*cmd_plobj_to_string_id) (const NMPlatformObject *obj, char *buf, gsize buf_size); - const char *(*cmd_plobj_to_string) (const NMPlatformObject *obj, char *buf, gsize len); - void (*cmd_plobj_hash_update) (const NMPlatformObject *obj, NMHashState *h); - int (*cmd_plobj_cmp) (const NMPlatformObject *obj1, const NMPlatformObject *obj2); + NMDedupMultiObjClass parent; + const char * obj_type_name; + const char * signal_type; + const guint8 * supported_cache_ids; + int sizeof_data; + int sizeof_public; + int addr_family; + int rtm_gettype; + NMPObjectType obj_type; + NMPlatformSignalIdType signal_type_id; + + /* Only for NMPObjectLnk* types. */ + NMLinkType lnk_link_type; + + void (*cmd_obj_hash_update)(const NMPObject *obj, NMHashState *h); + int (*cmd_obj_cmp)(const NMPObject *obj1, const NMPObject *obj2); + void (*cmd_obj_copy)(NMPObject *dst, const NMPObject *src); + void (*cmd_obj_dispose)(NMPObject *obj); + gboolean (*cmd_obj_is_alive)(const NMPObject *obj); + gboolean (*cmd_obj_is_visible)(const NMPObject *obj); + const char *(*cmd_obj_to_string)(const NMPObject * obj, + NMPObjectToStringMode to_string_mode, + char * buf, + gsize buf_size); + + /* functions that operate on NMPlatformObject */ + void (*cmd_plobj_id_copy)(NMPlatformObject *dst, const NMPlatformObject *src); + int (*cmd_plobj_id_cmp)(const NMPlatformObject *obj1, const NMPlatformObject *obj2); + void (*cmd_plobj_id_hash_update)(const NMPlatformObject *obj, NMHashState *h); + const char *(*cmd_plobj_to_string_id)(const NMPlatformObject *obj, char *buf, gsize buf_size); + const char *(*cmd_plobj_to_string)(const NMPlatformObject *obj, char *buf, gsize len); + void (*cmd_plobj_hash_update)(const NMPlatformObject *obj, NMHashState *h); + int (*cmd_plobj_cmp)(const NMPlatformObject *obj1, const NMPlatformObject *obj2); } NMPClass; extern const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX]; typedef struct { - NMPlatformLink _public; - - struct { - bool is_in_netlink; - - /* Additional data that depends on the link-type (IFLA_INFO_DATA) */ - const NMPObject *lnk; - } netlink; - - struct { - /* note that "struct udev_device" references the library context - * "struct udev", but doesn't own it. - * - * Hence, the udev.device shall not be used after the library - * context is is destroyed. - * - * In case of NMPObjectLink instances that you obtained from the - * platform cache, that means that you shall no keep references - * to those instances that outlife the NMPlatform instance. - * - * In practice, the requirement is less strict and you'll be even - * fine if the platform instance (and the "struct udev" instance) - * are already destroyed while you still hold onto a reference to - * the NMPObjectLink instance. Just don't make use of udev functions - * that cause access to the udev library context. - */ - struct udev_device *device; - } udev; - - /* Auxiliary data object for Wi-Fi and WPAN */ - GObject *ext_data; - - /* FIXME: not every NMPObjectLink should pay the price for tracking - * the wireguard family id. This should be tracked via ext_data, which - * would be exactly the right place. */ - int wireguard_family_id; + NMPlatformLink _public; + + struct { + bool is_in_netlink; + + /* Additional data that depends on the link-type (IFLA_INFO_DATA) */ + const NMPObject *lnk; + } netlink; + + struct { + /* note that "struct udev_device" references the library context + * "struct udev", but doesn't own it. + * + * Hence, the udev.device shall not be used after the library + * context is destroyed. + * + * In case of NMPObjectLink instances that you obtained from the + * platform cache, that means that you shall no keep references + * to those instances that outlife the NMPlatform instance. + * + * In practice, the requirement is less strict and you'll be even + * fine if the platform instance (and the "struct udev" instance) + * are already destroyed while you still hold onto a reference to + * the NMPObjectLink instance. Just don't make use of udev functions + * that cause access to the udev library context. + */ + struct udev_device *device; + } udev; + + /* Auxiliary data object for Wi-Fi and WPAN */ + GObject *ext_data; + + /* FIXME: not every NMPObjectLink should pay the price for tracking + * the wireguard family id. This should be tracked via ext_data, which + * would be exactly the right place. */ + int wireguard_family_id; } NMPObjectLink; typedef struct { - NMPlatformLnkGre _public; + NMPlatformLnkBridge _public; +} NMPObjectLnkBridge; + +typedef struct { + NMPlatformLnkGre _public; } NMPObjectLnkGre; typedef struct { - NMPlatformLnkInfiniband _public; + NMPlatformLnkInfiniband _public; } NMPObjectLnkInfiniband; typedef struct { - NMPlatformLnkIp6Tnl _public; + NMPlatformLnkIp6Tnl _public; } NMPObjectLnkIp6Tnl; typedef struct { - NMPlatformLnkIpIp _public; + NMPlatformLnkIpIp _public; } NMPObjectLnkIpIp; typedef struct { - NMPlatformLnkMacsec _public; + NMPlatformLnkMacsec _public; } NMPObjectLnkMacsec; typedef struct { - NMPlatformLnkMacvlan _public; + NMPlatformLnkMacvlan _public; } NMPObjectLnkMacvlan; typedef NMPObjectLnkMacvlan NMPObjectLnkMacvtap; typedef struct { - NMPlatformLnkSit _public; + NMPlatformLnkSit _public; } NMPObjectLnkSit; typedef struct { - NMPlatformLnkTun _public; + NMPlatformLnkTun _public; } NMPObjectLnkTun; typedef struct { - NMPlatformLnkVlan _public; + NMPlatformLnkVlan _public; - guint n_ingress_qos_map; - guint n_egress_qos_map; - const NMVlanQosMapping *ingress_qos_map; - const NMVlanQosMapping *egress_qos_map; + guint n_ingress_qos_map; + guint n_egress_qos_map; + const NMVlanQosMapping *ingress_qos_map; + const NMVlanQosMapping *egress_qos_map; } NMPObjectLnkVlan; typedef struct { - NMPlatformLnkVrf _public; + NMPlatformLnkVrf _public; } NMPObjectLnkVrf; typedef struct { - NMPlatformLnkVxlan _public; + NMPlatformLnkVxlan _public; } NMPObjectLnkVxlan; typedef struct { - NMPlatformLnkWireGuard _public; - const NMPWireGuardPeer *peers; - const NMPWireGuardAllowedIP *_allowed_ips_buf; - guint peers_len; - guint _allowed_ips_buf_len; + NMPlatformLnkWireGuard _public; + const NMPWireGuardPeer * peers; + const NMPWireGuardAllowedIP *_allowed_ips_buf; + guint peers_len; + guint _allowed_ips_buf_len; } NMPObjectLnkWireGuard; typedef struct { - NMPlatformIP4Address _public; + NMPlatformIP4Address _public; } NMPObjectIP4Address; typedef struct { - NMPlatformIP4Route _public; + NMPlatformIP4Route _public; } NMPObjectIP4Route; typedef struct { - NMPlatformIP6Address _public; + NMPlatformIP6Address _public; } NMPObjectIP6Address; typedef struct { - NMPlatformIP6Route _public; + NMPlatformIP6Route _public; } NMPObjectIP6Route; typedef struct { - NMPlatformRoutingRule _public; + NMPlatformRoutingRule _public; } NMPObjectRoutingRule; typedef struct { - NMPlatformQdisc _public; + NMPlatformQdisc _public; } NMPObjectQdisc; typedef struct { - NMPlatformTfilter _public; + NMPlatformTfilter _public; } NMPObjectTfilter; struct _NMPObject { - union { - NMDedupMultiObj parent; - const NMPClass *_class; - }; - union { - NMPlatformObject object; + union { + NMDedupMultiObj parent; + const NMPClass *_class; + }; + union { + NMPlatformObject object; - NMPlatformObjWithIfindex obj_with_ifindex; + NMPlatformObjWithIfindex obj_with_ifindex; - NMPlatformLink link; - NMPObjectLink _link; + NMPlatformLink link; + NMPObjectLink _link; - NMPlatformLnkGre lnk_gre; - NMPObjectLnkGre _lnk_gre; + NMPlatformLnkBridge lnk_bridge; + NMPObjectLnkBridge _lnk_bridge; - NMPlatformLnkInfiniband lnk_infiniband; - NMPObjectLnkInfiniband _lnk_infiniband; + NMPlatformLnkGre lnk_gre; + NMPObjectLnkGre _lnk_gre; - NMPlatformLnkIpIp lnk_ipip; - NMPObjectLnkIpIp _lnk_ipip; + NMPlatformLnkInfiniband lnk_infiniband; + NMPObjectLnkInfiniband _lnk_infiniband; - NMPlatformLnkIp6Tnl lnk_ip6tnl; - NMPObjectLnkIp6Tnl _lnk_ip6tnl; + NMPlatformLnkIpIp lnk_ipip; + NMPObjectLnkIpIp _lnk_ipip; - NMPlatformLnkMacsec lnk_macsec; - NMPObjectLnkMacsec _lnk_macsec; + NMPlatformLnkIp6Tnl lnk_ip6tnl; + NMPObjectLnkIp6Tnl _lnk_ip6tnl; - NMPlatformLnkMacvlan lnk_macvlan; - NMPObjectLnkMacvlan _lnk_macvlan; + NMPlatformLnkMacsec lnk_macsec; + NMPObjectLnkMacsec _lnk_macsec; - NMPlatformLnkSit lnk_sit; - NMPObjectLnkSit _lnk_sit; + NMPlatformLnkMacvlan lnk_macvlan; + NMPObjectLnkMacvlan _lnk_macvlan; - NMPlatformLnkTun lnk_tun; - NMPObjectLnkTun _lnk_tun; + NMPlatformLnkSit lnk_sit; + NMPObjectLnkSit _lnk_sit; - NMPlatformLnkVlan lnk_vlan; - NMPObjectLnkVlan _lnk_vlan; + NMPlatformLnkTun lnk_tun; + NMPObjectLnkTun _lnk_tun; - NMPlatformLnkVrf lnk_vrf; - NMPObjectLnkVrf _lnk_vrf; + NMPlatformLnkVlan lnk_vlan; + NMPObjectLnkVlan _lnk_vlan; - NMPlatformLnkVxlan lnk_vxlan; - NMPObjectLnkVxlan _lnk_vxlan; + NMPlatformLnkVrf lnk_vrf; + NMPObjectLnkVrf _lnk_vrf; - NMPlatformLnkWireGuard lnk_wireguard; - NMPObjectLnkWireGuard _lnk_wireguard; + NMPlatformLnkVxlan lnk_vxlan; + NMPObjectLnkVxlan _lnk_vxlan; - NMPlatformIPAddress ip_address; - NMPlatformIPXAddress ipx_address; - NMPlatformIP4Address ip4_address; - NMPlatformIP6Address ip6_address; - NMPObjectIP4Address _ip4_address; - NMPObjectIP6Address _ip6_address; + NMPlatformLnkWireGuard lnk_wireguard; + NMPObjectLnkWireGuard _lnk_wireguard; - NMPlatformIPRoute ip_route; - NMPlatformIPXRoute ipx_route; - NMPlatformIP4Route ip4_route; - NMPlatformIP6Route ip6_route; - NMPObjectIP4Route _ip4_route; - NMPObjectIP6Route _ip6_route; + NMPlatformIPAddress ip_address; + NMPlatformIPXAddress ipx_address; + NMPlatformIP4Address ip4_address; + NMPlatformIP6Address ip6_address; + NMPObjectIP4Address _ip4_address; + NMPObjectIP6Address _ip6_address; - NMPlatformRoutingRule routing_rule; - NMPObjectRoutingRule _routing_rule; + NMPlatformIPRoute ip_route; + NMPlatformIPXRoute ipx_route; + NMPlatformIP4Route ip4_route; + NMPlatformIP6Route ip6_route; + NMPObjectIP4Route _ip4_route; + NMPObjectIP6Route _ip6_route; - NMPlatformQdisc qdisc; - NMPObjectQdisc _qdisc; - NMPlatformTfilter tfilter; - NMPObjectTfilter _tfilter; - }; + NMPlatformRoutingRule routing_rule; + NMPObjectRoutingRule _routing_rule; + + NMPlatformQdisc qdisc; + NMPObjectQdisc _qdisc; + NMPlatformTfilter tfilter; + NMPObjectTfilter _tfilter; + }; }; /*****************************************************************************/ static inline gboolean -NMP_CLASS_IS_VALID (const NMPClass *klass) +NMP_CLASS_IS_VALID(const NMPClass *klass) { - return klass >= &_nmp_classes[0] - && klass <= &_nmp_classes[G_N_ELEMENTS (_nmp_classes)] - && ((((char *) klass) - ((char *) _nmp_classes)) % (sizeof (_nmp_classes[0]))) == 0; + return klass >= &_nmp_classes[0] && klass <= &_nmp_classes[G_N_ELEMENTS(_nmp_classes)] + && ((((char *) klass) - ((char *) _nmp_classes)) % (sizeof(_nmp_classes[0]))) == 0; } static inline const NMPClass * -nmp_class_from_type (NMPObjectType obj_type) +nmp_class_from_type(NMPObjectType obj_type) { - nm_assert (obj_type > 0); - nm_assert (obj_type <= G_N_ELEMENTS (_nmp_classes)); - nm_assert (_nmp_classes[obj_type - 1].obj_type == obj_type); - nm_assert (NMP_CLASS_IS_VALID (&_nmp_classes[obj_type - 1])); + nm_assert(obj_type > 0); + nm_assert(obj_type <= G_N_ELEMENTS(_nmp_classes)); + nm_assert(_nmp_classes[obj_type - 1].obj_type == obj_type); + nm_assert(NMP_CLASS_IS_VALID(&_nmp_classes[obj_type - 1])); - return &_nmp_classes[obj_type - 1]; + return &_nmp_classes[obj_type - 1]; } static inline NMPObject * NMP_OBJECT_UP_CAST(const NMPlatformObject *plobj) { - NMPObject *obj; + NMPObject *obj; - obj = plobj - ? (NMPObject *) ( &(((char *) plobj)[-((int) G_STRUCT_OFFSET (NMPObject, object))]) ) - : NULL; - nm_assert (!obj || (obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID (obj->_class))); - return obj; + obj = plobj ? (NMPObject *) (&(((char *) plobj)[-((int) G_STRUCT_OFFSET(NMPObject, object))])) + : NULL; + nm_assert(!obj || (obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID(obj->_class))); + return obj; } -#define NMP_OBJECT_UP_CAST(plobj) (NMP_OBJECT_UP_CAST ((const NMPlatformObject *) (plobj))) +#define NMP_OBJECT_UP_CAST(plobj) (NMP_OBJECT_UP_CAST((const NMPlatformObject *) (plobj))) static inline gboolean -NMP_OBJECT_IS_VALID (const NMPObject *obj) +NMP_OBJECT_IS_VALID(const NMPObject *obj) { - nm_assert (!obj || ( obj - && obj->parent._ref_count > 0 - && NMP_CLASS_IS_VALID (obj->_class))); + nm_assert(!obj || (obj && obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID(obj->_class))); - /* There isn't really much to check. Either @obj is NULL, or we must - * assume that it points to valid memory. */ - return obj != NULL; + /* There isn't really much to check. Either @obj is NULL, or we must + * assume that it points to valid memory. */ + return obj != NULL; } static inline gboolean -NMP_OBJECT_IS_STACKINIT (const NMPObject *obj) +NMP_OBJECT_IS_STACKINIT(const NMPObject *obj) { - nm_assert (!obj || NMP_OBJECT_IS_VALID (obj)); + nm_assert(!obj || NMP_OBJECT_IS_VALID(obj)); - return obj && obj->parent._ref_count == NM_OBJ_REF_COUNT_STACKINIT; + return obj && obj->parent._ref_count == NM_OBJ_REF_COUNT_STACKINIT; } static inline const NMPClass * -NMP_OBJECT_GET_CLASS (const NMPObject *obj) +NMP_OBJECT_GET_CLASS(const NMPObject *obj) { - nm_assert (NMP_OBJECT_IS_VALID (obj)); + nm_assert(NMP_OBJECT_IS_VALID(obj)); - return obj->_class; + return obj->_class; } static inline NMPObjectType -NMP_OBJECT_GET_TYPE (const NMPObject *obj) +NMP_OBJECT_GET_TYPE(const NMPObject *obj) { - nm_assert (!obj || NMP_OBJECT_IS_VALID (obj)); + nm_assert(!obj || NMP_OBJECT_IS_VALID(obj)); - return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN; + return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN; } static inline gboolean -_NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMPObjectType obj_type) -{ - switch (obj_type) { - case NMP_OBJECT_TYPE_LINK: - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP6_ADDRESS: - case NMP_OBJECT_TYPE_IP4_ROUTE: - case NMP_OBJECT_TYPE_IP6_ROUTE: - - case NMP_OBJECT_TYPE_QDISC: - - case NMP_OBJECT_TYPE_TFILTER: - - case NMP_OBJECT_TYPE_LNK_GRE: - case NMP_OBJECT_TYPE_LNK_GRETAP: - case NMP_OBJECT_TYPE_LNK_INFINIBAND: - case NMP_OBJECT_TYPE_LNK_IP6TNL: - case NMP_OBJECT_TYPE_LNK_IP6GRE: - case NMP_OBJECT_TYPE_LNK_IP6GRETAP: - case NMP_OBJECT_TYPE_LNK_IPIP: - case NMP_OBJECT_TYPE_LNK_MACSEC: - case NMP_OBJECT_TYPE_LNK_MACVLAN: - case NMP_OBJECT_TYPE_LNK_MACVTAP: - case NMP_OBJECT_TYPE_LNK_SIT: - case NMP_OBJECT_TYPE_LNK_TUN: - case NMP_OBJECT_TYPE_LNK_VLAN: - case NMP_OBJECT_TYPE_LNK_VRF: - case NMP_OBJECT_TYPE_LNK_VXLAN: - case NMP_OBJECT_TYPE_LNK_WIREGUARD: - return TRUE; - - case NMP_OBJECT_TYPE_ROUTING_RULE: - return FALSE; - - case NMP_OBJECT_TYPE_UNKNOWN: - case __NMP_OBJECT_TYPE_LAST: - break; - } - nm_assert_not_reached (); - return FALSE; -} - -#define NMP_OBJECT_CAST_OBJECT(obj) \ - ({ \ - typeof (obj) _obj = (obj); \ - \ - nm_assert ( !_obj \ - || nmp_class_from_type (NMP_OBJECT_GET_TYPE (_obj)))); \ - _obj ? &NM_CONSTCAST (NMPObject, _obj)->object : NULL; \ - }) - -#define NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj) \ - ({ \ - typeof (obj) _obj = (obj); \ - \ - nm_assert ( !_obj \ - || _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMP_OBJECT_GET_TYPE (_obj))); \ - _obj ? &NM_CONSTCAST (NMPObject, _obj)->obj_with_ifindex : NULL; \ - }) - -#define _NMP_OBJECT_CAST(obj, field, ...) \ - ({ \ - typeof (obj) _obj = (obj); \ - \ - nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), __VA_ARGS__)); \ - _obj ? &NM_CONSTCAST (NMPObject, _obj)->field : NULL; \ - }) - -#define NMP_OBJECT_CAST_LINK(obj) _NMP_OBJECT_CAST (obj, link, NMP_OBJECT_TYPE_LINK) -#define NMP_OBJECT_CAST_IP_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ip_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS) -#define NMP_OBJECT_CAST_IPX_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ipx_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS) -#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ip4_address, NMP_OBJECT_TYPE_IP4_ADDRESS) -#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) _NMP_OBJECT_CAST (obj, ip6_address, NMP_OBJECT_TYPE_IP6_ADDRESS) -#define NMP_OBJECT_CAST_IP_ROUTE(obj) _NMP_OBJECT_CAST (obj, ip_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) -#define NMP_OBJECT_CAST_IPX_ROUTE(obj) _NMP_OBJECT_CAST (obj, ipx_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) -#define NMP_OBJECT_CAST_IP4_ROUTE(obj) _NMP_OBJECT_CAST (obj, ip4_route, NMP_OBJECT_TYPE_IP4_ROUTE) -#define NMP_OBJECT_CAST_IP6_ROUTE(obj) _NMP_OBJECT_CAST (obj, ip6_route, NMP_OBJECT_TYPE_IP6_ROUTE) -#define NMP_OBJECT_CAST_ROUTING_RULE(obj) _NMP_OBJECT_CAST (obj, routing_rule, NMP_OBJECT_TYPE_ROUTING_RULE) -#define NMP_OBJECT_CAST_QDISC(obj) _NMP_OBJECT_CAST (obj, qdisc, NMP_OBJECT_TYPE_QDISC) -#define NMP_OBJECT_CAST_TFILTER(obj) _NMP_OBJECT_CAST (obj, tfilter, NMP_OBJECT_TYPE_TFILTER) -#define NMP_OBJECT_CAST_LNK_WIREGUARD(obj) _NMP_OBJECT_CAST (obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD) +_NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type) +{ + switch (obj_type) { + case NMP_OBJECT_TYPE_LINK: + case NMP_OBJECT_TYPE_IP4_ADDRESS: + case NMP_OBJECT_TYPE_IP6_ADDRESS: + case NMP_OBJECT_TYPE_IP4_ROUTE: + case NMP_OBJECT_TYPE_IP6_ROUTE: + + case NMP_OBJECT_TYPE_QDISC: + + case NMP_OBJECT_TYPE_TFILTER: + + case NMP_OBJECT_TYPE_LNK_BRIDGE: + case NMP_OBJECT_TYPE_LNK_GRE: + case NMP_OBJECT_TYPE_LNK_GRETAP: + case NMP_OBJECT_TYPE_LNK_INFINIBAND: + case NMP_OBJECT_TYPE_LNK_IP6TNL: + case NMP_OBJECT_TYPE_LNK_IP6GRE: + case NMP_OBJECT_TYPE_LNK_IP6GRETAP: + case NMP_OBJECT_TYPE_LNK_IPIP: + case NMP_OBJECT_TYPE_LNK_MACSEC: + case NMP_OBJECT_TYPE_LNK_MACVLAN: + case NMP_OBJECT_TYPE_LNK_MACVTAP: + case NMP_OBJECT_TYPE_LNK_SIT: + case NMP_OBJECT_TYPE_LNK_TUN: + case NMP_OBJECT_TYPE_LNK_VLAN: + case NMP_OBJECT_TYPE_LNK_VRF: + case NMP_OBJECT_TYPE_LNK_VXLAN: + case NMP_OBJECT_TYPE_LNK_WIREGUARD: + return TRUE; + + case NMP_OBJECT_TYPE_ROUTING_RULE: + return FALSE; + + case NMP_OBJECT_TYPE_UNKNOWN: + case __NMP_OBJECT_TYPE_LAST: + break; + } + nm_assert_not_reached(); + return FALSE; +} -static inline const NMPObject * -nmp_object_ref (const NMPObject *obj) +#define NMP_OBJECT_CAST_OBJECT(obj) \ + ({ \ + typeof(obj) _obj = (obj); \ + \ + nm_assert ( !_obj \ + || nmp_class_from_type (NMP_OBJECT_GET_TYPE (_obj)))); \ + _obj ? &NM_CONSTCAST(NMPObject, _obj)->object : NULL; \ + }) + +#define NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj) \ + ({ \ + typeof(obj) _obj = (obj); \ + \ + nm_assert(!_obj || _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMP_OBJECT_GET_TYPE(_obj))); \ + _obj ? &NM_CONSTCAST(NMPObject, _obj)->obj_with_ifindex : NULL; \ + }) + +#define _NMP_OBJECT_CAST(obj, field, ...) \ + ({ \ + typeof(obj) _obj = (obj); \ + \ + nm_assert(!_obj || NM_IN_SET(NMP_OBJECT_GET_TYPE(_obj), __VA_ARGS__)); \ + _obj ? &NM_CONSTCAST(NMPObject, _obj)->field : NULL; \ + }) + +#define NMP_OBJECT_CAST_LINK(obj) _NMP_OBJECT_CAST(obj, link, NMP_OBJECT_TYPE_LINK) +#define NMP_OBJECT_CAST_IP_ADDRESS(obj) \ + _NMP_OBJECT_CAST(obj, ip_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS) +#define NMP_OBJECT_CAST_IPX_ADDRESS(obj) \ + _NMP_OBJECT_CAST(obj, ipx_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS) +#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) \ + _NMP_OBJECT_CAST(obj, ip4_address, NMP_OBJECT_TYPE_IP4_ADDRESS) +#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \ + _NMP_OBJECT_CAST(obj, ip6_address, NMP_OBJECT_TYPE_IP6_ADDRESS) +#define NMP_OBJECT_CAST_IP_ROUTE(obj) \ + _NMP_OBJECT_CAST(obj, ip_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) +#define NMP_OBJECT_CAST_IPX_ROUTE(obj) \ + _NMP_OBJECT_CAST(obj, ipx_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE) +#define NMP_OBJECT_CAST_IP4_ROUTE(obj) _NMP_OBJECT_CAST(obj, ip4_route, NMP_OBJECT_TYPE_IP4_ROUTE) +#define NMP_OBJECT_CAST_IP6_ROUTE(obj) _NMP_OBJECT_CAST(obj, ip6_route, NMP_OBJECT_TYPE_IP6_ROUTE) +#define NMP_OBJECT_CAST_ROUTING_RULE(obj) \ + _NMP_OBJECT_CAST(obj, routing_rule, NMP_OBJECT_TYPE_ROUTING_RULE) +#define NMP_OBJECT_CAST_QDISC(obj) _NMP_OBJECT_CAST(obj, qdisc, NMP_OBJECT_TYPE_QDISC) +#define NMP_OBJECT_CAST_TFILTER(obj) _NMP_OBJECT_CAST(obj, tfilter, NMP_OBJECT_TYPE_TFILTER) +#define NMP_OBJECT_CAST_LNK_WIREGUARD(obj) \ + _NMP_OBJECT_CAST(obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD) +#define NMP_OBJECT_CAST_LNK_BRIDGE(obj) \ + _NMP_OBJECT_CAST(obj, lnk_bridge, NMP_OBJECT_TYPE_LNK_BRIDGE) + +static inline int +NMP_OBJECT_TYPE_TO_ADDR_FAMILY(NMPObjectType obj_type) { - if (!obj) { - /* for convenience, allow NULL. */ - return NULL; - } + return nmp_class_from_type(obj_type)->addr_family; +} - /* ref and unref accept const pointers. NMPObject is supposed to be shared - * and kept immutable. Disallowing to take/return a reference to a const - * NMPObject is cumbersome, because callers are precisely expected to - * keep a ref on the otherwise immutable object. */ - g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj), NULL); - g_return_val_if_fail (obj->parent._ref_count != NM_OBJ_REF_COUNT_STACKINIT, NULL); +static inline int +NMP_OBJECT_GET_ADDR_FAMILY(const NMPObject *obj) +{ + return NMP_OBJECT_GET_CLASS(obj)->addr_family; +} - return (const NMPObject *) nm_dedup_multi_obj_ref ((const NMDedupMultiObj *) obj); +static inline const NMPObject * +nmp_object_ref(const NMPObject *obj) +{ + if (!obj) { + /* for convenience, allow NULL. */ + return NULL; + } + + /* ref and unref accept const pointers. NMPObject is supposed to be shared + * and kept immutable. Disallowing to take/return a reference to a const + * NMPObject is cumbersome, because callers are precisely expected to + * keep a ref on the otherwise immutable object. */ + g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj), NULL); + g_return_val_if_fail(obj->parent._ref_count != NM_OBJ_REF_COUNT_STACKINIT, NULL); + + return (const NMPObject *) nm_dedup_multi_obj_ref((const NMDedupMultiObj *) obj); } static inline void -nmp_object_unref (const NMPObject *obj) +nmp_object_unref(const NMPObject *obj) { - if (obj) { - nm_assert (NMP_OBJECT_IS_VALID (obj)); + if (obj) { + nm_assert(NMP_OBJECT_IS_VALID(obj)); - nm_dedup_multi_obj_unref ((const NMDedupMultiObj *) obj); - } + nm_dedup_multi_obj_unref((const NMDedupMultiObj *) obj); + } } -#define nm_clear_nmp_object(ptr) \ - ({ \ - typeof (ptr) _ptr = (ptr); \ - typeof (*_ptr) _pptr; \ - gboolean _changed = FALSE; \ - \ - if ( _ptr \ - && (_pptr = *_ptr)) { \ - *_ptr = NULL; \ - nmp_object_unref (_pptr); \ - _changed = TRUE; \ - } \ - _changed; \ - }) +#define nm_clear_nmp_object(ptr) \ + ({ \ + typeof(ptr) _ptr = (ptr); \ + typeof(*_ptr) _pptr; \ + gboolean _changed = FALSE; \ + \ + if (_ptr && (_pptr = *_ptr)) { \ + *_ptr = NULL; \ + nmp_object_unref(_pptr); \ + _changed = TRUE; \ + } \ + _changed; \ + }) + +static inline gboolean +nmp_object_ref_set(const NMPObject **pp, const NMPObject *obj) +{ + gboolean _changed = FALSE; + const NMPObject *p; + + nm_assert(!pp || !*pp || NMP_OBJECT_IS_VALID(*pp)); + nm_assert(!obj || NMP_OBJECT_IS_VALID(obj)); + + if (pp && ((p = *pp) != obj)) { + nmp_object_ref(obj); + *pp = obj; + nmp_object_unref(p); + _changed = TRUE; + } + return _changed; +} -NMPObject *nmp_object_new (NMPObjectType obj_type, gconstpointer plobj); -NMPObject *nmp_object_new_link (int ifindex); +NMPObject *nmp_object_new(NMPObjectType obj_type, gconstpointer plobj); +NMPObject *nmp_object_new_link(int ifindex); -const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj); +const NMPObject *nmp_object_stackinit(NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj); static inline NMPObject * -nmp_object_stackinit_obj (NMPObject *obj, const NMPObject *src) +nmp_object_stackinit_obj(NMPObject *obj, const NMPObject *src) { - return obj == src - ? obj - : (NMPObject *) nmp_object_stackinit (obj, NMP_OBJECT_GET_TYPE (src), &src->object); + return obj == src + ? obj + : (NMPObject *) nmp_object_stackinit(obj, NMP_OBJECT_GET_TYPE(src), &src->object); } -const NMPObject *nmp_object_stackinit_id (NMPObject *obj, const NMPObject *src); -const NMPObject *nmp_object_stackinit_id_link (NMPObject *obj, int ifindex); -const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address); -const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address); - -const char *nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size); -void nmp_object_hash_update (const NMPObject *obj, NMHashState *h); -int nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2); +const NMPObject *nmp_object_stackinit_id(NMPObject *obj, const NMPObject *src); +const NMPObject *nmp_object_stackinit_id_link(NMPObject *obj, int ifindex); +const NMPObject *nmp_object_stackinit_id_ip4_address(NMPObject *obj, + int ifindex, + guint32 address, + guint8 plen, + guint32 peer_address); +const NMPObject * +nmp_object_stackinit_id_ip6_address(NMPObject *obj, int ifindex, const struct in6_addr *address); + +const char *nmp_object_to_string(const NMPObject * obj, + NMPObjectToStringMode to_string_mode, + char * buf, + gsize buf_size); +void nmp_object_hash_update(const NMPObject *obj, NMHashState *h); +int nmp_object_cmp(const NMPObject *obj1, const NMPObject *obj2); static inline gboolean -nmp_object_equal (const NMPObject *obj1, const NMPObject *obj2) +nmp_object_equal(const NMPObject *obj1, const NMPObject *obj2) { - return nmp_object_cmp (obj1, obj2) == 0; + return nmp_object_cmp(obj1, obj2) == 0; } -void nmp_object_copy (NMPObject *dst, const NMPObject *src, gboolean id_only); -NMPObject *nmp_object_clone (const NMPObject *obj, gboolean id_only); +void nmp_object_copy(NMPObject *dst, const NMPObject *src, gboolean id_only); +NMPObject *nmp_object_clone(const NMPObject *obj, gboolean id_only); -int nmp_object_id_cmp (const NMPObject *obj1, const NMPObject *obj2); -void nmp_object_id_hash_update (const NMPObject *obj, NMHashState *h); -guint nmp_object_id_hash (const NMPObject *obj); +int nmp_object_id_cmp(const NMPObject *obj1, const NMPObject *obj2); +void nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h); +guint nmp_object_id_hash(const NMPObject *obj); static inline gboolean -nmp_object_id_equal (const NMPObject *obj1, const NMPObject *obj2) +nmp_object_id_equal(const NMPObject *obj1, const NMPObject *obj2) { - return nmp_object_id_cmp (obj1, obj2) == 0; + return nmp_object_id_cmp(obj1, obj2) == 0; } -gboolean nmp_object_is_alive (const NMPObject *obj); -gboolean nmp_object_is_visible (const NMPObject *obj); +guint nmp_object_indirect_id_hash(gconstpointer a); +gboolean nmp_object_indirect_id_equal(gconstpointer a, gconstpointer b); + +gboolean nmp_object_is_alive(const NMPObject *obj); +gboolean nmp_object_is_visible(const NMPObject *obj); -void _nmp_object_fixup_link_udev_fields (NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev); +void +_nmp_object_fixup_link_udev_fields(NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev); static inline void -_nm_auto_nmpobj_cleanup (gpointer p) +_nm_auto_nmpobj_cleanup(gpointer p) { - nmp_object_unref (*((const NMPObject **) p)); + nmp_object_unref(*((const NMPObject **) p)); } #define nm_auto_nmpobj nm_auto(_nm_auto_nmpobj_cleanup) typedef struct _NMPCache NMPCache; -typedef void (*NMPCachePreHook) (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data); -typedef gboolean (*NMPObjectMatchFn) (const NMPObject *obj, gpointer user_data); - -const NMDedupMultiEntry *nmp_cache_lookup_entry (const NMPCache *cache, - const NMPObject *obj); -const NMDedupMultiEntry *nmp_cache_lookup_entry_with_idx_type (const NMPCache *cache, - NMPCacheIdType cache_id_type, - const NMPObject *obj); -const NMDedupMultiEntry *nmp_cache_lookup_entry_link (const NMPCache *cache, - int ifindex); -const NMPObject *nmp_cache_lookup_obj (const NMPCache *cache, - const NMPObject *obj); -const NMPObject *nmp_cache_lookup_link (const NMPCache *cache, - int ifindex); +typedef void (*NMPCachePreHook)(NMPCache * cache, + const NMPObject *old, + const NMPObject *new, + NMPCacheOpsType ops_type, + gpointer user_data); +typedef gboolean (*NMPObjectMatchFn)(const NMPObject *obj, gpointer user_data); + +const NMDedupMultiEntry *nmp_cache_lookup_entry(const NMPCache *cache, const NMPObject *obj); +const NMDedupMultiEntry *nmp_cache_lookup_entry_with_idx_type(const NMPCache * cache, + NMPCacheIdType cache_id_type, + const NMPObject *obj); +const NMDedupMultiEntry *nmp_cache_lookup_entry_link(const NMPCache *cache, int ifindex); +const NMPObject * nmp_cache_lookup_obj(const NMPCache *cache, const NMPObject *obj); +const NMPObject * nmp_cache_lookup_link(const NMPCache *cache, int ifindex); typedef struct _NMPLookup NMPLookup; struct _NMPLookup { - NMPCacheIdType cache_id_type; - NMPObject selector_obj; + NMPCacheIdType cache_id_type; + NMPObject selector_obj; }; -const NMDedupMultiHeadEntry *nmp_cache_lookup_all (const NMPCache *cache, - NMPCacheIdType cache_id_type, - const NMPObject *select_obj); +const NMDedupMultiHeadEntry *nmp_cache_lookup_all(const NMPCache * cache, + NMPCacheIdType cache_id_type, + const NMPObject *select_obj); static inline const NMDedupMultiHeadEntry * -nmp_cache_lookup (const NMPCache *cache, - const NMPLookup *lookup) +nmp_cache_lookup(const NMPCache *cache, const NMPLookup *lookup) { - return nmp_cache_lookup_all (cache, lookup->cache_id_type, &lookup->selector_obj); + return nmp_cache_lookup_all(cache, lookup->cache_id_type, &lookup->selector_obj); } -const NMPLookup *nmp_lookup_init_obj_type (NMPLookup *lookup, - NMPObjectType obj_type); -const NMPLookup *nmp_lookup_init_link_by_ifname (NMPLookup *lookup, - const char *ifname); -const NMPLookup *nmp_lookup_init_object (NMPLookup *lookup, - NMPObjectType obj_type, - int ifindex); -const NMPLookup *nmp_lookup_init_route_default (NMPLookup *lookup, - NMPObjectType obj_type); -const NMPLookup *nmp_lookup_init_route_by_weak_id (NMPLookup *lookup, - const NMPObject *obj); -const NMPLookup *nmp_lookup_init_ip4_route_by_weak_id (NMPLookup *lookup, - in_addr_t network, - guint plen, - guint32 metric, - guint8 tos); -const NMPLookup *nmp_lookup_init_ip6_route_by_weak_id (NMPLookup *lookup, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen); -const NMPLookup *nmp_lookup_init_object_by_addr_family (NMPLookup *lookup, - NMPObjectType obj_type, - int addr_family); - -GArray *nmp_cache_lookup_to_array (const NMDedupMultiHeadEntry *head_entry, - NMPObjectType obj_type, - gboolean visible_only); +const NMPLookup *nmp_lookup_init_obj_type(NMPLookup *lookup, NMPObjectType obj_type); +const NMPLookup *nmp_lookup_init_link_by_ifname(NMPLookup *lookup, const char *ifname); +const NMPLookup *nmp_lookup_init_object(NMPLookup *lookup, NMPObjectType obj_type, int ifindex); +const NMPLookup *nmp_lookup_init_route_default(NMPLookup *lookup, NMPObjectType obj_type); +const NMPLookup *nmp_lookup_init_route_by_weak_id(NMPLookup *lookup, const NMPObject *obj); +const NMPLookup *nmp_lookup_init_ip4_route_by_weak_id(NMPLookup *lookup, + in_addr_t network, + guint plen, + guint32 metric, + guint8 tos); +const NMPLookup *nmp_lookup_init_ip6_route_by_weak_id(NMPLookup * lookup, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen); +const NMPLookup * +nmp_lookup_init_object_by_addr_family(NMPLookup *lookup, NMPObjectType obj_type, int addr_family); + +GArray *nmp_cache_lookup_to_array(const NMDedupMultiHeadEntry *head_entry, + NMPObjectType obj_type, + gboolean visible_only); static inline gboolean -nmp_cache_iter_next (NMDedupMultiIter *iter, const NMPObject **out_obj) +nmp_cache_iter_next(NMDedupMultiIter *iter, const NMPObject **out_obj) { - gboolean has_next; + gboolean has_next; - has_next = nm_dedup_multi_iter_next (iter); - nm_assert (!has_next || NMP_OBJECT_IS_VALID (iter->current->obj)); - if (out_obj) - *out_obj = has_next ? iter->current->obj : NULL; - return has_next; + has_next = nm_dedup_multi_iter_next(iter); + nm_assert(!has_next || NMP_OBJECT_IS_VALID(iter->current->obj)); + if (out_obj) + *out_obj = has_next ? iter->current->obj : NULL; + return has_next; } static inline gboolean -nmp_cache_iter_next_link (NMDedupMultiIter *iter, const NMPlatformLink **out_obj) +nmp_cache_iter_next_link(NMDedupMultiIter *iter, const NMPlatformLink **out_obj) { - gboolean has_next; + gboolean has_next; - has_next = nm_dedup_multi_iter_next (iter); - nm_assert (!has_next || NMP_OBJECT_GET_TYPE (iter->current->obj) == NMP_OBJECT_TYPE_LINK); - if (out_obj) - *out_obj = has_next ? &(((const NMPObject *) iter->current->obj)->link) : NULL; - return has_next; + has_next = nm_dedup_multi_iter_next(iter); + nm_assert(!has_next || NMP_OBJECT_GET_TYPE(iter->current->obj) == NMP_OBJECT_TYPE_LINK); + if (out_obj) + *out_obj = has_next ? &(((const NMPObject *) iter->current->obj)->link) : NULL; + return has_next; } #define nmp_cache_iter_for_each(iter, head, obj) \ - for (nm_dedup_multi_iter_init ((iter), \ - (head)); \ - nmp_cache_iter_next ((iter), (obj)); \ - ) + for (nm_dedup_multi_iter_init((iter), (head)); nmp_cache_iter_next((iter), (obj));) #define nmp_cache_iter_for_each_link(iter, head, obj) \ - for (nm_dedup_multi_iter_init ((iter), \ - (head)); \ - nmp_cache_iter_next_link ((iter), (obj)); \ - ) - -const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache, - int ifindex, - const char *ifname, - gboolean visible_only, - NMLinkType link_type, - NMPObjectMatchFn match_fn, - gpointer user_data); - -gboolean nmp_cache_link_connected_for_slave (int ifindex_master, const NMPObject *slave); -gboolean nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *master, const NMPObject *potential_slave, const NMPObject *ignore_slave); -const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex (const NMPCache *cache, int master_ifindex, const NMPObject *potential_slave, const NMPObject *ignore_slave); - -gboolean nmp_cache_use_udev_get (const NMPCache *cache); - -void ASSERT_nmp_cache_is_consistent (const NMPCache *cache); - -NMPCacheOpsType nmp_cache_remove (NMPCache *cache, - const NMPObject *obj_needle, - gboolean equals_by_ptr, - gboolean only_dirty, - const NMPObject **out_obj_old); -NMPCacheOpsType nmp_cache_remove_netlink (NMPCache *cache, - const NMPObject *obj_needle, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new); -NMPCacheOpsType nmp_cache_update_netlink (NMPCache *cache, - NMPObject *obj_hand_over, - gboolean is_dump, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new); -NMPCacheOpsType nmp_cache_update_netlink_route (NMPCache *cache, - NMPObject *obj_hand_over, - gboolean is_dump, - guint16 nlmsgflags, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new, - const NMPObject **out_obj_replace, - gboolean *out_resync_required); -NMPCacheOpsType nmp_cache_update_link_udev (NMPCache *cache, - int ifindex, - struct udev_device *udevice, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new); -NMPCacheOpsType nmp_cache_update_link_master_connected (NMPCache *cache, - int ifindex, - const NMPObject **out_obj_old, - const NMPObject **out_obj_new); + for (nm_dedup_multi_iter_init((iter), (head)); nmp_cache_iter_next_link((iter), (obj));) + +const NMPObject *nmp_cache_lookup_link_full(const NMPCache * cache, + int ifindex, + const char * ifname, + gboolean visible_only, + NMLinkType link_type, + NMPObjectMatchFn match_fn, + gpointer user_data); + +gboolean nmp_cache_link_connected_for_slave(int ifindex_master, const NMPObject *slave); +gboolean nmp_cache_link_connected_needs_toggle(const NMPCache * cache, + const NMPObject *master, + const NMPObject *potential_slave, + const NMPObject *ignore_slave); +const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex(const NMPCache * cache, + int master_ifindex, + const NMPObject *potential_slave, + const NMPObject *ignore_slave); + +gboolean nmp_cache_use_udev_get(const NMPCache *cache); + +void nmtst_assert_nmp_cache_is_consistent(const NMPCache *cache); + +NMPCacheOpsType nmp_cache_remove(NMPCache * cache, + const NMPObject * obj_needle, + gboolean equals_by_ptr, + gboolean only_dirty, + const NMPObject **out_obj_old); +NMPCacheOpsType nmp_cache_remove_netlink(NMPCache * cache, + const NMPObject * obj_needle, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new); +NMPCacheOpsType nmp_cache_update_netlink(NMPCache * cache, + NMPObject * obj_hand_over, + gboolean is_dump, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new); +NMPCacheOpsType nmp_cache_update_netlink_route(NMPCache * cache, + NMPObject * obj_hand_over, + gboolean is_dump, + guint16 nlmsgflags, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new, + const NMPObject **out_obj_replace, + gboolean * out_resync_required); +NMPCacheOpsType nmp_cache_update_link_udev(NMPCache * cache, + int ifindex, + struct udev_device *udevice, + const NMPObject ** out_obj_old, + const NMPObject ** out_obj_new); +NMPCacheOpsType nmp_cache_update_link_master_connected(NMPCache * cache, + int ifindex, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new); static inline const NMDedupMultiEntry * -nmp_cache_reresolve_main_entry (NMPCache *cache, - const NMDedupMultiEntry *entry, - const NMPLookup *lookup) +nmp_cache_reresolve_main_entry(NMPCache * cache, + const NMDedupMultiEntry *entry, + const NMPLookup * lookup) { - const NMDedupMultiEntry *main_entry; + const NMDedupMultiEntry *main_entry; - nm_assert (cache); - nm_assert (entry); - nm_assert (lookup); + nm_assert(cache); + nm_assert(entry); + nm_assert(lookup); - if (lookup->cache_id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) { - nm_assert (entry == nmp_cache_lookup_entry (cache, entry->obj)); - return entry; - } + if (lookup->cache_id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) { + nm_assert(entry == nmp_cache_lookup_entry(cache, entry->obj)); + return entry; + } - /* we only track the dirty flag for the OBJECT-TYPE index. That means, - * for other lookup types we need to check the dirty flag of the main-entry. */ - main_entry = nmp_cache_lookup_entry (cache, entry->obj); + /* we only track the dirty flag for the OBJECT-TYPE index. That means, + * for other lookup types we need to check the dirty flag of the main-entry. */ + main_entry = nmp_cache_lookup_entry(cache, entry->obj); - nm_assert (main_entry); - nm_assert (main_entry->obj == entry->obj); + nm_assert(main_entry); + nm_assert(main_entry->obj == entry->obj); - return main_entry; + return main_entry; } -void nmp_cache_dirty_set_all_main (NMPCache *cache, - const NMPLookup *lookup); +void nmp_cache_dirty_set_all_main(NMPCache *cache, const NMPLookup *lookup); -NMPCache *nmp_cache_new (NMDedupMultiIndex *multi_idx, gboolean use_udev); -void nmp_cache_free (NMPCache *cache); +NMPCache *nmp_cache_new(NMDedupMultiIndex *multi_idx, gboolean use_udev); +void nmp_cache_free(NMPCache *cache); static inline void -ASSERT_nmp_cache_ops (const NMPCache *cache, - NMPCacheOpsType ops_type, - const NMPObject *obj_old, - const NMPObject *obj_new) +ASSERT_nmp_cache_ops(const NMPCache * cache, + NMPCacheOpsType ops_type, + const NMPObject *obj_old, + const NMPObject *obj_new) { #if NM_MORE_ASSERTS - nm_assert (cache); - nm_assert (obj_old || obj_new); - nm_assert (!obj_old || ( NMP_OBJECT_IS_VALID (obj_old) - && !NMP_OBJECT_IS_STACKINIT (obj_old) - && nmp_object_is_alive (obj_old))); - nm_assert (!obj_new || ( NMP_OBJECT_IS_VALID (obj_new) - && !NMP_OBJECT_IS_STACKINIT (obj_new) - && nmp_object_is_alive (obj_new))); - - switch (ops_type) { - case NMP_CACHE_OPS_UNCHANGED: - nm_assert (obj_old == obj_new); - break; - case NMP_CACHE_OPS_ADDED: - nm_assert (!obj_old && obj_new); - break; - case NMP_CACHE_OPS_UPDATED: - nm_assert (obj_old && obj_new && obj_old != obj_new); - break; - case NMP_CACHE_OPS_REMOVED: - nm_assert (obj_old && !obj_new); - break; - default: - nm_assert_not_reached (); - } - - nm_assert (obj_new == NULL || obj_old == NULL || nmp_object_id_equal (obj_new, obj_old)); - nm_assert (!obj_old || !obj_new || NMP_OBJECT_GET_CLASS (obj_old) == NMP_OBJECT_GET_CLASS (obj_new)); - - nm_assert (obj_new == nmp_cache_lookup_obj (cache, obj_new ?: obj_old)); + nm_assert(cache); + nm_assert(obj_old || obj_new); + nm_assert(!obj_old + || (NMP_OBJECT_IS_VALID(obj_old) && !NMP_OBJECT_IS_STACKINIT(obj_old) + && nmp_object_is_alive(obj_old))); + nm_assert(!obj_new + || (NMP_OBJECT_IS_VALID(obj_new) && !NMP_OBJECT_IS_STACKINIT(obj_new) + && nmp_object_is_alive(obj_new))); + + switch (ops_type) { + case NMP_CACHE_OPS_UNCHANGED: + nm_assert(obj_old == obj_new); + break; + case NMP_CACHE_OPS_ADDED: + nm_assert(!obj_old && obj_new); + break; + case NMP_CACHE_OPS_UPDATED: + nm_assert(obj_old && obj_new && obj_old != obj_new); + break; + case NMP_CACHE_OPS_REMOVED: + nm_assert(obj_old && !obj_new); + break; + default: + nm_assert_not_reached(); + } + + nm_assert(obj_new == NULL || obj_old == NULL || nmp_object_id_equal(obj_new, obj_old)); + nm_assert(!obj_old || !obj_new + || NMP_OBJECT_GET_CLASS(obj_old) == NMP_OBJECT_GET_CLASS(obj_new)); + + nm_assert(obj_new == nmp_cache_lookup_obj(cache, obj_new ?: obj_old)); #endif } -const NMDedupMultiHeadEntry *nm_platform_lookup_all (NMPlatform *platform, - NMPCacheIdType cache_id_type, - const NMPObject *obj); +const NMDedupMultiHeadEntry * +nm_platform_lookup_all(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj); -const NMDedupMultiEntry *nm_platform_lookup_entry (NMPlatform *platform, - NMPCacheIdType cache_id_type, - const NMPObject *obj); +const NMDedupMultiEntry * +nm_platform_lookup_entry(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj); static inline const NMPObject * -nm_platform_lookup_obj (NMPlatform *platform, - NMPCacheIdType cache_id_type, - const NMPObject *obj) +nm_platform_lookup_obj(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj) { - return nm_dedup_multi_entry_get_obj (nm_platform_lookup_entry (platform, - cache_id_type, - obj)); + return nm_dedup_multi_entry_get_obj(nm_platform_lookup_entry(platform, cache_id_type, obj)); } static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_obj_type (NMPlatform *platform, - NMPObjectType obj_type) +nm_platform_lookup_obj_type(NMPlatform *platform, NMPObjectType obj_type) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_obj_type (&lookup, obj_type); - return nm_platform_lookup (platform, &lookup); + nmp_lookup_init_obj_type(&lookup, obj_type); + return nm_platform_lookup(platform, &lookup); } static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_link_by_ifname (NMPlatform *platform, - const char *ifname) +nm_platform_lookup_link_by_ifname(NMPlatform *platform, const char *ifname) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_link_by_ifname (&lookup, ifname); - return nm_platform_lookup (platform, &lookup); + nmp_lookup_init_link_by_ifname(&lookup, ifname); + return nm_platform_lookup(platform, &lookup); } static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_object (NMPlatform *platform, - NMPObjectType obj_type, - int ifindex) +nm_platform_lookup_object(NMPlatform *platform, NMPObjectType obj_type, int ifindex) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_object (&lookup, obj_type, ifindex); - return nm_platform_lookup (platform, &lookup); + nmp_lookup_init_object(&lookup, obj_type, ifindex); + return nm_platform_lookup(platform, &lookup); } static inline GPtrArray * -nm_platform_lookup_object_clone (NMPlatform *platform, - NMPObjectType obj_type, - int ifindex, - NMPObjectPredicateFunc predicate, - gpointer user_data) +nm_platform_lookup_object_clone(NMPlatform * platform, + NMPObjectType obj_type, + int ifindex, + NMPObjectPredicateFunc predicate, + gpointer user_data) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_object (&lookup, obj_type, ifindex); - return nm_platform_lookup_clone (platform, &lookup, predicate, user_data); + nmp_lookup_init_object(&lookup, obj_type, ifindex); + return nm_platform_lookup_clone(platform, &lookup, predicate, user_data); } static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_route_default (NMPlatform *platform, - NMPObjectType obj_type) +nm_platform_lookup_route_default(NMPlatform *platform, NMPObjectType obj_type) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_route_default (&lookup, obj_type); - return nm_platform_lookup (platform, &lookup); + nmp_lookup_init_route_default(&lookup, obj_type); + return nm_platform_lookup(platform, &lookup); } static inline GPtrArray * -nm_platform_lookup_route_default_clone (NMPlatform *platform, - NMPObjectType obj_type, - NMPObjectPredicateFunc predicate, - gpointer user_data) +nm_platform_lookup_route_default_clone(NMPlatform * platform, + NMPObjectType obj_type, + NMPObjectPredicateFunc predicate, + gpointer user_data) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_route_default (&lookup, obj_type); - return nm_platform_lookup_clone (platform, &lookup, predicate, user_data); + nmp_lookup_init_route_default(&lookup, obj_type); + return nm_platform_lookup_clone(platform, &lookup, predicate, user_data); } static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_ip4_route_by_weak_id (NMPlatform *platform, - in_addr_t network, - guint plen, - guint32 metric, - guint8 tos) +nm_platform_lookup_ip4_route_by_weak_id(NMPlatform *platform, + in_addr_t network, + guint plen, + guint32 metric, + guint8 tos) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_ip4_route_by_weak_id (&lookup, network, plen, metric, tos); - return nm_platform_lookup (platform, &lookup); + nmp_lookup_init_ip4_route_by_weak_id(&lookup, network, plen, metric, tos); + return nm_platform_lookup(platform, &lookup); } static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_ip6_route_by_weak_id (NMPlatform *platform, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen) +nm_platform_lookup_ip6_route_by_weak_id(NMPlatform * platform, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen) { - NMPLookup lookup; + NMPLookup lookup; - nmp_lookup_init_ip6_route_by_weak_id (&lookup, network, plen, metric, src, src_plen); - return nm_platform_lookup (platform, &lookup); + nmp_lookup_init_ip6_route_by_weak_id(&lookup, network, plen, metric, src, src_plen); + return nm_platform_lookup(platform, &lookup); } static inline const NMDedupMultiHeadEntry * -nm_platform_lookup_object_by_addr_family (NMPlatform *platform, - NMPObjectType obj_type, - int addr_family) +nm_platform_lookup_object_by_addr_family(NMPlatform * platform, + NMPObjectType obj_type, + int addr_family) +{ + NMPLookup lookup; + + nmp_lookup_init_object_by_addr_family(&lookup, obj_type, addr_family); + return nm_platform_lookup(platform, &lookup); +} + +/*****************************************************************************/ + +static inline const char * +nmp_object_link_get_ifname(const NMPObject *obj) +{ + if (!obj) + return NULL; + return NMP_OBJECT_CAST_LINK(obj)->name; +} + +static inline gboolean +nmp_object_ip_route_is_best_defaut_route(const NMPObject *obj) +{ + const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE(obj); + + /* return whether @obj is considered a default-route. + * + * NMIP4Config/NMIP6Config tracks the (best) default-route explicitly, because + * at various places we act differently depending on whether there is a default-route + * configured. + * + * Note that this only considers the main routing table. */ + return r && NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) + && nm_platform_route_table_is_main(r->table_coerced) + && r->type_coerced == nm_platform_route_type_coerce(1 /* RTN_UNICAST */); +} + +static inline gboolean +nmp_object_ip6_address_is_not_link_local(const NMPObject *obj) +{ + return !IN6_IS_ADDR_LINKLOCAL(&NMP_OBJECT_CAST_IP6_ADDRESS(obj)->address); +} + +/*****************************************************************************/ + +static inline gboolean +nm_platform_dedup_multi_iter_next_obj(NMDedupMultiIter *ipconf_iter, + const NMPObject **out_obj, + NMPObjectType assert_obj_type) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next(ipconf_iter); + nm_assert(assert_obj_type == NMP_OBJECT_TYPE_UNKNOWN || !has_next + || NMP_OBJECT_GET_TYPE(ipconf_iter->current->obj) == assert_obj_type); + NM_SET_OUT(out_obj, has_next ? ipconf_iter->current->obj : NULL); + return has_next; +} + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip4_address(NMDedupMultiIter * ipconf_iter, + const NMPlatformIP4Address **out_address) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next(ipconf_iter); + if (out_address) + *out_address = has_next ? NMP_OBJECT_CAST_IP4_ADDRESS(ipconf_iter->current->obj) : NULL; + return has_next; +} + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip4_route(NMDedupMultiIter * ipconf_iter, + const NMPlatformIP4Route **out_route) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next(ipconf_iter); + if (out_route) + *out_route = has_next ? NMP_OBJECT_CAST_IP4_ROUTE(ipconf_iter->current->obj) : NULL; + return has_next; +} + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip6_address(NMDedupMultiIter * ipconf_iter, + const NMPlatformIP6Address **out_address) +{ + gboolean has_next; + + has_next = nm_dedup_multi_iter_next(ipconf_iter); + if (out_address) + *out_address = has_next ? NMP_OBJECT_CAST_IP6_ADDRESS(ipconf_iter->current->obj) : NULL; + return has_next; +} + +static inline gboolean +nm_platform_dedup_multi_iter_next_ip6_route(NMDedupMultiIter * ipconf_iter, + const NMPlatformIP6Route **out_route) { - NMPLookup lookup; + gboolean has_next; - nmp_lookup_init_object_by_addr_family (&lookup, obj_type, addr_family); - return nm_platform_lookup (platform, &lookup); + has_next = nm_dedup_multi_iter_next(ipconf_iter); + if (out_route) + *out_route = has_next ? NMP_OBJECT_CAST_IP6_ROUTE(ipconf_iter->current->obj) : NULL; + return has_next; } #endif /* __NMP_OBJECT_H__ */ diff --git a/src/platform/nmp-rules-manager.c b/src/platform/nmp-rules-manager.c index a1d724c5..d139c9a3 100644 --- a/src/platform/nmp-rules-manager.c +++ b/src/platform/nmp-rules-manager.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ #include "nm-default.h" @@ -13,276 +13,278 @@ /*****************************************************************************/ struct _NMPRulesManager { - NMPlatform *platform; - GHashTable *by_obj; - GHashTable *by_user_tag; - GHashTable *by_data; - guint ref_count; + NMPlatform *platform; + GHashTable *by_obj; + GHashTable *by_user_tag; + GHashTable *by_data; + guint ref_count; }; /*****************************************************************************/ -static void _rules_init (NMPRulesManager *self); +static void _rules_init(NMPRulesManager *self); /*****************************************************************************/ -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG_PREFIX_NAME "rules-manager" - -#define _NMLOG(level, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - \ - if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ - _nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG_PREFIX_NAME "rules-manager" + +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \ + _nm_log(__level, \ + _NMLOG_DOMAIN, \ + 0, \ + NULL, \ + NULL, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ static gboolean -NMP_IS_RULES_MANAGER (gpointer self) +NMP_IS_RULES_MANAGER(gpointer self) { - return self - && ((NMPRulesManager *) self)->ref_count > 0 - && NM_IS_PLATFORM (((NMPRulesManager *) self)->platform); + return self && ((NMPRulesManager *) self)->ref_count > 0 + && NM_IS_PLATFORM(((NMPRulesManager *) self)->platform); } -#define _USER_TAG_LOG(user_tag) nm_hash_obfuscate_ptr (1240261787u, (user_tag)) +#define _USER_TAG_LOG(user_tag) nm_hash_obfuscate_ptr(1240261787u, (user_tag)) /*****************************************************************************/ typedef struct { - const NMPObject *obj; - gconstpointer user_tag; - CList obj_lst; - CList user_tag_lst; - - /* track_priority_val zero is special: those are weakly tracked rules. - * That means: NetworkManager will restore them only if it removed them earlier. - * But it will not remove or add them otherwise. - * - * Otherwise, the track_priority_val goes together with track_priority_present. - * In case of one rule being tracked multiple times (with different priorities), - * the one with higher priority wins. See _rules_obj_get_best_data(). - * Then, the winning present state either enforces that the rule is present - * or absent. - * - * If a rules is not tracked at all, it is ignored by NetworkManager. Assuming - * that it was added externally by the user. But unlike weakly tracked rules, - * NM will *not* restore such rules if NetworkManager themself removed them. */ - guint32 track_priority_val; - bool track_priority_present:1; - - bool dirty:1; + const NMPObject *obj; + gconstpointer user_tag; + CList obj_lst; + CList user_tag_lst; + + /* track_priority_val zero is special: those are weakly tracked rules. + * That means: NetworkManager will restore them only if it removed them earlier. + * But it will not remove or add them otherwise. + * + * Otherwise, the track_priority_val goes together with track_priority_present. + * In case of one rule being tracked multiple times (with different priorities), + * the one with higher priority wins. See _rules_obj_get_best_data(). + * Then, the winning present state either enforces that the rule is present + * or absent. + * + * If a rules is not tracked at all, it is ignored by NetworkManager. Assuming + * that it was added externally by the user. But unlike weakly tracked rules, + * NM will *not* restore such rules if NetworkManager themself removed them. */ + guint32 track_priority_val; + bool track_priority_present : 1; + + bool dirty : 1; } RulesData; typedef enum { - CONFIG_STATE_NONE = 0, - CONFIG_STATE_ADDED_BY_US = 1, - CONFIG_STATE_REMOVED_BY_US = 2, - - /* ConfigState encodes whether the rule was touched by us at all (CONFIG_STATE_NONE). - * - * Maybe we would only need to track whether we touched the rule at all. But we - * track it more in detail what we did: did we add it (CONFIG_STATE_ADDED_BY_US) - * or did we remove it (CONFIG_STATE_REMOVED_BY_US)? - * Finally, we need CONFIG_STATE_OWNED_BY_US, which means that we didn't actively - * add/remove it, but whenever we are about to undo the add/remove, we need to do it. - * In that sense, CONFIG_STATE_OWNED_BY_US is really just a flag that we unconditionally - * force the state next time when necessary. */ - CONFIG_STATE_OWNED_BY_US = 3, + CONFIG_STATE_NONE = 0, + CONFIG_STATE_ADDED_BY_US = 1, + CONFIG_STATE_REMOVED_BY_US = 2, + + /* ConfigState encodes whether the rule was touched by us at all (CONFIG_STATE_NONE). + * + * Maybe we would only need to track whether we touched the rule at all. But we + * track it more in detail what we did: did we add it (CONFIG_STATE_ADDED_BY_US) + * or did we remove it (CONFIG_STATE_REMOVED_BY_US)? + * Finally, we need CONFIG_STATE_OWNED_BY_US, which means that we didn't actively + * add/remove it, but whenever we are about to undo the add/remove, we need to do it. + * In that sense, CONFIG_STATE_OWNED_BY_US is really just a flag that we unconditionally + * force the state next time when necessary. */ + CONFIG_STATE_OWNED_BY_US = 3, } ConfigState; typedef struct { - const NMPObject *obj; - CList obj_lst_head; - - /* indicates whether we configured/removed the rule (during sync()). We need that, so - * if the rule gets untracked, that we know to remove/restore it. - * - * This makes NMPRulesManager stateful (beyond the configuration that indicates - * which rules are tracked). - * After a restart, NetworkManager would no longer remember which rules were added - * by us. - * - * That is partially fixed by NetworkManager taking over the rules that it - * actively configures (see %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG). */ - ConfigState config_state; + const NMPObject *obj; + CList obj_lst_head; + + /* indicates whether we configured/removed the rule (during sync()). We need that, so + * if the rule gets untracked, that we know to remove/restore it. + * + * This makes NMPRulesManager stateful (beyond the configuration that indicates + * which rules are tracked). + * After a restart, NetworkManager would no longer remember which rules were added + * by us. + * + * That is partially fixed by NetworkManager taking over the rules that it + * actively configures (see %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG). */ + ConfigState config_state; } RulesObjData; typedef struct { - gconstpointer user_tag; - CList user_tag_lst_head; + gconstpointer user_tag; + CList user_tag_lst_head; } RulesUserTagData; /*****************************************************************************/ -static void _rules_data_untrack (NMPRulesManager *self, - RulesData *rules_data, - gboolean remove_user_tag_data, - gboolean make_owned_by_us); +static void _rules_data_untrack(NMPRulesManager *self, + RulesData * rules_data, + gboolean remove_user_tag_data, + gboolean make_owned_by_us); /*****************************************************************************/ static void -_rules_data_assert (const RulesData *rules_data, gboolean linked) +_rules_data_assert(const RulesData *rules_data, gboolean linked) { - nm_assert (rules_data); - nm_assert (NMP_OBJECT_GET_TYPE (rules_data->obj) == NMP_OBJECT_TYPE_ROUTING_RULE); - nm_assert (nmp_object_is_visible (rules_data->obj)); - nm_assert (rules_data->user_tag); - nm_assert (!linked || !c_list_is_empty (&rules_data->obj_lst)); - nm_assert (!linked || !c_list_is_empty (&rules_data->user_tag_lst)); + nm_assert(rules_data); + nm_assert(NMP_OBJECT_GET_TYPE(rules_data->obj) == NMP_OBJECT_TYPE_ROUTING_RULE); + nm_assert(nmp_object_is_visible(rules_data->obj)); + nm_assert(rules_data->user_tag); + nm_assert(!linked || !c_list_is_empty(&rules_data->obj_lst)); + nm_assert(!linked || !c_list_is_empty(&rules_data->user_tag_lst)); } static guint -_rules_data_hash (gconstpointer data) +_rules_data_hash(gconstpointer data) { - const RulesData *rules_data = data; - NMHashState h; + const RulesData *rules_data = data; + NMHashState h; - _rules_data_assert (rules_data, FALSE); + _rules_data_assert(rules_data, FALSE); - nm_hash_init (&h, 269297543u); - nm_platform_routing_rule_hash_update (NMP_OBJECT_CAST_ROUTING_RULE (rules_data->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, - &h); - nm_hash_update_val (&h, rules_data->user_tag); - return nm_hash_complete (&h); + nm_hash_init(&h, 269297543u); + nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(rules_data->obj), + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, + &h); + nm_hash_update_val(&h, rules_data->user_tag); + return nm_hash_complete(&h); } static gboolean -_rules_data_equal (gconstpointer data_a, gconstpointer data_b) +_rules_data_equal(gconstpointer data_a, gconstpointer data_b) { - const RulesData *rules_data_a = data_a; - const RulesData *rules_data_b = data_b; + const RulesData *rules_data_a = data_a; + const RulesData *rules_data_b = data_b; - _rules_data_assert (rules_data_a, FALSE); - _rules_data_assert (rules_data_b, FALSE); + _rules_data_assert(rules_data_a, FALSE); + _rules_data_assert(rules_data_b, FALSE); - return rules_data_a->user_tag == rules_data_b->user_tag - && (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (rules_data_a->obj), - NMP_OBJECT_CAST_ROUTING_RULE (rules_data_b->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0); + return rules_data_a->user_tag == rules_data_b->user_tag + && (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(rules_data_a->obj), + NMP_OBJECT_CAST_ROUTING_RULE(rules_data_b->obj), + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) + == 0); } static void -_rules_data_destroy (gpointer data) +_rules_data_destroy(gpointer data) { - RulesData *rules_data = data; + RulesData *rules_data = data; - _rules_data_assert (rules_data, FALSE); + _rules_data_assert(rules_data, FALSE); - c_list_unlink_stale (&rules_data->obj_lst); - c_list_unlink_stale (&rules_data->user_tag_lst); - nmp_object_unref (rules_data->obj); - g_slice_free (RulesData, rules_data); + c_list_unlink_stale(&rules_data->obj_lst); + c_list_unlink_stale(&rules_data->user_tag_lst); + nmp_object_unref(rules_data->obj); + g_slice_free(RulesData, rules_data); } static const RulesData * -_rules_obj_get_best_data (RulesObjData *obj_data) +_rules_obj_get_best_data(RulesObjData *obj_data) { - RulesData *rules_data; - const RulesData *rd_best = NULL; - - c_list_for_each_entry (rules_data, &obj_data->obj_lst_head, obj_lst) { - - _rules_data_assert (rules_data, TRUE); - - if (rd_best) { - if (rd_best->track_priority_val > rules_data->track_priority_val) - continue; - if (rd_best->track_priority_val == rules_data->track_priority_val) { - if ( rd_best->track_priority_present - || !rules_data->track_priority_present) { - /* if the priorities are identical, then "present" wins over - * "!present" (absent). */ - continue; - } - } - } - - rd_best = rules_data; - } - - return rd_best; + RulesData * rules_data; + const RulesData *rd_best = NULL; + + c_list_for_each_entry (rules_data, &obj_data->obj_lst_head, obj_lst) { + _rules_data_assert(rules_data, TRUE); + + if (rd_best) { + if (rd_best->track_priority_val > rules_data->track_priority_val) + continue; + if (rd_best->track_priority_val == rules_data->track_priority_val) { + if (rd_best->track_priority_present || !rules_data->track_priority_present) { + /* if the priorities are identical, then "present" wins over + * "!present" (absent). */ + continue; + } + } + } + + rd_best = rules_data; + } + + return rd_best; } static guint -_rules_obj_hash (gconstpointer data) +_rules_obj_hash(gconstpointer data) { - const RulesObjData *obj_data = data; - NMHashState h; - - nm_hash_init (&h, 432817559u); - nm_platform_routing_rule_hash_update (NMP_OBJECT_CAST_ROUTING_RULE (obj_data->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, - &h); - return nm_hash_complete (&h); + const RulesObjData *obj_data = data; + NMHashState h; + + nm_hash_init(&h, 432817559u); + nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj), + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID, + &h); + return nm_hash_complete(&h); } static gboolean -_rules_obj_equal (gconstpointer data_a, gconstpointer data_b) +_rules_obj_equal(gconstpointer data_a, gconstpointer data_b) { - const RulesObjData *obj_data_a = data_a; - const RulesObjData *obj_data_b = data_b; + const RulesObjData *obj_data_a = data_a; + const RulesObjData *obj_data_b = data_b; - return (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (obj_data_a->obj), - NMP_OBJECT_CAST_ROUTING_RULE (obj_data_b->obj), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0); + return (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(obj_data_a->obj), + NMP_OBJECT_CAST_ROUTING_RULE(obj_data_b->obj), + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) + == 0); } static void -_rules_obj_destroy (gpointer data) +_rules_obj_destroy(gpointer data) { - RulesObjData *obj_data = data; + RulesObjData *obj_data = data; - c_list_unlink_stale (&obj_data->obj_lst_head); - nmp_object_unref (obj_data->obj); - g_slice_free (RulesObjData, obj_data); + c_list_unlink_stale(&obj_data->obj_lst_head); + nmp_object_unref(obj_data->obj); + g_slice_free(RulesObjData, obj_data); } static guint -_rules_user_tag_hash (gconstpointer data) +_rules_user_tag_hash(gconstpointer data) { - const RulesUserTagData *user_tag_data = data; + const RulesUserTagData *user_tag_data = data; - return nm_hash_val (644693447u, user_tag_data->user_tag); + return nm_hash_val(644693447u, user_tag_data->user_tag); } static gboolean -_rules_user_tag_equal (gconstpointer data_a, gconstpointer data_b) +_rules_user_tag_equal(gconstpointer data_a, gconstpointer data_b) { - const RulesUserTagData *user_tag_data_a = data_a; - const RulesUserTagData *user_tag_data_b = data_b; + const RulesUserTagData *user_tag_data_a = data_a; + const RulesUserTagData *user_tag_data_b = data_b; - return user_tag_data_a->user_tag == user_tag_data_b->user_tag; + return user_tag_data_a->user_tag == user_tag_data_b->user_tag; } static void -_rules_user_tag_destroy (gpointer data) +_rules_user_tag_destroy(gpointer data) { - RulesUserTagData *user_tag_data = data; + RulesUserTagData *user_tag_data = data; - c_list_unlink_stale (&user_tag_data->user_tag_lst_head); - g_slice_free (RulesUserTagData, user_tag_data); + c_list_unlink_stale(&user_tag_data->user_tag_lst_head); + g_slice_free(RulesUserTagData, user_tag_data); } static RulesData * -_rules_data_lookup (GHashTable *by_data, - const NMPObject *obj, - gconstpointer user_tag) +_rules_data_lookup(GHashTable *by_data, const NMPObject *obj, gconstpointer user_tag) { - RulesData rules_data_needle = { - .obj = obj, - .user_tag = user_tag, - }; + RulesData rules_data_needle = { + .obj = obj, + .user_tag = user_tag, + }; - return g_hash_table_lookup (by_data, &rules_data_needle); + return g_hash_table_lookup(by_data, &rules_data_needle); } /** @@ -305,496 +307,502 @@ _rules_data_lookup (GHashTable *by_data, * The purpose here is to set this to %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG. */ void -nmp_rules_manager_track (NMPRulesManager *self, - const NMPlatformRoutingRule *routing_rule, - gint32 track_priority, - gconstpointer user_tag, - gconstpointer user_tag_untrack) +nmp_rules_manager_track(NMPRulesManager * self, + const NMPlatformRoutingRule *routing_rule, + gint32 track_priority, + gconstpointer user_tag, + gconstpointer user_tag_untrack) { - NMPObject obj_stack; - const NMPObject *p_obj_stack; - RulesData *rules_data; - RulesObjData *obj_data; - RulesUserTagData *user_tag_data; - gboolean changed = FALSE; - guint32 track_priority_val; - gboolean track_priority_present; - - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); - g_return_if_fail (routing_rule); - g_return_if_fail (user_tag); - nm_assert (track_priority != G_MININT32); - - _rules_init (self); - - p_obj_stack = nmp_object_stackinit (&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule); - - nm_assert (nmp_object_is_visible (p_obj_stack)); - - if (track_priority >= 0) { - track_priority_val = track_priority; - track_priority_present = TRUE; - } else { - track_priority_val = -track_priority; - track_priority_present = FALSE; - } - - rules_data = _rules_data_lookup (self->by_data, p_obj_stack, user_tag); - - if (!rules_data) { - rules_data = g_slice_new (RulesData); - *rules_data = (RulesData) { - .obj = nm_dedup_multi_index_obj_intern (nm_platform_get_multi_idx (self->platform), - p_obj_stack), - .user_tag = user_tag, - .track_priority_val = track_priority_val, - .track_priority_present = track_priority_present, - .dirty = FALSE, - }; - g_hash_table_add (self->by_data, rules_data); - - obj_data = g_hash_table_lookup (self->by_obj, &rules_data->obj); - if (!obj_data) { - obj_data = g_slice_new (RulesObjData); - *obj_data = (RulesObjData) { - .obj = nmp_object_ref (rules_data->obj), - .obj_lst_head = C_LIST_INIT (obj_data->obj_lst_head), - .config_state = CONFIG_STATE_NONE, - }; - g_hash_table_add (self->by_obj, obj_data); - } - c_list_link_tail (&obj_data->obj_lst_head, &rules_data->obj_lst); - - user_tag_data = g_hash_table_lookup (self->by_user_tag, &rules_data->user_tag); - if (!user_tag_data) { - user_tag_data = g_slice_new (RulesUserTagData); - *user_tag_data = (RulesUserTagData) { - .user_tag = user_tag, - .user_tag_lst_head = C_LIST_INIT (user_tag_data->user_tag_lst_head), - }; - g_hash_table_add (self->by_user_tag, user_tag_data); - } - c_list_link_tail (&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst); - changed = TRUE; - } else { - rules_data->dirty = FALSE; - if ( rules_data->track_priority_val != track_priority_val - || rules_data->track_priority_present != track_priority_present) { - rules_data->track_priority_val = track_priority_val; - rules_data->track_priority_present = track_priority_present; - changed = TRUE; - } - } - - if (user_tag_untrack) { - if (user_tag != user_tag_untrack) { - RulesData *rules_data_untrack; - - rules_data_untrack = _rules_data_lookup (self->by_data, p_obj_stack, user_tag_untrack); - if (rules_data_untrack) - _rules_data_untrack (self, rules_data_untrack, FALSE, TRUE); - } else - nm_assert_not_reached (); - } - - _rules_data_assert (rules_data, TRUE); - - if (changed) { - _LOGD ("routing-rule: track ["NM_HASH_OBFUSCATE_PTR_FMT",%s%u] \"%s\")", - _USER_TAG_LOG (rules_data->user_tag), - ( rules_data->track_priority_val == 0 - ? "" - : ( rules_data->track_priority_present - ? "+" - : "-")), - (guint) rules_data->track_priority_val, - nmp_object_to_string (rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - } + NMPObject obj_stack; + const NMPObject * p_obj_stack; + RulesData * rules_data; + RulesObjData * obj_data; + RulesUserTagData *user_tag_data; + gboolean changed = FALSE; + guint32 track_priority_val; + gboolean track_priority_present; + + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); + g_return_if_fail(routing_rule); + g_return_if_fail(user_tag); + nm_assert(track_priority != G_MININT32); + + _rules_init(self); + + p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule); + + nm_assert(nmp_object_is_visible(p_obj_stack)); + + if (track_priority >= 0) { + track_priority_val = track_priority; + track_priority_present = TRUE; + } else { + track_priority_val = -track_priority; + track_priority_present = FALSE; + } + + rules_data = _rules_data_lookup(self->by_data, p_obj_stack, user_tag); + + if (!rules_data) { + rules_data = g_slice_new(RulesData); + *rules_data = (RulesData){ + .obj = nm_dedup_multi_index_obj_intern(nm_platform_get_multi_idx(self->platform), + p_obj_stack), + .user_tag = user_tag, + .track_priority_val = track_priority_val, + .track_priority_present = track_priority_present, + .dirty = FALSE, + }; + g_hash_table_add(self->by_data, rules_data); + + obj_data = g_hash_table_lookup(self->by_obj, &rules_data->obj); + if (!obj_data) { + obj_data = g_slice_new(RulesObjData); + *obj_data = (RulesObjData){ + .obj = nmp_object_ref(rules_data->obj), + .obj_lst_head = C_LIST_INIT(obj_data->obj_lst_head), + .config_state = CONFIG_STATE_NONE, + }; + g_hash_table_add(self->by_obj, obj_data); + } + c_list_link_tail(&obj_data->obj_lst_head, &rules_data->obj_lst); + + user_tag_data = g_hash_table_lookup(self->by_user_tag, &rules_data->user_tag); + if (!user_tag_data) { + user_tag_data = g_slice_new(RulesUserTagData); + *user_tag_data = (RulesUserTagData){ + .user_tag = user_tag, + .user_tag_lst_head = C_LIST_INIT(user_tag_data->user_tag_lst_head), + }; + g_hash_table_add(self->by_user_tag, user_tag_data); + } + c_list_link_tail(&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst); + changed = TRUE; + } else { + rules_data->dirty = FALSE; + if (rules_data->track_priority_val != track_priority_val + || rules_data->track_priority_present != track_priority_present) { + rules_data->track_priority_val = track_priority_val; + rules_data->track_priority_present = track_priority_present; + changed = TRUE; + } + } + + if (user_tag_untrack) { + if (user_tag != user_tag_untrack) { + RulesData *rules_data_untrack; + + rules_data_untrack = _rules_data_lookup(self->by_data, p_obj_stack, user_tag_untrack); + if (rules_data_untrack) + _rules_data_untrack(self, rules_data_untrack, FALSE, TRUE); + } else + nm_assert_not_reached(); + } + + _rules_data_assert(rules_data, TRUE); + + if (changed) { + _LOGD("routing-rule: track [" NM_HASH_OBFUSCATE_PTR_FMT ",%s%u] \"%s\")", + _USER_TAG_LOG(rules_data->user_tag), + (rules_data->track_priority_val == 0 + ? "" + : (rules_data->track_priority_present ? "+" : "-")), + (guint) rules_data->track_priority_val, + nmp_object_to_string(rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + } } static void -_rules_data_untrack (NMPRulesManager *self, - RulesData *rules_data, - gboolean remove_user_tag_data, - gboolean make_owned_by_us) +_rules_data_untrack(NMPRulesManager *self, + RulesData * rules_data, + gboolean remove_user_tag_data, + gboolean make_owned_by_us) { - RulesObjData *obj_data; + RulesObjData *obj_data; - nm_assert (NMP_IS_RULES_MANAGER (self)); - _rules_data_assert (rules_data, TRUE); - nm_assert (self->by_data); - nm_assert (g_hash_table_lookup (self->by_data, rules_data) == rules_data); + nm_assert(NMP_IS_RULES_MANAGER(self)); + _rules_data_assert(rules_data, TRUE); + nm_assert(self->by_data); + nm_assert(g_hash_table_lookup(self->by_data, rules_data) == rules_data); - _LOGD ("routing-rule: untrack ["NM_HASH_OBFUSCATE_PTR_FMT"] \"%s\"", - _USER_TAG_LOG (rules_data->user_tag), - nmp_object_to_string (rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + _LOGD("routing-rule: untrack [" NM_HASH_OBFUSCATE_PTR_FMT "] \"%s\"", + _USER_TAG_LOG(rules_data->user_tag), + nmp_object_to_string(rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); #if NM_MORE_ASSERTS - { - RulesUserTagData *user_tag_data; + { + RulesUserTagData *user_tag_data; - user_tag_data = g_hash_table_lookup (self->by_user_tag, &rules_data->user_tag); - nm_assert (user_tag_data); - nm_assert (c_list_contains (&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst)); - } + user_tag_data = g_hash_table_lookup(self->by_user_tag, &rules_data->user_tag); + nm_assert(user_tag_data); + nm_assert(c_list_contains(&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst)); + } #endif - nm_assert (!c_list_is_empty (&rules_data->user_tag_lst)); - - obj_data = g_hash_table_lookup (self->by_obj, &rules_data->obj); - nm_assert (obj_data); - nm_assert (c_list_contains (&obj_data->obj_lst_head, &rules_data->obj_lst)); - nm_assert (obj_data == g_hash_table_lookup (self->by_obj, &rules_data->obj)); - - if (make_owned_by_us) { - if (obj_data->config_state == CONFIG_STATE_NONE) { - /* we need to mark this entry that it requires a touch on the next - * sync. */ - obj_data->config_state = CONFIG_STATE_OWNED_BY_US; - } - } else if ( remove_user_tag_data - && c_list_length_is (&rules_data->user_tag_lst, 1)) - g_hash_table_remove (self->by_user_tag, &rules_data->user_tag); - - /* if obj_data is marked to be "added_by_us" or "removed_by_us", we need to keep this entry - * around for the next sync -- so that we can undo what we did earlier. */ - if ( obj_data->config_state == CONFIG_STATE_NONE - && c_list_length_is (&rules_data->obj_lst, 1)) - g_hash_table_remove (self->by_obj, &rules_data->obj); - - g_hash_table_remove (self->by_data, rules_data); + nm_assert(!c_list_is_empty(&rules_data->user_tag_lst)); + + obj_data = g_hash_table_lookup(self->by_obj, &rules_data->obj); + nm_assert(obj_data); + nm_assert(c_list_contains(&obj_data->obj_lst_head, &rules_data->obj_lst)); + nm_assert(obj_data == g_hash_table_lookup(self->by_obj, &rules_data->obj)); + + if (make_owned_by_us) { + if (obj_data->config_state == CONFIG_STATE_NONE) { + /* we need to mark this entry that it requires a touch on the next + * sync. */ + obj_data->config_state = CONFIG_STATE_OWNED_BY_US; + } + } else if (remove_user_tag_data && c_list_length_is(&rules_data->user_tag_lst, 1)) + g_hash_table_remove(self->by_user_tag, &rules_data->user_tag); + + /* if obj_data is marked to be "added_by_us" or "removed_by_us", we need to keep this entry + * around for the next sync -- so that we can undo what we did earlier. */ + if (obj_data->config_state == CONFIG_STATE_NONE && c_list_length_is(&rules_data->obj_lst, 1)) + g_hash_table_remove(self->by_obj, &rules_data->obj); + + g_hash_table_remove(self->by_data, rules_data); } void -nmp_rules_manager_untrack (NMPRulesManager *self, - const NMPlatformRoutingRule *routing_rule, - gconstpointer user_tag) +nmp_rules_manager_untrack(NMPRulesManager * self, + const NMPlatformRoutingRule *routing_rule, + gconstpointer user_tag) { - NMPObject obj_stack; - const NMPObject *p_obj_stack; - RulesData *rules_data; + NMPObject obj_stack; + const NMPObject *p_obj_stack; + RulesData * rules_data; - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); - g_return_if_fail (routing_rule); - g_return_if_fail (user_tag); + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); + g_return_if_fail(routing_rule); + g_return_if_fail(user_tag); - _rules_init (self); + _rules_init(self); - p_obj_stack = nmp_object_stackinit (&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule); + p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule); - nm_assert (nmp_object_is_visible (p_obj_stack)); + nm_assert(nmp_object_is_visible(p_obj_stack)); - rules_data = _rules_data_lookup (self->by_data, p_obj_stack, user_tag); - if (rules_data) - _rules_data_untrack (self, rules_data, TRUE, FALSE); + rules_data = _rules_data_lookup(self->by_data, p_obj_stack, user_tag); + if (rules_data) + _rules_data_untrack(self, rules_data, TRUE, FALSE); } void -nmp_rules_manager_set_dirty (NMPRulesManager *self, - gconstpointer user_tag) +nmp_rules_manager_set_dirty(NMPRulesManager *self, gconstpointer user_tag) { - RulesData *rules_data; - RulesUserTagData *user_tag_data; + RulesData * rules_data; + RulesUserTagData *user_tag_data; - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); - g_return_if_fail (user_tag); + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); + g_return_if_fail(user_tag); - if (!self->by_data) - return; + if (!self->by_data) + return; - user_tag_data = g_hash_table_lookup (self->by_user_tag, &user_tag); - if (!user_tag_data) - return; + user_tag_data = g_hash_table_lookup(self->by_user_tag, &user_tag); + if (!user_tag_data) + return; - c_list_for_each_entry (rules_data, &user_tag_data->user_tag_lst_head, user_tag_lst) - rules_data->dirty = TRUE; + c_list_for_each_entry (rules_data, &user_tag_data->user_tag_lst_head, user_tag_lst) + rules_data->dirty = TRUE; } void -nmp_rules_manager_untrack_all (NMPRulesManager *self, - gconstpointer user_tag, - gboolean all /* or only dirty */) +nmp_rules_manager_untrack_all(NMPRulesManager *self, + gconstpointer user_tag, + gboolean all /* or only dirty */) { - RulesData *rules_data; - RulesData *rules_data_safe; - RulesUserTagData *user_tag_data; - - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); - g_return_if_fail (user_tag); - - if (!self->by_data) - return; - - user_tag_data = g_hash_table_lookup (self->by_user_tag, &user_tag); - if (!user_tag_data) - return; - - c_list_for_each_entry_safe (rules_data, rules_data_safe, &user_tag_data->user_tag_lst_head, user_tag_lst) { - if ( all - || rules_data->dirty) - _rules_data_untrack (self, rules_data, FALSE, FALSE); - } - if (c_list_is_empty (&user_tag_data->user_tag_lst_head)) - g_hash_table_remove (self->by_user_tag, user_tag_data); + RulesData * rules_data; + RulesData * rules_data_safe; + RulesUserTagData *user_tag_data; + + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); + g_return_if_fail(user_tag); + + if (!self->by_data) + return; + + user_tag_data = g_hash_table_lookup(self->by_user_tag, &user_tag); + if (!user_tag_data) + return; + + c_list_for_each_entry_safe (rules_data, + rules_data_safe, + &user_tag_data->user_tag_lst_head, + user_tag_lst) { + if (all || rules_data->dirty) + _rules_data_untrack(self, rules_data, FALSE, FALSE); + } + if (c_list_is_empty(&user_tag_data->user_tag_lst_head)) + g_hash_table_remove(self->by_user_tag, user_tag_data); } void -nmp_rules_manager_sync (NMPRulesManager *self, - gboolean keep_deleted_rules) +nmp_rules_manager_sync(NMPRulesManager *self, gboolean keep_deleted_rules) { - const NMDedupMultiHeadEntry *pl_head_entry; - NMDedupMultiIter pl_iter; - const NMPObject *plobj; - gs_unref_ptrarray GPtrArray *rules_to_delete = NULL; - RulesObjData *obj_data; - GHashTableIter h_iter; - guint i; - const RulesData *rd_best; - - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); - - if (!self->by_data) - return; - - _LOGD ("sync%s", keep_deleted_rules ? " (don't remove any rules)" : ""); - - pl_head_entry = nm_platform_lookup_obj_type (self->platform, NMP_OBJECT_TYPE_ROUTING_RULE); - if (pl_head_entry) { - nmp_cache_iter_for_each (&pl_iter, pl_head_entry, &plobj) { - obj_data = g_hash_table_lookup (self->by_obj, &plobj); - - if (!obj_data) { - /* this rule is not tracked. It was externally added, hence we - * ignore it. */ - continue; - } - - rd_best = _rules_obj_get_best_data (obj_data); - if (rd_best) { - if (rd_best->track_priority_present) { - if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US) - obj_data->config_state = CONFIG_STATE_ADDED_BY_US; - continue; - } - if (rd_best->track_priority_val == 0) { - if (!NM_IN_SET (obj_data->config_state, CONFIG_STATE_ADDED_BY_US, - CONFIG_STATE_OWNED_BY_US)) { - obj_data->config_state = CONFIG_STATE_NONE; - continue; - } - obj_data->config_state = CONFIG_STATE_NONE; - } - } - - if (keep_deleted_rules) { - _LOGD ("forget/leak rule added by us: %s", nmp_object_to_string (plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - continue; - } - - if (!rules_to_delete) - rules_to_delete = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - - g_ptr_array_add (rules_to_delete, (gpointer) nmp_object_ref (plobj)); - - obj_data->config_state = CONFIG_STATE_REMOVED_BY_US; - } - } - - if (rules_to_delete) { - for (i = 0; i < rules_to_delete->len; i++) - nm_platform_object_delete (self->platform, rules_to_delete->pdata[i]); - } - - g_hash_table_iter_init (&h_iter, self->by_obj); - while (g_hash_table_iter_next (&h_iter, (gpointer *) &obj_data, NULL)) { - - rd_best = _rules_obj_get_best_data (obj_data); - - if (!rd_best) { - g_hash_table_iter_remove (&h_iter); - continue; - } - - if (!rd_best->track_priority_present) { - if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US) - obj_data->config_state = CONFIG_STATE_REMOVED_BY_US; - continue; - } - if (rd_best->track_priority_val == 0) { - if (!NM_IN_SET (obj_data->config_state, CONFIG_STATE_REMOVED_BY_US, - CONFIG_STATE_OWNED_BY_US)) { - obj_data->config_state = CONFIG_STATE_NONE; - continue; - } - obj_data->config_state = CONFIG_STATE_NONE; - } - - plobj = nm_platform_lookup_obj (self->platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj_data->obj); - if (plobj) - continue; - - obj_data->config_state = CONFIG_STATE_ADDED_BY_US; - nm_platform_routing_rule_add (self->platform, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_ROUTING_RULE (obj_data->obj)); - } + const NMDedupMultiHeadEntry *pl_head_entry; + NMDedupMultiIter pl_iter; + const NMPObject * plobj; + gs_unref_ptrarray GPtrArray *rules_to_delete = NULL; + RulesObjData * obj_data; + GHashTableIter h_iter; + guint i; + const RulesData * rd_best; + + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); + + if (!self->by_data) + return; + + _LOGD("sync%s", keep_deleted_rules ? " (don't remove any rules)" : ""); + + pl_head_entry = nm_platform_lookup_obj_type(self->platform, NMP_OBJECT_TYPE_ROUTING_RULE); + if (pl_head_entry) { + nmp_cache_iter_for_each (&pl_iter, pl_head_entry, &plobj) { + obj_data = g_hash_table_lookup(self->by_obj, &plobj); + + if (!obj_data) { + /* this rule is not tracked. It was externally added, hence we + * ignore it. */ + continue; + } + + rd_best = _rules_obj_get_best_data(obj_data); + if (rd_best) { + if (rd_best->track_priority_present) { + if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US) + obj_data->config_state = CONFIG_STATE_ADDED_BY_US; + continue; + } + if (rd_best->track_priority_val == 0) { + if (!NM_IN_SET(obj_data->config_state, + CONFIG_STATE_ADDED_BY_US, + CONFIG_STATE_OWNED_BY_US)) { + obj_data->config_state = CONFIG_STATE_NONE; + continue; + } + obj_data->config_state = CONFIG_STATE_NONE; + } + } + + if (keep_deleted_rules) { + _LOGD("forget/leak rule added by us: %s", + nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + continue; + } + + if (!rules_to_delete) + rules_to_delete = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + + g_ptr_array_add(rules_to_delete, (gpointer) nmp_object_ref(plobj)); + + obj_data->config_state = CONFIG_STATE_REMOVED_BY_US; + } + } + + if (rules_to_delete) { + for (i = 0; i < rules_to_delete->len; i++) + nm_platform_object_delete(self->platform, rules_to_delete->pdata[i]); + } + + g_hash_table_iter_init(&h_iter, self->by_obj); + while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj_data, NULL)) { + rd_best = _rules_obj_get_best_data(obj_data); + + if (!rd_best) { + g_hash_table_iter_remove(&h_iter); + continue; + } + + if (!rd_best->track_priority_present) { + if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US) + obj_data->config_state = CONFIG_STATE_REMOVED_BY_US; + continue; + } + if (rd_best->track_priority_val == 0) { + if (!NM_IN_SET(obj_data->config_state, + CONFIG_STATE_REMOVED_BY_US, + CONFIG_STATE_OWNED_BY_US)) { + obj_data->config_state = CONFIG_STATE_NONE; + continue; + } + obj_data->config_state = CONFIG_STATE_NONE; + } + + plobj = + nm_platform_lookup_obj(self->platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj_data->obj); + if (plobj) + continue; + + obj_data->config_state = CONFIG_STATE_ADDED_BY_US; + nm_platform_routing_rule_add(self->platform, + NMP_NLM_FLAG_ADD, + NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj)); + } } void -nmp_rules_manager_track_from_platform (NMPRulesManager *self, - NMPlatform *platform, - int addr_family, - gint32 tracking_priority, - gconstpointer user_tag) +nmp_rules_manager_track_from_platform(NMPRulesManager *self, + NMPlatform * platform, + int addr_family, + gint32 tracking_priority, + gconstpointer user_tag) { - NMPLookup lookup; - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; - const NMPObject *o; + NMPLookup lookup; + const NMDedupMultiHeadEntry *head_entry; + NMDedupMultiIter iter; + const NMPObject * o; - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - if (!platform) - platform = self->platform; - else - g_return_if_fail (NM_IS_PLATFORM (platform)); + if (!platform) + platform = self->platform; + else + g_return_if_fail(NM_IS_PLATFORM(platform)); - nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6)); + nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - head_entry = nm_platform_lookup (platform, &lookup); - nmp_cache_iter_for_each (&iter, head_entry, &o) { - const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (o); + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); + head_entry = nm_platform_lookup(platform, &lookup); + nmp_cache_iter_for_each (&iter, head_entry, &o) { + const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE(o); - if ( addr_family != AF_UNSPEC - && rr->addr_family != addr_family) - continue; + if (addr_family != AF_UNSPEC && rr->addr_family != addr_family) + continue; - nmp_rules_manager_track (self, rr, tracking_priority, user_tag, NULL); - } + nmp_rules_manager_track(self, rr, tracking_priority, user_tag, NULL); + } } /*****************************************************************************/ void -nmp_rules_manager_track_default (NMPRulesManager *self, - int addr_family, - gint32 track_priority, - gconstpointer user_tag) +nmp_rules_manager_track_default(NMPRulesManager *self, + int addr_family, + gint32 track_priority, + gconstpointer user_tag) { - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); - - nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - /* track the default rules. See also `man ip-rule`. */ - - if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) { - nmp_rules_manager_track (self, - &((NMPlatformRoutingRule) { - .addr_family = AF_INET, - .priority = 0, - .table = RT_TABLE_LOCAL, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - nmp_rules_manager_track (self, - &((NMPlatformRoutingRule) { - .addr_family = AF_INET, - .priority = 32766, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - nmp_rules_manager_track (self, - &((NMPlatformRoutingRule) { - .addr_family = AF_INET, - .priority = 32767, - .table = RT_TABLE_DEFAULT, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - } - if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) { - nmp_rules_manager_track (self, - &((NMPlatformRoutingRule) { - .addr_family = AF_INET6, - .priority = 0, - .table = RT_TABLE_LOCAL, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - nmp_rules_manager_track (self, - &((NMPlatformRoutingRule) { - .addr_family = AF_INET6, - .priority = 32766, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - .protocol = RTPROT_KERNEL, - }), - track_priority, - user_tag, - NULL); - } + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); + + nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); + + /* track the default rules. See also `man ip-rule`. */ + + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) { + nmp_rules_manager_track(self, + &((NMPlatformRoutingRule){ + .addr_family = AF_INET, + .priority = 0, + .table = RT_TABLE_LOCAL, + .action = FR_ACT_TO_TBL, + .protocol = RTPROT_KERNEL, + }), + track_priority, + user_tag, + NULL); + nmp_rules_manager_track(self, + &((NMPlatformRoutingRule){ + .addr_family = AF_INET, + .priority = 32766, + .table = RT_TABLE_MAIN, + .action = FR_ACT_TO_TBL, + .protocol = RTPROT_KERNEL, + }), + track_priority, + user_tag, + NULL); + nmp_rules_manager_track(self, + &((NMPlatformRoutingRule){ + .addr_family = AF_INET, + .priority = 32767, + .table = RT_TABLE_DEFAULT, + .action = FR_ACT_TO_TBL, + .protocol = RTPROT_KERNEL, + }), + track_priority, + user_tag, + NULL); + } + if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) { + nmp_rules_manager_track(self, + &((NMPlatformRoutingRule){ + .addr_family = AF_INET6, + .priority = 0, + .table = RT_TABLE_LOCAL, + .action = FR_ACT_TO_TBL, + .protocol = RTPROT_KERNEL, + }), + track_priority, + user_tag, + NULL); + nmp_rules_manager_track(self, + &((NMPlatformRoutingRule){ + .addr_family = AF_INET6, + .priority = 32766, + .table = RT_TABLE_MAIN, + .action = FR_ACT_TO_TBL, + .protocol = RTPROT_KERNEL, + }), + track_priority, + user_tag, + NULL); + } } static void -_rules_init (NMPRulesManager *self) +_rules_init(NMPRulesManager *self) { - if (self->by_data) - return; - - self->by_data = g_hash_table_new_full (_rules_data_hash, _rules_data_equal, NULL, _rules_data_destroy); - self->by_obj = g_hash_table_new_full (_rules_obj_hash, _rules_obj_equal, NULL, _rules_obj_destroy); - self->by_user_tag = g_hash_table_new_full (_rules_user_tag_hash, _rules_user_tag_equal, NULL, _rules_user_tag_destroy); + if (self->by_data) + return; + + self->by_data = + g_hash_table_new_full(_rules_data_hash, _rules_data_equal, NULL, _rules_data_destroy); + self->by_obj = + g_hash_table_new_full(_rules_obj_hash, _rules_obj_equal, NULL, _rules_obj_destroy); + self->by_user_tag = g_hash_table_new_full(_rules_user_tag_hash, + _rules_user_tag_equal, + NULL, + _rules_user_tag_destroy); } /*****************************************************************************/ NMPRulesManager * -nmp_rules_manager_new (NMPlatform *platform) +nmp_rules_manager_new(NMPlatform *platform) { - NMPRulesManager *self; + NMPRulesManager *self; - g_return_val_if_fail (NM_IS_PLATFORM (platform), NULL); + g_return_val_if_fail(NM_IS_PLATFORM(platform), NULL); - self = g_slice_new (NMPRulesManager); - *self = (NMPRulesManager) { - .ref_count = 1, - .platform = g_object_ref (platform), - }; - return self; + self = g_slice_new(NMPRulesManager); + *self = (NMPRulesManager){ + .ref_count = 1, + .platform = g_object_ref(platform), + }; + return self; } void -nmp_rules_manager_ref (NMPRulesManager *self) +nmp_rules_manager_ref(NMPRulesManager *self) { - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); - self->ref_count++; + self->ref_count++; } -void nmp_rules_manager_unref (NMPRulesManager *self) +void +nmp_rules_manager_unref(NMPRulesManager *self) { - g_return_if_fail (NMP_IS_RULES_MANAGER (self)); - - if (--self->ref_count > 0) - return; - - if (self->by_data) { - g_hash_table_destroy (self->by_user_tag); - g_hash_table_destroy (self->by_obj); - g_hash_table_destroy (self->by_data); - } - g_object_unref (self->platform); - g_slice_free (NMPRulesManager, self); + g_return_if_fail(NMP_IS_RULES_MANAGER(self)); + + if (--self->ref_count > 0) + return; + + if (self->by_data) { + g_hash_table_destroy(self->by_user_tag); + g_hash_table_destroy(self->by_obj); + g_hash_table_destroy(self->by_data); + } + g_object_unref(self->platform); + g_slice_free(NMPRulesManager, self); } diff --git a/src/platform/nmp-rules-manager.h b/src/platform/nmp-rules-manager.h index cf29ff45..29c1295c 100644 --- a/src/platform/nmp-rules-manager.h +++ b/src/platform/nmp-rules-manager.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ #ifndef __NMP_RULES_MANAGER_H__ #define __NMP_RULES_MANAGER_H__ @@ -11,44 +11,42 @@ typedef struct _NMPRulesManager NMPRulesManager; -NMPRulesManager *nmp_rules_manager_new (NMPlatform *platform); +NMPRulesManager *nmp_rules_manager_new(NMPlatform *platform); -void nmp_rules_manager_ref (NMPRulesManager *self); -void nmp_rules_manager_unref (NMPRulesManager *self); +void nmp_rules_manager_ref(NMPRulesManager *self); +void nmp_rules_manager_unref(NMPRulesManager *self); -#define nm_auto_unref_rules_manager nm_auto (_nmp_rules_manager_unref) -NM_AUTO_DEFINE_FCN0 (NMPRulesManager *, _nmp_rules_manager_unref, nmp_rules_manager_unref) +#define nm_auto_unref_rules_manager nm_auto(_nmp_rules_manager_unref) +NM_AUTO_DEFINE_FCN0(NMPRulesManager *, _nmp_rules_manager_unref, nmp_rules_manager_unref); -void nmp_rules_manager_track (NMPRulesManager *self, - const NMPlatformRoutingRule *routing_rule, - gint32 track_priority, - gconstpointer user_tag, - gconstpointer user_tag_untrack); +void nmp_rules_manager_track(NMPRulesManager * self, + const NMPlatformRoutingRule *routing_rule, + gint32 track_priority, + gconstpointer user_tag, + gconstpointer user_tag_untrack); -void nmp_rules_manager_track_default (NMPRulesManager *self, - int addr_family, - gint32 track_priority, - gconstpointer user_tag); +void nmp_rules_manager_track_default(NMPRulesManager *self, + int addr_family, + gint32 track_priority, + gconstpointer user_tag); -void nmp_rules_manager_track_from_platform (NMPRulesManager *self, - NMPlatform *platform, - int addr_family, - gint32 tracking_priority, - gconstpointer user_tag); +void nmp_rules_manager_track_from_platform(NMPRulesManager *self, + NMPlatform * platform, + int addr_family, + gint32 tracking_priority, + gconstpointer user_tag); -void nmp_rules_manager_untrack (NMPRulesManager *self, - const NMPlatformRoutingRule *routing_rule, - gconstpointer user_tag); +void nmp_rules_manager_untrack(NMPRulesManager * self, + const NMPlatformRoutingRule *routing_rule, + gconstpointer user_tag); -void nmp_rules_manager_set_dirty (NMPRulesManager *self, - gconstpointer user_tag); +void nmp_rules_manager_set_dirty(NMPRulesManager *self, gconstpointer user_tag); -void nmp_rules_manager_untrack_all (NMPRulesManager *self, - gconstpointer user_tag, - gboolean all /* or only dirty */); +void nmp_rules_manager_untrack_all(NMPRulesManager *self, + gconstpointer user_tag, + gboolean all /* or only dirty */); -void nmp_rules_manager_sync (NMPRulesManager *self, - gboolean keep_deleted_rules); +void nmp_rules_manager_sync(NMPRulesManager *self, gboolean keep_deleted_rules); /*****************************************************************************/ diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c index aec29b75..a8d0fad2 100644 --- a/src/platform/tests/monitor.c +++ b/src/platform/tests/monitor.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 Red Hat, Inc. */ @@ -12,61 +12,67 @@ #include "nm-test-utils-core.h" -NMTST_DEFINE (); +NMTST_DEFINE(); static struct { - gboolean persist; + gboolean persist; } global_opt = { - .persist = TRUE, + .persist = TRUE, }; static gboolean -read_argv (int *argc, char ***argv) +read_argv(int *argc, char ***argv) { - GOptionContext *context; - GOptionEntry options[] = { - { "no-persist", 'P', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &global_opt.persist, "Exit after processing netlink messages", NULL }, - { 0 }, - }; - gs_free_error GError *error = NULL; - - context = g_option_context_new (NULL); - g_option_context_set_summary (context, "Monitor netlink events in NMPlatform."); - g_option_context_add_main_entries (context, options, NULL); - - if (!g_option_context_parse (context, argc, argv, &error)) { - g_warning ("Error parsing command line arguments: %s", error->message); - g_option_context_free (context); - return FALSE; - } - - g_option_context_free (context); - return TRUE; + GOptionContext *context; + GOptionEntry options[] = { + {"no-persist", + 'P', + G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, + &global_opt.persist, + "Exit after processing netlink messages", + NULL}, + {0}, + }; + gs_free_error GError *error = NULL; + + context = g_option_context_new(NULL); + g_option_context_set_summary(context, "Monitor netlink events in NMPlatform."); + g_option_context_add_main_entries(context, options, NULL); + + if (!g_option_context_parse(context, argc, argv, &error)) { + g_warning("Error parsing command line arguments: %s", error->message); + g_option_context_free(context); + return FALSE; + } + + g_option_context_free(context); + return TRUE; } int -main (int argc, char **argv) +main(int argc, char **argv) { - GMainLoop *loop; + GMainLoop *loop; - if (!g_getenv ("G_MESSAGES_DEBUG")) - g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + if (!g_getenv("G_MESSAGES_DEBUG")) + g_setenv("G_MESSAGES_DEBUG", "all", TRUE); - nmtst_init_with_logging (&argc, &argv, "DEBUG", "ALL"); + nmtst_init_with_logging(&argc, &argv, "DEBUG", "ALL"); - if (!read_argv (&argc, &argv)) - return 2; + if (!read_argv(&argc, &argv)) + return 2; - nm_log_info (LOGD_PLATFORM, "platform monitor start"); + nm_log_info(LOGD_PLATFORM, "platform monitor start"); - loop = g_main_loop_new (NULL, FALSE); + loop = g_main_loop_new(NULL, FALSE); - nm_linux_platform_setup (); + nm_linux_platform_setup(); - if (global_opt.persist) - g_main_loop_run (loop); + if (global_opt.persist) + g_main_loop_run(loop); - g_main_loop_unref (loop); + g_main_loop_unref(loop); - return EXIT_SUCCESS; + return EXIT_SUCCESS; } diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index 26072400..5ea30a57 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 Red Hat, Inc. */ @@ -7,12 +7,12 @@ #include "test-common.h" -#define IP4_ADDRESS "192.0.2.1" -#define IP4_ADDRESS_PEER "192.0.2.2" +#define IP4_ADDRESS "192.0.2.1" +#define IP4_ADDRESS_PEER "192.0.2.2" #define IP4_ADDRESS_PEER2 "192.0.3.1" -#define IP4_PLEN 24 -#define IP6_ADDRESS "2001:db8:a:b:1:2:3:4" -#define IP6_PLEN 64 +#define IP4_PLEN 24 +#define IP6_ADDRESS "2001:db8:a:b:1:2:3:4" +#define IP6_PLEN 64 #define DEVICE_IFINDEX NMTSTP_ENV1_IFINDEX #define EX NMTSTP_ENV1_EX @@ -20,320 +20,420 @@ /*****************************************************************************/ static void -ip4_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformIP4Address *received, NMPlatformSignalChangeType change_type, SignalData *data) +ip4_address_callback(NMPlatform * platform, + NMPObjectType obj_type, + int ifindex, + NMPlatformIP4Address * received, + NMPlatformSignalChangeType change_type, + SignalData * data) { - g_assert (received); - g_assert_cmpint (received->ifindex, ==, ifindex); - g_assert (data && data->name); - g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED); + g_assert(received); + g_assert_cmpint(received->ifindex, ==, ifindex); + g_assert(data && data->name); + g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED); - if (data->ifindex && data->ifindex != received->ifindex) - return; - if (data->change_type != change_type) - return; + if (data->ifindex && data->ifindex != received->ifindex) + return; + if (data->change_type != change_type) + return; - if (data->loop) - g_main_loop_quit (data->loop); + if (data->loop) + g_main_loop_quit(data->loop); - data->received_count++; - _LOGD ("Received signal '%s' %dth time.", data->name, data->received_count); + data->received_count++; + _LOGD("Received signal '%s' %dth time.", data->name, data->received_count); } static void -ip6_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformIP6Address *received, NMPlatformSignalChangeType change_type, SignalData *data) +ip6_address_callback(NMPlatform * platform, + NMPObjectType obj_type, + int ifindex, + NMPlatformIP6Address * received, + NMPlatformSignalChangeType change_type, + SignalData * data) { - g_assert (received); - g_assert_cmpint (received->ifindex, ==, ifindex); - g_assert (data && data->name); - g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED); + g_assert(received); + g_assert_cmpint(received->ifindex, ==, ifindex); + g_assert(data && data->name); + g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED); - if (data->ifindex && data->ifindex != received->ifindex) - return; - if (data->change_type != change_type) - return; + if (data->ifindex && data->ifindex != received->ifindex) + return; + if (data->change_type != change_type) + return; - if (data->loop) - g_main_loop_quit (data->loop); + if (data->loop) + g_main_loop_quit(data->loop); - data->received_count++; - _LOGD ("Received signal '%s' %dth time.", data->name, data->received_count); + data->received_count++; + _LOGD("Received signal '%s' %dth time.", data->name, data->received_count); } /*****************************************************************************/ static void -test_ip4_address_general (void) +test_ip4_address_general(void) { - const int ifindex = DEVICE_IFINDEX; - SignalData *address_added = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_address_callback, ifindex); - SignalData *address_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip4_address_callback, ifindex); - SignalData *address_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_address_callback, ifindex); - GArray *addresses; - NMPlatformIP4Address *address; - in_addr_t addr; - guint32 lifetime = 2000; - guint32 preferred = 1000; - - inet_pton (AF_INET, IP4_ADDRESS, &addr); - - /* Add address */ - g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); - nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); - g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); - accept_signal (address_added); - - /* Add address again (aka update) */ - nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, 0, NULL); - accept_signals (address_changed, 0, 1); - - /* Test address listing */ - addresses = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); - g_assert (addresses); - g_assert_cmpint (addresses->len, ==, 1); - address = &g_array_index (addresses, NMPlatformIP4Address, 0); - g_assert_cmpint (address->ifindex, ==, ifindex); - g_assert_cmphex (address->address, ==, addr); - g_assert_cmphex (address->peer_address, ==, addr); - g_assert_cmpint (address->plen, ==, IP4_PLEN); - g_array_unref (addresses); - - /* Remove address */ - nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr); - g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); - accept_signal (address_removed); - - /* Remove address again */ - nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr); - - free_signal (address_added); - free_signal (address_changed); - free_signal (address_removed); + const int ifindex = DEVICE_IFINDEX; + SignalData *address_added = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip4_address_callback, + ifindex); + SignalData *address_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + ip4_address_callback, + ifindex); + SignalData *address_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip4_address_callback, + ifindex); + GArray * addresses; + NMPlatformIP4Address *address; + in_addr_t addr; + guint32 lifetime = 2000; + guint32 preferred = 1000; + + inet_pton(AF_INET, IP4_ADDRESS, &addr); + + /* Add address */ + g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); + nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); + g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); + accept_signal(address_added); + + /* Add address again (aka update) */ + nmtstp_ip4_address_add(NULL, + EX, + ifindex, + addr, + IP4_PLEN, + addr, + lifetime + 100, + preferred + 50, + 0, + NULL); + accept_signals(address_changed, 0, 1); + + /* Test address listing */ + addresses = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex); + g_assert(addresses); + g_assert_cmpint(addresses->len, ==, 1); + address = &g_array_index(addresses, NMPlatformIP4Address, 0); + g_assert_cmpint(address->ifindex, ==, ifindex); + g_assert_cmphex(address->address, ==, addr); + g_assert_cmphex(address->peer_address, ==, addr); + g_assert_cmpint(address->plen, ==, IP4_PLEN); + g_array_unref(addresses); + + /* Remove address */ + nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr); + g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); + accept_signal(address_removed); + + /* Remove address again */ + nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr); + + free_signal(address_added); + free_signal(address_changed); + free_signal(address_removed); } static void -test_ip6_address_general (void) +test_ip6_address_general(void) { - const int ifindex = DEVICE_IFINDEX; - SignalData *address_added = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_address_callback, ifindex); - SignalData *address_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip6_address_callback, ifindex); - SignalData *address_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip6_address_callback, ifindex); - GArray *addresses; - NMPlatformIP6Address *address; - struct in6_addr addr; - guint32 lifetime = 2000; - guint32 preferred = 1000; - guint flags = 0; - - inet_pton (AF_INET6, IP6_ADDRESS, &addr); - - /* Add address */ - g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); - nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); - accept_signal (address_added); - - /* Add address again (aka update) */ - nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags); - accept_signals (address_changed, 0, 2); - - /* Test address listing */ - addresses = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); - g_assert (addresses); - g_assert_cmpint (addresses->len, ==, 1); - address = &g_array_index (addresses, NMPlatformIP6Address, 0); - g_assert_cmpint (address->ifindex, ==, ifindex); - g_assert (!memcmp (&address->address, &addr, sizeof (addr))); - g_assert_cmpint (address->plen, ==, IP6_PLEN); - g_array_unref (addresses); - - /* Remove address */ - nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN); - g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); - accept_signal (address_removed); - - /* Remove address again */ - nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN); - - /* ensure not pending signal. */ - accept_signals (address_changed, 0, 1); - - free_signal (address_added); - free_signal (address_changed); - free_signal (address_removed); + const int ifindex = DEVICE_IFINDEX; + SignalData *address_added = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip6_address_callback, + ifindex); + SignalData *address_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + ip6_address_callback, + ifindex); + SignalData *address_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip6_address_callback, + ifindex); + GArray * addresses; + NMPlatformIP6Address *address; + struct in6_addr addr; + guint32 lifetime = 2000; + guint32 preferred = 1000; + guint flags = 0; + + inet_pton(AF_INET6, IP6_ADDRESS, &addr); + + /* Add address */ + g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr)); + nmtstp_ip6_address_add(NULL, + EX, + ifindex, + addr, + IP6_PLEN, + in6addr_any, + lifetime, + preferred, + flags); + g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr)); + accept_signal(address_added); + + /* Add address again (aka update) */ + nmtstp_ip6_address_add(NULL, + EX, + ifindex, + addr, + IP6_PLEN, + in6addr_any, + lifetime, + preferred, + flags); + accept_signals(address_changed, 0, 2); + + /* Test address listing */ + addresses = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex); + g_assert(addresses); + g_assert_cmpint(addresses->len, ==, 1); + address = &g_array_index(addresses, NMPlatformIP6Address, 0); + g_assert_cmpint(address->ifindex, ==, ifindex); + g_assert(!memcmp(&address->address, &addr, sizeof(addr))); + g_assert_cmpint(address->plen, ==, IP6_PLEN); + g_array_unref(addresses); + + /* Remove address */ + nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN); + g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr)); + accept_signal(address_removed); + + /* Remove address again */ + nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN); + + /* ensure not pending signal. */ + accept_signals(address_changed, 0, 1); + + free_signal(address_added); + free_signal(address_changed); + free_signal(address_removed); } static void -test_ip4_address_general_2 (void) +test_ip4_address_general_2(void) { - const int ifindex = DEVICE_IFINDEX; - SignalData *address_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_address_callback); - SignalData *address_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_address_callback); - in_addr_t addr; - guint32 lifetime = 2000; - guint32 preferred = 1000; - - inet_pton (AF_INET, IP4_ADDRESS, &addr); - g_assert (ifindex > 0); - - /* Looks like addresses are not announced by kernel when the interface - * is down. Link-local IPv6 address is automatically added. - */ - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, DEVICE_IFINDEX, NULL)); - - /* Add/delete notification */ - nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); - accept_signal (address_added); - g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); - nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr); - accept_signal (address_removed); - g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); - - /* Add/delete conflict */ - nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); - g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); - accept_signal (address_added); - - free_signal (address_added); - free_signal (address_removed); + const int ifindex = DEVICE_IFINDEX; + SignalData *address_added = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip4_address_callback); + SignalData *address_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip4_address_callback); + in_addr_t addr; + guint32 lifetime = 2000; + guint32 preferred = 1000; + + inet_pton(AF_INET, IP4_ADDRESS, &addr); + g_assert(ifindex > 0); + + /* Looks like addresses are not announced by kernel when the interface + * is down. Link-local IPv6 address is automatically added. + */ + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, DEVICE_IFINDEX, NULL)); + + /* Add/delete notification */ + nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); + accept_signal(address_added); + g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); + nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr); + accept_signal(address_removed); + g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); + + /* Add/delete conflict */ + nmtstp_ip4_address_add(NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL); + g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr)); + accept_signal(address_added); + + free_signal(address_added); + free_signal(address_removed); } static void -test_ip6_address_general_2 (void) +test_ip6_address_general_2(void) { - const int ifindex = DEVICE_IFINDEX; - SignalData *address_added = add_signal (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_address_callback); - SignalData *address_removed = add_signal (NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip6_address_callback); - struct in6_addr addr; - guint32 lifetime = 2000; - guint32 preferred = 1000; - guint flags = 0; - - inet_pton (AF_INET6, IP6_ADDRESS, &addr); - - /* Add/delete notification */ - nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0); - accept_signal (address_added); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); - - nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN); - accept_signal (address_removed); - g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); - - /* Add/delete conflict */ - nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0); - accept_signal (address_added); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); - - nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags); - ensure_no_signal (address_added); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); - - free_signal (address_added); - free_signal (address_removed); + const int ifindex = DEVICE_IFINDEX; + SignalData * address_added = add_signal(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip6_address_callback); + SignalData * address_removed = add_signal(NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip6_address_callback); + struct in6_addr addr; + guint32 lifetime = 2000; + guint32 preferred = 1000; + guint flags = 0; + + inet_pton(AF_INET6, IP6_ADDRESS, &addr); + + /* Add/delete notification */ + nmtstp_ip6_address_add(NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0); + accept_signal(address_added); + g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr)); + + nmtstp_ip6_address_del(NULL, EX, ifindex, addr, IP6_PLEN); + accept_signal(address_removed); + g_assert(!nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr)); + + /* Add/delete conflict */ + nmtstp_ip6_address_add(NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0); + accept_signal(address_added); + g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr)); + + nmtstp_ip6_address_add(NULL, + EX, + ifindex, + addr, + IP6_PLEN, + in6addr_any, + lifetime, + preferred, + flags); + ensure_no_signal(address_added); + g_assert(nm_platform_ip6_address_get(NM_PLATFORM_GET, ifindex, &addr)); + + free_signal(address_added); + free_signal(address_removed); } /*****************************************************************************/ static void -test_ip4_address_peer (void) +test_ip4_address_peer(void) { - const int ifindex = DEVICE_IFINDEX; - SignalData *address_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_address_callback); - SignalData *address_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_address_callback); - in_addr_t addr, addr_peer, addr_peer2; - guint32 lifetime = 2000; - guint32 preferred = 1000; - const NMPlatformIP4Address *a; - - inet_pton (AF_INET, IP4_ADDRESS, &addr); - inet_pton (AF_INET, IP4_ADDRESS_PEER, &addr_peer); - inet_pton (AF_INET, IP4_ADDRESS_PEER2, &addr_peer2); - g_assert (ifindex > 0); - - g_assert (addr != addr_peer); - - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL)); - accept_signals (address_removed, 0, G_MAXINT); - accept_signals (address_added, 0, G_MAXINT); - - /* Add/delete notification */ - nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, 0, NULL); - accept_signal (address_added); - a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer); - g_assert (a); - g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2)); - - nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred); - - nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, 0, NULL); - accept_signal (address_added); - g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer)); - a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2); - g_assert (a); - - nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred); - - g_assert (addr != addr_peer); - nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer); - accept_signal (address_removed); - g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer)); - g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2)); - - free_signal (address_added); - free_signal (address_removed); + const int ifindex = DEVICE_IFINDEX; + SignalData * address_added = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip4_address_callback); + SignalData * address_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip4_address_callback); + in_addr_t addr, addr_peer, addr_peer2; + guint32 lifetime = 2000; + guint32 preferred = 1000; + const NMPlatformIP4Address *a; + + inet_pton(AF_INET, IP4_ADDRESS, &addr); + inet_pton(AF_INET, IP4_ADDRESS_PEER, &addr_peer); + inet_pton(AF_INET, IP4_ADDRESS_PEER2, &addr_peer2); + g_assert(ifindex > 0); + + g_assert(addr != addr_peer); + + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + accept_signals(address_removed, 0, G_MAXINT); + accept_signals(address_added, 0, G_MAXINT); + + /* Add/delete notification */ + nmtstp_ip4_address_add(NULL, + EX, + ifindex, + addr, + IP4_PLEN, + addr_peer, + lifetime, + preferred, + 0, + NULL); + accept_signal(address_added); + a = nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer); + g_assert(a); + g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2)); + + nmtstp_ip_address_assert_lifetime((NMPlatformIPAddress *) a, -1, lifetime, preferred); + + nmtstp_ip4_address_add(NULL, + EX, + ifindex, + addr, + IP4_PLEN, + addr_peer2, + lifetime, + preferred, + 0, + NULL); + accept_signal(address_added); + g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer)); + a = nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2); + g_assert(a); + + nmtstp_ip_address_assert_lifetime((NMPlatformIPAddress *) a, -1, lifetime, preferred); + + g_assert(addr != addr_peer); + nmtstp_ip4_address_del(NULL, EX, ifindex, addr, IP4_PLEN, addr_peer); + accept_signal(address_removed); + g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer)); + g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2)); + + free_signal(address_added); + free_signal(address_removed); } /*****************************************************************************/ static void -test_ip4_address_peer_zero (void) +test_ip4_address_peer_zero(void) { - const int ifindex = DEVICE_IFINDEX; - in_addr_t addr, addr_peer; - guint32 lifetime = 2000; - guint32 preferred = 1000; - const gint8 plen = 24; - const char *label = NULL; - in_addr_t peers[3], r_peers[3]; - int i; - GArray *addrs; - - g_assert (ifindex > 0); - - inet_pton (AF_INET, "192.168.5.2", &addr); - inet_pton (AF_INET, "192.168.6.2", &addr_peer); - peers[0] = addr; - peers[1] = addr_peer; - peers[2] = 0; - - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL)); - - nmtst_rand_perm (NULL, r_peers, peers, sizeof (peers[0]), G_N_ELEMENTS (peers)); - for (i = 0; i < G_N_ELEMENTS (peers); i++) { - g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i])); - - nmtstp_ip4_address_add (NULL, EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label); - - addrs = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); - g_assert (addrs); - g_assert_cmpint (addrs->len, ==, i + 1); - g_array_unref (addrs); - } - - if (nmtst_is_debug () && nmtstp_is_root_test ()) - nmtstp_run_command_check ("ip address show dev %s", DEVICE_NAME); - - nmtst_rand_perm (NULL, r_peers, peers, sizeof (peers[0]), G_N_ELEMENTS (peers)); - for (i = 0; i < G_N_ELEMENTS (peers); i++) { - g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i])); - - nmtstp_ip4_address_del (NULL, EX, ifindex, addr, plen, r_peers[i]); - - addrs = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); - g_assert (addrs); - g_assert_cmpint (addrs->len, ==, G_N_ELEMENTS (peers) - i - 1); - g_array_unref (addrs); - } + const int ifindex = DEVICE_IFINDEX; + in_addr_t addr, addr_peer; + guint32 lifetime = 2000; + guint32 preferred = 1000; + const gint8 plen = 24; + const char *label = NULL; + in_addr_t peers[3], r_peers[3]; + int i; + GArray * addrs; + + g_assert(ifindex > 0); + + inet_pton(AF_INET, "192.168.5.2", &addr); + inet_pton(AF_INET, "192.168.6.2", &addr_peer); + peers[0] = addr; + peers[1] = addr_peer; + peers[2] = 0; + + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + + nmtst_rand_perm(NULL, r_peers, peers, sizeof(peers[0]), G_N_ELEMENTS(peers)); + for (i = 0; i < G_N_ELEMENTS(peers); i++) { + g_assert(!nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i])); + + nmtstp_ip4_address_add(NULL, + EX, + ifindex, + addr, + plen, + r_peers[i], + lifetime, + preferred, + 0, + label); + + addrs = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex); + g_assert(addrs); + g_assert_cmpint(addrs->len, ==, i + 1); + g_array_unref(addrs); + } + + if (nmtst_is_debug() && nmtstp_is_root_test()) + nmtstp_run_command_check("ip address show dev %s", DEVICE_NAME); + + nmtst_rand_perm(NULL, r_peers, peers, sizeof(peers[0]), G_N_ELEMENTS(peers)); + for (i = 0; i < G_N_ELEMENTS(peers); i++) { + g_assert(nm_platform_ip4_address_get(NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i])); + + nmtstp_ip4_address_del(NULL, EX, ifindex, addr, plen, r_peers[i]); + + addrs = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex); + g_assert(addrs); + g_assert_cmpint(addrs->len, ==, G_N_ELEMENTS(peers) - i - 1); + g_array_unref(addrs); + } } /*****************************************************************************/ @@ -341,9 +441,9 @@ test_ip4_address_peer_zero (void) NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; void -_nmtstp_init_tests (int *argc, char ***argv) +_nmtstp_init_tests(int *argc, char ***argv) { - nmtst_init_with_logging (argc, argv, NULL, "ALL"); + nmtst_init_with_logging(argc, argv, NULL, "ALL"); } /***************************************************************************** @@ -351,15 +451,15 @@ _nmtstp_init_tests (int *argc, char ***argv) *****************************************************************************/ void -_nmtstp_setup_tests (void) +_nmtstp_setup_tests(void) { #define add_test_func(testpath, test_func) nmtstp_env1_add_test_func(testpath, test_func, FALSE) - add_test_func ("/address/ipv4/general", test_ip4_address_general); - add_test_func ("/address/ipv6/general", test_ip6_address_general); + add_test_func("/address/ipv4/general", test_ip4_address_general); + add_test_func("/address/ipv6/general", test_ip6_address_general); - add_test_func ("/address/ipv4/general-2", test_ip4_address_general_2); - add_test_func ("/address/ipv6/general-2", test_ip6_address_general_2); + add_test_func("/address/ipv4/general-2", test_ip4_address_general_2); + add_test_func("/address/ipv6/general-2", test_ip6_address_general_2); - add_test_func ("/address/ipv4/peer", test_ip4_address_peer); - add_test_func ("/address/ipv4/peer/zero", test_ip4_address_peer_zero); + add_test_func("/address/ipv4/peer", test_ip4_address_peer); + add_test_func("/address/ipv4/peer/zero", test_ip4_address_peer_zero); } diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index d19ff1f0..c364bfa1 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 Red Hat, Inc. */ @@ -8,113 +8,181 @@ #include "test-common.h" static void -test_cleanup_internal (void) +test_cleanup_internal(void) { - SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); - int ifindex; - GArray *addresses4; - GArray *addresses6; - GPtrArray *routes4; - GPtrArray *routes6; - in_addr_t addr4; - in_addr_t network4; - int plen4 = 24; - in_addr_t gateway4; - struct in6_addr addr6; - struct in6_addr network6; - int plen6 = 64; - struct in6_addr gateway6; - int lifetime = NM_PLATFORM_LIFETIME_PERMANENT; - int preferred = NM_PLATFORM_LIFETIME_PERMANENT; - int metric = 20; - int mss = 1000; - guint32 flags = 0; - - inet_pton (AF_INET, "192.0.2.1", &addr4); - inet_pton (AF_INET, "192.0.3.0", &network4); - inet_pton (AF_INET, "198.51.100.1", &gateway4); - inet_pton (AF_INET6, "2001:db8:a:b:1:2:3:4", &addr6); - inet_pton (AF_INET6, "2001:db8:c:d:0:0:0:0", &network6); - inet_pton (AF_INET6, "2001:db8:e:f:1:2:3:4", &gateway6); - - /* Create and set up device */ - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL))); - accept_signal (link_added); - free_signal (link_added); - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME), NULL)); - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert (ifindex > 0); - - /* wait for kernel to add the IPv6 link local address... it takes a bit. */ - NMTST_WAIT_ASSERT (300, { - gs_unref_array GArray *addrs = NULL; - const NMPlatformIP6Address *a; - - if (nmtst_wait_iteration > 0) { - nmtstp_wait_for_signal (NM_PLATFORM_GET, nmtst_wait_remaining_us / 1000); - nm_platform_process_events (NM_PLATFORM_GET); - } - addrs = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); - if ( addrs->len == 1 - && (a = &g_array_index (addrs, NMPlatformIP6Address, 0)) - && IN6_IS_ADDR_LINKLOCAL (&a->address)) - break; - }); - - g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, nm_platform_ip4_broadcast_address_create (addr4, plen4), lifetime, preferred, 0, NULL)); - g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags)); - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss); - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss); - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway4, 0, metric, mss); - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway6, 128, in6addr_any, in6addr_any, metric, mss); - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, in6addr_any, metric, mss); - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, in6addr_any, metric, mss); - - addresses4 = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); - addresses6 = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); - routes4 = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); - routes6 = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex); - - g_assert_cmpint (addresses4->len, ==, 1); - g_assert_cmpint (addresses6->len, ==, 2); /* also has a IPv6 LL address. */ - g_assert_cmpint (routes4->len, ==, 3); - g_assert_cmpint (routes6->len, ==, 3); - - g_array_unref (addresses4); - g_array_unref (addresses6); - g_ptr_array_unref (routes4); - g_ptr_array_unref (routes6); - - /* Delete interface with all addresses and routes */ - g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex)); - - addresses4 = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); - addresses6 = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); - routes4 = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); - routes6 = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex); - - g_assert_cmpint (addresses4->len, ==, 0); - g_assert_cmpint (addresses6->len, ==, 0); - g_assert (!routes4); - g_assert (!routes6); - - g_array_unref (addresses4); - g_array_unref (addresses6); + SignalData * link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + link_callback, + DEVICE_NAME); + int ifindex; + GArray * addresses4; + GArray * addresses6; + GPtrArray * routes4; + GPtrArray * routes6; + in_addr_t addr4; + in_addr_t network4; + int plen4 = 24; + in_addr_t gateway4; + struct in6_addr addr6; + struct in6_addr network6; + int plen6 = 64; + struct in6_addr gateway6; + int lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + int preferred = NM_PLATFORM_LIFETIME_PERMANENT; + int metric = 20; + int mss = 1000; + guint32 flags = 0; + + inet_pton(AF_INET, "192.0.2.1", &addr4); + inet_pton(AF_INET, "192.0.3.0", &network4); + inet_pton(AF_INET, "198.51.100.1", &gateway4); + inet_pton(AF_INET6, "2001:db8:a:b:1:2:3:4", &addr6); + inet_pton(AF_INET6, "2001:db8:c:d:0:0:0:0", &network6); + inet_pton(AF_INET6, "2001:db8:e:f:1:2:3:4", &gateway6); + + /* Create and set up device */ + g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL))); + accept_signal(link_added); + free_signal(link_added); + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, + nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME), + NULL)); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert(ifindex > 0); + + /* wait for kernel to add the IPv6 link local address... it takes a bit. */ + NMTST_WAIT_ASSERT(300, { + gs_unref_array GArray * addrs = NULL; + const NMPlatformIP6Address *a; + + if (nmtst_wait_iteration > 0) { + nmtstp_wait_for_signal(NM_PLATFORM_GET, nmtst_wait_remaining_us / 1000); + nm_platform_process_events(NM_PLATFORM_GET); + } + addrs = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex); + if (addrs->len == 1 && (a = &g_array_index(addrs, NMPlatformIP6Address, 0)) + && IN6_IS_ADDR_LINKLOCAL(&a->address)) + break; + }); + + g_assert(nm_platform_ip4_address_add(NM_PLATFORM_GET, + ifindex, + addr4, + plen4, + addr4, + nm_platform_ip4_broadcast_address_create(addr4, plen4), + lifetime, + preferred, + 0, + NULL)); + g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET, + ifindex, + addr6, + plen6, + in6addr_any, + lifetime, + preferred, + flags)); + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + gateway4, + 32, + INADDR_ANY, + 0, + metric, + mss); + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network4, + plen4, + gateway4, + 0, + metric, + mss); + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + 0, + 0, + gateway4, + 0, + metric, + mss); + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + gateway6, + 128, + in6addr_any, + in6addr_any, + metric, + mss); + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network6, + plen6, + gateway6, + in6addr_any, + metric, + mss); + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + in6addr_any, + 0, + gateway6, + in6addr_any, + metric, + mss); + + addresses4 = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex); + addresses6 = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex); + routes4 = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex); + routes6 = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex); + + g_assert_cmpint(addresses4->len, ==, 1); + g_assert_cmpint(addresses6->len, ==, 2); /* also has a IPv6 LL address. */ + g_assert_cmpint(routes4->len, ==, 3); + g_assert_cmpint(routes6->len, ==, 3); + + g_array_unref(addresses4); + g_array_unref(addresses6); + g_ptr_array_unref(routes4); + g_ptr_array_unref(routes6); + + /* Delete interface with all addresses and routes */ + g_assert(nm_platform_link_delete(NM_PLATFORM_GET, ifindex)); + + addresses4 = nmtstp_platform_ip4_address_get_all(NM_PLATFORM_GET, ifindex); + addresses6 = nmtstp_platform_ip6_address_get_all(NM_PLATFORM_GET, ifindex); + routes4 = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex); + routes6 = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex); + + g_assert_cmpint(addresses4->len, ==, 0); + g_assert_cmpint(addresses6->len, ==, 0); + g_assert(!routes4); + g_assert(!routes6); + + g_array_unref(addresses4); + g_array_unref(addresses6); } NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; void -_nmtstp_init_tests (int *argc, char ***argv) +_nmtstp_init_tests(int *argc, char ***argv) { - nmtst_init_with_logging (argc, argv, NULL, "ALL"); + nmtst_init_with_logging(argc, argv, NULL, "ALL"); } void -_nmtstp_setup_tests (void) +_nmtstp_setup_tests(void) { - nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); + nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); - g_test_add_func ("/internal", test_cleanup_internal); - /* FIXME: add external cleanup check */ + g_test_add_func("/internal", test_cleanup_internal); + /* FIXME: add external cleanup check */ } diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 9f6a29bc..e305357a 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 - 2017 Red Hat, Inc. */ @@ -14,2021 +14,2461 @@ #include "test-common.h" #define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)" -#define SIGNAL_DATA_ARG(data) (data)->name, nm_platform_signal_change_type_to_string ((data)->change_type), (data)->ifindex, (data)->ifname ? " ifname '" : "", (data)->ifname ?: "", (data)->ifname ? "'" : "", (data)->received_count +#define SIGNAL_DATA_ARG(data) \ + (data)->name, nm_platform_signal_change_type_to_string((data)->change_type), (data)->ifindex, \ + (data)->ifname ? " ifname '" : "", (data)->ifname ?: "", (data)->ifname ? "'" : "", \ + (data)->received_count int NMTSTP_ENV1_IFINDEX = -1; -int NMTSTP_ENV1_EX = -1; +int NMTSTP_ENV1_EX = -1; /*****************************************************************************/ void -nmtstp_setup_platform (void) +nmtstp_setup_platform(void) { - g_assert (_nmtstp_setup_platform_func); - _nmtstp_setup_platform_func (); + g_assert(_nmtstp_setup_platform_func); + _nmtstp_setup_platform_func(); } gboolean -nmtstp_is_root_test (void) +nmtstp_is_root_test(void) { - g_assert (_nmtstp_setup_platform_func); - return _nmtstp_setup_platform_func == nm_linux_platform_setup; + g_assert(_nmtstp_setup_platform_func); + return _nmtstp_setup_platform_func == nm_linux_platform_setup; } gboolean -nmtstp_is_sysfs_writable (void) +nmtstp_is_sysfs_writable(void) { - return !nmtstp_is_root_test () - || (access ("/sys/devices", W_OK) == 0); + return !nmtstp_is_root_test() || (access("/sys/devices", W_OK) == 0); } static void -_init_platform (NMPlatform **platform, gboolean external_command) +_init_platform(NMPlatform **platform, gboolean external_command) { - g_assert (platform); - if (!*platform) - *platform = NM_PLATFORM_GET; - g_assert (NM_IS_PLATFORM (*platform)); + g_assert(platform); + if (!*platform) + *platform = NM_PLATFORM_GET; + g_assert(NM_IS_PLATFORM(*platform)); - if (external_command) - g_assert (NM_IS_LINUX_PLATFORM (*platform)); + if (external_command) + g_assert(NM_IS_LINUX_PLATFORM(*platform)); } /*****************************************************************************/ static GArray * -_ipx_address_get_all (NMPlatform *self, int ifindex, NMPObjectType obj_type) +_ipx_address_get_all(NMPlatform *self, int ifindex, NMPObjectType obj_type) { - NMPLookup lookup; + NMPLookup lookup; - g_assert (NM_IS_PLATFORM (self)); - g_assert (ifindex > 0); - g_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)); - nmp_lookup_init_object (&lookup, - obj_type, - ifindex); - return nmp_cache_lookup_to_array (nm_platform_lookup (self, &lookup), - obj_type, - FALSE /*addresses are always visible. */); + g_assert(NM_IS_PLATFORM(self)); + g_assert(ifindex > 0); + g_assert(NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)); + nmp_lookup_init_object(&lookup, obj_type, ifindex); + return nmp_cache_lookup_to_array(nm_platform_lookup(self, &lookup), + obj_type, + FALSE /*addresses are always visible. */); } GArray * -nmtstp_platform_ip4_address_get_all (NMPlatform *self, int ifindex) +nmtstp_platform_ip4_address_get_all(NMPlatform *self, int ifindex) { - return _ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP4_ADDRESS); + return _ipx_address_get_all(self, ifindex, NMP_OBJECT_TYPE_IP4_ADDRESS); } GArray * -nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex) +nmtstp_platform_ip6_address_get_all(NMPlatform *self, int ifindex) { - return _ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP6_ADDRESS); + return _ipx_address_get_all(self, ifindex, NMP_OBJECT_TYPE_IP6_ADDRESS); +} + +const NMPlatformIPAddress * +nmtstp_platform_ip_address_find(NMPlatform *self, int ifindex, int addr_family, gconstpointer addr) +{ + const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const NMPlatformIPAddress *found = NULL; + NMDedupMultiIter iter; + const NMPObject * obj; + NMPLookup lookup; + + g_assert(NM_IS_PLATFORM(self)); + nm_assert(ifindex >= 0); + nm_assert_addr_family(addr_family); + nm_assert(addr); + + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex); + nm_platform_iter_obj_for_each(&iter, self, &lookup, &obj) + { + const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(obj); + + g_assert(NMP_OBJECT_GET_ADDR_FAMILY(obj) == addr_family); + g_assert(ifindex <= 0 || a->ifindex == ifindex); + + if (memcmp(addr, a->address_ptr, nm_utils_addr_family_to_size(addr_family)) != 0) + continue; + + g_assert(!found); + found = a; + } + + if (!IS_IPv4 && ifindex > 0) + g_assert(found + == (const NMPlatformIPAddress *) nm_platform_ip6_address_get(self, ifindex, addr)); + + return found; +} + +/*****************************************************************************/ + +typedef struct { + NMIPAddr addr; + int addr_family; + bool found : 1; +} IPAddressesAssertData; + +void +_nmtstp_platform_ip_addresses_assert(const char * filename, + int lineno, + NMPlatform * self, + int ifindex, + gboolean force_exact_4, + gboolean force_exact_6, + gboolean ignore_ll6, + guint addrs_len, + const char *const *addrs) +{ + gs_free IPAddressesAssertData *addrs_bin = NULL; + int IS_IPv4; + guint i; + + g_assert(filename); + g_assert(lineno >= 0); + g_assert(NM_IS_PLATFORM(self)); + g_assert(ifindex >= 0); + + addrs_bin = g_new(IPAddressesAssertData, addrs_len); + + for (i = 0; i < addrs_len; i++) { + const char *addrstr = addrs[i]; + int addr_family; + NMIPAddr a; + + if (!addrstr) { + addr_family = AF_UNSPEC; + a = nm_ip_addr_zero; + } else if (inet_pton(AF_INET, addrstr, &a) == 1) + addr_family = AF_INET; + else if (inet_pton(AF_INET6, addrstr, &a) == 1) + addr_family = AF_INET6; + else + g_error("%s:%d: invalid IP address in argument: %s", filename, lineno, addrstr); + + addrs_bin[i] = (IPAddressesAssertData){ + .addr_family = addr_family, + .addr = a, + .found = FALSE, + }; + } + + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; + gs_unref_ptrarray GPtrArray *plat_addrs = NULL; + NMPLookup lookup; + guint j; + + plat_addrs = nm_platform_lookup_clone( + self, + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex), + NULL, + NULL); + + for (i = 0; i < addrs_len; i++) { + IPAddressesAssertData *addr_bin = &addrs_bin[i]; + + if (addr_bin->addr_family != addr_family) + continue; + + g_assert(!addr_bin->found); + for (j = 0; j < nm_g_ptr_array_len(plat_addrs);) { + const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(plat_addrs->pdata[j]); + + if (memcmp(&addr_bin->addr, + a->address_ptr, + nm_utils_addr_family_to_size(addr_family)) + != 0) { + j++; + continue; + } + + g_assert(!addr_bin->found); + addr_bin->found = TRUE; + g_ptr_array_remove_index_fast(plat_addrs, j); + } + + if (!addr_bin->found) { + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + g_error("%s:%d: IPv%c address %s was not found on ifindex %d", + filename, + lineno, + nm_utils_addr_family_to_char(addr_bin->addr_family), + nm_utils_inet_ntop(addr_bin->addr_family, &addr_bin->addr, sbuf), + ifindex); + } + } + if (!IS_IPv4 && ignore_ll6 && nm_g_ptr_array_len(plat_addrs) > 0) { + /* we prune all remaining, non-matching IPv6 link local addresses. */ + for (j = 0; j < nm_g_ptr_array_len(plat_addrs);) { + const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(plat_addrs->pdata[j]); + + if (!IN6_IS_ADDR_LINKLOCAL(a->address_ptr)) { + j++; + continue; + } + + g_ptr_array_remove_index_fast(plat_addrs, j); + } + } + if ((IS_IPv4 ? force_exact_4 : force_exact_6) && nm_g_ptr_array_len(plat_addrs) > 0) { + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + + g_error("%s:%d: %u IPv%c addresses found on ifindex %d that should not be there (one " + "is %s)", + filename, + lineno, + plat_addrs->len, + nm_utils_addr_family_to_char(addr_family), + ifindex, + nmp_object_to_string(plat_addrs->pdata[0], + NMP_OBJECT_TO_STRING_PUBLIC, + sbuf, + sizeof(sbuf))); + } + } } /*****************************************************************************/ gboolean -nmtstp_platform_ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric) +nmtstp_platform_ip4_route_delete(NMPlatform *platform, + int ifindex, + in_addr_t network, + guint8 plen, + guint32 metric) { - NMDedupMultiIter iter; + NMDedupMultiIter iter; - nm_platform_process_events (platform); + nm_platform_process_events(platform); - nm_dedup_multi_iter_for_each (&iter, - nm_platform_lookup_object (platform, - NMP_OBJECT_TYPE_IP4_ROUTE, - ifindex)) { - const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (iter.current->obj); + nm_dedup_multi_iter_for_each ( + &iter, + nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex)) { + const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE(iter.current->obj); - if ( r->ifindex != ifindex - || r->network != network - || r->plen != plen - || r->metric != metric) { - continue; - } + if (r->ifindex != ifindex || r->network != network || r->plen != plen + || r->metric != metric) { + continue; + } - return nm_platform_object_delete (platform, NMP_OBJECT_UP_CAST (r)); - } + return nm_platform_object_delete(platform, NMP_OBJECT_UP_CAST(r)); + } - return TRUE; + return TRUE; } gboolean -nmtstp_platform_ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric) +nmtstp_platform_ip6_route_delete(NMPlatform * platform, + int ifindex, + struct in6_addr network, + guint8 plen, + guint32 metric) { - NMDedupMultiIter iter; + NMDedupMultiIter iter; - nm_platform_process_events (platform); + nm_platform_process_events(platform); - nm_dedup_multi_iter_for_each (&iter, - nm_platform_lookup_object (platform, - NMP_OBJECT_TYPE_IP6_ROUTE, - ifindex)) { - const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (iter.current->obj); + nm_dedup_multi_iter_for_each ( + &iter, + nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex)) { + const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE(iter.current->obj); - if ( r->ifindex != ifindex - || !IN6_ARE_ADDR_EQUAL (&r->network, &network) - || r->plen != plen - || r->metric != metric) { - continue; - } + if (r->ifindex != ifindex || !IN6_ARE_ADDR_EQUAL(&r->network, &network) || r->plen != plen + || r->metric != metric) { + continue; + } - return nm_platform_object_delete (platform, NMP_OBJECT_UP_CAST (r)); - } + return nm_platform_object_delete(platform, NMP_OBJECT_UP_CAST(r)); + } - return TRUE; + return TRUE; } /*****************************************************************************/ SignalData * -add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname) +add_signal_full(const char * name, + NMPlatformSignalChangeType change_type, + GCallback callback, + int ifindex, + const char * ifname) { - SignalData *data = g_new0 (SignalData, 1); + SignalData *data = g_new0(SignalData, 1); - data->name = name; - data->change_type = change_type; - data->received_count = 0; - data->handler_id = g_signal_connect (NM_PLATFORM_GET, name, callback, data); - data->ifindex = ifindex; - data->ifname = ifname; + data->name = name; + data->change_type = change_type; + data->received_count = 0; + data->handler_id = g_signal_connect(NM_PLATFORM_GET, name, callback, data); + data->ifindex = ifindex; + data->ifname = ifname; - g_assert (data->handler_id > 0); + g_assert(data->handler_id > 0); - return data; + return data; } void -_accept_signal (const char *file, int line, const char *func, SignalData *data) -{ - _LOGD ("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal one time: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); - if (data->received_count != 1) - g_error ("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal one time: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); - data->received_count = 0; +_accept_signal(const char *file, int line, const char *func, SignalData *data) +{ + _LOGD("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal one time: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); + if (data->received_count != 1) + g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal one " + "time: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); + data->received_count = 0; } void -_accept_signals (const char *file, int line, const char *func, SignalData *data, int min, int max) -{ - _LOGD ("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal [%d,%d] times: "SIGNAL_DATA_FMT, file, line, func, min, max, SIGNAL_DATA_ARG (data)); - if (data->received_count < min || data->received_count > max) - g_error ("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal [%d,%d] times: "SIGNAL_DATA_FMT, file, line, func, min, max, SIGNAL_DATA_ARG (data)); - data->received_count = 0; +_accept_signals(const char *file, int line, const char *func, SignalData *data, int min, int max) +{ + _LOGD("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal [%d,%d] times: " SIGNAL_DATA_FMT, + file, + line, + func, + min, + max, + SIGNAL_DATA_ARG(data)); + if (data->received_count < min || data->received_count > max) + g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal [%d,%d] " + "times: " SIGNAL_DATA_FMT, + file, + line, + func, + min, + max, + SIGNAL_DATA_ARG(data)); + data->received_count = 0; } void -_ensure_no_signal (const char *file, int line, const char *func, SignalData *data) -{ - _LOGD ("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal 0 times: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); - if (data->received_count > 0) - g_error ("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal 0 times: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); +_ensure_no_signal(const char *file, int line, const char *func, SignalData *data) +{ + _LOGD("NMPlatformSignalAssert: %s:%d, %s(): Accepting signal 0 times: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); + if (data->received_count > 0) + g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to accept signal 0 " + "times: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); } void -_accept_or_wait_signal (const char *file, int line, const char *func, SignalData *data) +_accept_or_wait_signal(const char *file, int line, const char *func, SignalData *data) { - _LOGD ("NMPlatformSignalAssert: %s:%d, %s(): accept-or-wait signal: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); - if (data->received_count == 0) { - data->loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (data->loop); - nm_clear_pointer (&data->loop, g_main_loop_unref); - } + _LOGD("NMPlatformSignalAssert: %s:%d, %s(): accept-or-wait signal: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); + if (data->received_count == 0) { + data->loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(data->loop); + nm_clear_pointer(&data->loop, g_main_loop_unref); + } - _accept_signal (file, line, func, data); + _accept_signal(file, line, func, data); } void -_wait_signal (const char *file, int line, const char *func, SignalData *data) +_wait_signal(const char *file, int line, const char *func, SignalData *data) { - _LOGD ("NMPlatformSignalAssert: %s:%d, %s(): wait signal: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); - if (data->received_count) - g_error ("NMPlatformSignalAssert: %s:%d, %s(): failure to wait for signal: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); + _LOGD("NMPlatformSignalAssert: %s:%d, %s(): wait signal: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); + if (data->received_count) + g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to wait for signal: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); - data->loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (data->loop); - nm_clear_pointer (&data->loop, g_main_loop_unref); + data->loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(data->loop); + nm_clear_pointer(&data->loop, g_main_loop_unref); - _accept_signal (file, line, func, data); + _accept_signal(file, line, func, data); } void -_free_signal (const char *file, int line, const char *func, SignalData *data) +_free_signal(const char *file, int line, const char *func, SignalData *data) { - _LOGD ("NMPlatformSignalAssert: %s:%d, %s(): free signal: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); - if (data->received_count != 0) - g_error ("NMPlatformSignalAssert: %s:%d, %s(): failure to free non-accepted signal: "SIGNAL_DATA_FMT, file, line, func, SIGNAL_DATA_ARG (data)); + _LOGD("NMPlatformSignalAssert: %s:%d, %s(): free signal: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); + if (data->received_count != 0) + g_error("NMPlatformSignalAssert: %s:%d, %s(): failure to free non-accepted " + "signal: " SIGNAL_DATA_FMT, + file, + line, + func, + SIGNAL_DATA_ARG(data)); - g_signal_handler_disconnect (NM_PLATFORM_GET, data->handler_id); - g_free (data); + g_signal_handler_disconnect(NM_PLATFORM_GET, data->handler_id); + g_free(data); } void -link_callback (NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink *received, int change_type_i, SignalData *data) -{ - const NMPObjectType obj_type = obj_type_i; - const NMPlatformSignalChangeType change_type = change_type_i; - NMPLookup lookup; - NMDedupMultiIter iter; - const NMPlatformLink *cached; - - g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_LINK); - g_assert (received); - g_assert_cmpint (received->ifindex, ==, ifindex); - g_assert (data && data->name); - g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_LINK_CHANGED); - - if (data->ifindex && data->ifindex != received->ifindex) - return; - if (data->ifname && g_strcmp0 (data->ifname, nm_platform_link_get_name (NM_PLATFORM_GET, ifindex)) != 0) - return; - if (change_type != data->change_type) - return; - - if (data->loop) { - _LOGD ("Quitting main loop."); - g_main_loop_quit (data->loop); - } - - data->received_count++; - _LOGD ("Received signal '%s-%s' ifindex %d ifname '%s' %dth time.", data->name, nm_platform_signal_change_type_to_string (data->change_type), ifindex, received->name, data->received_count); - - if (change_type == NM_PLATFORM_SIGNAL_REMOVED) - g_assert (!nm_platform_link_get_name (NM_PLATFORM_GET, ifindex)); - else - g_assert (nm_platform_link_get_name (NM_PLATFORM_GET, ifindex)); - - /* Check the data */ - g_assert (received->ifindex > 0); - - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK); - nmp_cache_iter_for_each_link (&iter, - nm_platform_lookup (platform, &lookup), - &cached) { - if (!nmp_object_is_visible (NMP_OBJECT_UP_CAST (cached))) - continue; - if (cached->ifindex == received->ifindex) { - g_assert_cmpint (nm_platform_link_cmp (cached, received), ==, 0); - g_assert (!memcmp (cached, received, sizeof (*cached))); - if (data->change_type == NM_PLATFORM_SIGNAL_REMOVED) - g_error ("Deleted link still found in the local cache."); - return; - } - } - - if (data->change_type != NM_PLATFORM_SIGNAL_REMOVED) - g_error ("Added/changed link not found in the local cache."); +link_callback(NMPlatform * platform, + int obj_type_i, + int ifindex, + NMPlatformLink *received, + int change_type_i, + SignalData * data) +{ + const NMPObjectType obj_type = obj_type_i; + const NMPlatformSignalChangeType change_type = change_type_i; + NMPLookup lookup; + NMDedupMultiIter iter; + const NMPlatformLink * cached; + + g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_LINK); + g_assert(received); + g_assert_cmpint(received->ifindex, ==, ifindex); + g_assert(data && data->name); + g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_LINK_CHANGED); + + if (data->ifindex && data->ifindex != received->ifindex) + return; + if (data->ifname + && g_strcmp0(data->ifname, nm_platform_link_get_name(NM_PLATFORM_GET, ifindex)) != 0) + return; + if (change_type != data->change_type) + return; + + if (data->loop) { + _LOGD("Quitting main loop."); + g_main_loop_quit(data->loop); + } + + data->received_count++; + _LOGD("Received signal '%s-%s' ifindex %d ifname '%s' %dth time.", + data->name, + nm_platform_signal_change_type_to_string(data->change_type), + ifindex, + received->name, + data->received_count); + + if (change_type == NM_PLATFORM_SIGNAL_REMOVED) + g_assert(!nm_platform_link_get_name(NM_PLATFORM_GET, ifindex)); + else + g_assert(nm_platform_link_get_name(NM_PLATFORM_GET, ifindex)); + + /* Check the data */ + g_assert(received->ifindex > 0); + + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); + nmp_cache_iter_for_each_link (&iter, nm_platform_lookup(platform, &lookup), &cached) { + if (!nmp_object_is_visible(NMP_OBJECT_UP_CAST(cached))) + continue; + if (cached->ifindex == received->ifindex) { + g_assert_cmpint(nm_platform_link_cmp(cached, received), ==, 0); + g_assert(!memcmp(cached, received, sizeof(*cached))); + if (data->change_type == NM_PLATFORM_SIGNAL_REMOVED) + g_error("Deleted link still found in the local cache."); + return; + } + } + + if (data->change_type != NM_PLATFORM_SIGNAL_REMOVED) + g_error("Added/changed link not found in the local cache."); } /*****************************************************************************/ static const NMPlatformIP4Route * -_ip4_route_get (NMPlatform *platform, - int ifindex, - guint32 network, - int plen, - guint32 metric, - guint8 tos, - guint *out_c_exists) -{ - NMDedupMultiIter iter; - NMPLookup lookup; - const NMPObject *o = NULL; - guint c; - const NMPlatformIP4Route *r = NULL; - - _init_platform (&platform, FALSE); - - nmp_lookup_init_ip4_route_by_weak_id (&lookup, - network, - plen, - metric, - tos); - - c = 0; - nmp_cache_iter_for_each (&iter, - nm_platform_lookup (platform, &lookup), - &o) { - if ( NMP_OBJECT_CAST_IP4_ROUTE (o)->ifindex != ifindex - && ifindex > 0) - continue; - if (!r) - r = NMP_OBJECT_CAST_IP4_ROUTE (o); - c++; - } - - NM_SET_OUT (out_c_exists, c); - return r; +_ip4_route_get(NMPlatform *platform, + int ifindex, + guint32 network, + int plen, + guint32 metric, + guint8 tos, + guint * out_c_exists) +{ + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPObject * o = NULL; + guint c; + const NMPlatformIP4Route *r = NULL; + + _init_platform(&platform, FALSE); + + nmp_lookup_init_ip4_route_by_weak_id(&lookup, network, plen, metric, tos); + + c = 0; + nmp_cache_iter_for_each (&iter, nm_platform_lookup(platform, &lookup), &o) { + if (NMP_OBJECT_CAST_IP4_ROUTE(o)->ifindex != ifindex && ifindex > 0) + continue; + if (!r) + r = NMP_OBJECT_CAST_IP4_ROUTE(o); + c++; + } + + NM_SET_OUT(out_c_exists, c); + return r; } const NMPlatformIP4Route * -_nmtstp_assert_ip4_route_exists (const char *file, - guint line, - const char *func, - NMPlatform *platform, - int c_exists, - const char *ifname, - guint32 network, - int plen, - guint32 metric, - guint8 tos) -{ - int ifindex; - guint c; - const NMPlatformIP4Route *r = NULL; - - _init_platform (&platform, FALSE); - - ifindex = -1; - if (ifname) { - ifindex = nm_platform_link_get_ifindex (platform, ifname); - g_assert (ifindex > 0); - } - - r = _ip4_route_get (platform, - ifindex, - network, - plen, - metric, - tos, - &c); - - if (c != c_exists && c_exists != -1) { - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u tos %u shall exist %u times, but platform has it %u times", - file, line, func, - _nm_utils_inet4_ntop (network, sbuf), - plen, - metric, - tos, - c_exists, - c); - } - - return r; +_nmtstp_assert_ip4_route_exists(const char *file, + guint line, + const char *func, + NMPlatform *platform, + int c_exists, + const char *ifname, + guint32 network, + int plen, + guint32 metric, + guint8 tos) +{ + int ifindex; + guint c; + const NMPlatformIP4Route *r = NULL; + + _init_platform(&platform, FALSE); + + ifindex = -1; + if (ifname) { + ifindex = nm_platform_link_get_ifindex(platform, ifname); + g_assert(ifindex > 0); + } + + r = _ip4_route_get(platform, ifindex, network, plen, metric, tos, &c); + + if (c != c_exists && c_exists != -1) { + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + g_error("[%s:%u] %s(): The ip4 route %s/%d metric %u tos %u shall exist %u times, but " + "platform has it %u times", + file, + line, + func, + _nm_utils_inet4_ntop(network, sbuf), + plen, + metric, + tos, + c_exists, + c); + } + + return r; } const NMPlatformIP4Route * -nmtstp_ip4_route_get (NMPlatform *platform, - int ifindex, - guint32 network, - int plen, - guint32 metric, - guint8 tos) -{ - return _ip4_route_get (platform, - ifindex, - network, - plen, - metric, - tos, - NULL); +nmtstp_ip4_route_get(NMPlatform *platform, + int ifindex, + guint32 network, + int plen, + guint32 metric, + guint8 tos) +{ + return _ip4_route_get(platform, ifindex, network, plen, metric, tos, NULL); } /*****************************************************************************/ static const NMPlatformIP6Route * -_ip6_route_get (NMPlatform *platform, - int ifindex, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen, - guint *out_c_exists) -{ - NMDedupMultiIter iter; - NMPLookup lookup; - const NMPObject *o = NULL; - guint c; - const NMPlatformIP6Route *r = NULL; - - _init_platform (&platform, FALSE); - - nmp_lookup_init_ip6_route_by_weak_id (&lookup, - network, - plen, - metric, - src, - src_plen); - - c = 0; - nmp_cache_iter_for_each (&iter, - nm_platform_lookup (platform, &lookup), - &o) { - if ( NMP_OBJECT_CAST_IP6_ROUTE (o)->ifindex != ifindex - && ifindex > 0) - continue; - if (!r) - r = NMP_OBJECT_CAST_IP6_ROUTE (o); - c++; - } - - NM_SET_OUT (out_c_exists, c); - return r; +_ip6_route_get(NMPlatform * platform, + int ifindex, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen, + guint * out_c_exists) +{ + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPObject * o = NULL; + guint c; + const NMPlatformIP6Route *r = NULL; + + _init_platform(&platform, FALSE); + + nmp_lookup_init_ip6_route_by_weak_id(&lookup, network, plen, metric, src, src_plen); + + c = 0; + nmp_cache_iter_for_each (&iter, nm_platform_lookup(platform, &lookup), &o) { + if (NMP_OBJECT_CAST_IP6_ROUTE(o)->ifindex != ifindex && ifindex > 0) + continue; + if (!r) + r = NMP_OBJECT_CAST_IP6_ROUTE(o); + c++; + } + + NM_SET_OUT(out_c_exists, c); + return r; } const NMPlatformIP6Route * -_nmtstp_assert_ip6_route_exists (const char *file, - guint line, - const char *func, - NMPlatform *platform, - int c_exists, - const char *ifname, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen) -{ - int ifindex; - guint c; - const NMPlatformIP6Route *r = NULL; - - _init_platform (&platform, FALSE); - - ifindex = -1; - if (ifname) { - ifindex = nm_platform_link_get_ifindex (platform, ifname); - g_assert (ifindex > 0); - } - - r = _ip6_route_get (platform, - ifindex, - network, - plen, - metric, - src, - src_plen, - &c); - - if (c != c_exists && c_exists != -1) { - char s_src[NM_UTILS_INET_ADDRSTRLEN]; - char s_network[NM_UTILS_INET_ADDRSTRLEN]; - - g_error ("[%s:%u] %s(): The ip6 route %s/%d metric %u src %s/%d shall exist %u times, but platform has it %u times", - file, line, func, - _nm_utils_inet6_ntop (network, s_network), - plen, - metric, - _nm_utils_inet6_ntop (src, s_src), - src_plen, - c_exists, - c); - } - - return r; +_nmtstp_assert_ip6_route_exists(const char * file, + guint line, + const char * func, + NMPlatform * platform, + int c_exists, + const char * ifname, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen) +{ + int ifindex; + guint c; + const NMPlatformIP6Route *r = NULL; + + _init_platform(&platform, FALSE); + + ifindex = -1; + if (ifname) { + ifindex = nm_platform_link_get_ifindex(platform, ifname); + g_assert(ifindex > 0); + } + + r = _ip6_route_get(platform, ifindex, network, plen, metric, src, src_plen, &c); + + if (c != c_exists && c_exists != -1) { + char s_src[NM_UTILS_INET_ADDRSTRLEN]; + char s_network[NM_UTILS_INET_ADDRSTRLEN]; + + g_error("[%s:%u] %s(): The ip6 route %s/%d metric %u src %s/%d shall exist %u times, but " + "platform has it %u times", + file, + line, + func, + _nm_utils_inet6_ntop(network, s_network), + plen, + metric, + _nm_utils_inet6_ntop(src, s_src), + src_plen, + c_exists, + c); + } + + return r; } const NMPlatformIP6Route * -nmtstp_ip6_route_get (NMPlatform *platform, - int ifindex, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen) -{ - return _ip6_route_get (platform, - ifindex, - network, - plen, - metric, - src, - src_plen, - NULL); +nmtstp_ip6_route_get(NMPlatform * platform, + int ifindex, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen) +{ + return _ip6_route_get(platform, ifindex, network, plen, metric, src, src_plen, NULL); } /*****************************************************************************/ int -nmtstp_run_command (const char *format, ...) +nmtstp_run_command(const char *format, ...) { - int result; - gs_free char *command = NULL; - va_list ap; + int result; + gs_free char *command = NULL; + va_list ap; - va_start (ap, format); - command = g_strdup_vprintf (format, ap); - va_end (ap); + va_start(ap, format); + command = g_strdup_vprintf(format, ap); + va_end(ap); - _LOGD ("Running command: %s", command); - result = system (command); - _LOGD ("Command finished: result=%d", result); + _LOGD("Running command: %s", command); + result = system(command); + _LOGD("Command finished: result=%d", result); - return result; + return result; } /*****************************************************************************/ typedef struct { - GMainLoop *loop; - guint signal_counts; - guint id; + GMainLoop *loop; + guint signal_counts; + guint id; } WaitForSignalData; static void -_wait_for_signal_cb (NMPlatform *platform, - int obj_type_i, - int ifindex, - NMPlatformLink *plink, - int change_type_i, - gpointer user_data) +_wait_for_signal_cb(NMPlatform * platform, + int obj_type_i, + int ifindex, + NMPlatformLink *plink, + int change_type_i, + gpointer user_data) { - WaitForSignalData *data = user_data; + WaitForSignalData *data = user_data; - data->signal_counts++; - nm_clear_g_source (&data->id); - g_main_loop_quit (data->loop); + data->signal_counts++; + nm_clear_g_source(&data->id); + g_main_loop_quit(data->loop); } static gboolean -_wait_for_signal_timeout (gpointer user_data) +_wait_for_signal_timeout(gpointer user_data) { - WaitForSignalData *data = user_data; + WaitForSignalData *data = user_data; - g_assert (data->id); - data->id = 0; - g_main_loop_quit (data->loop); - return G_SOURCE_REMOVE; + g_assert(data->id); + data->id = 0; + g_main_loop_quit(data->loop); + return G_SOURCE_REMOVE; } guint -nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_msec) -{ - WaitForSignalData data = { 0 }; - gulong id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route; - gulong id_qdisc, id_tfilter; - - _init_platform (&platform, FALSE); - - data.loop = g_main_loop_new (NULL, FALSE); - - id_link = g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip4_address = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip6_address = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip4_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_ip6_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_qdisc = g_signal_connect (platform, NM_PLATFORM_SIGNAL_QDISC_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - id_tfilter = g_signal_connect (platform, NM_PLATFORM_SIGNAL_TFILTER_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - - /* if timeout_msec is negative, it means the wait-time already expired. - * Maybe, we should do nothing and return right away, without even - * processing events from platform. However, that inconsistency (of not - * processing events from mainloop) is inconvenient. - * - * It's better that on the return of nmtstp_wait_for_signal(), we always - * have no events pending. So, a negative timeout is treated the same as - * a zero timeout: we check whether there are any events pending in platform, - * and quite the mainloop immediately afterwards. But we always check. */ - - data.id = g_timeout_add (CLAMP (timeout_msec, 0, G_MAXUINT32), - _wait_for_signal_timeout, &data); - - g_main_loop_run (data.loop); - - g_assert (!data.id); - g_assert (nm_clear_g_signal_handler (platform, &id_link)); - g_assert (nm_clear_g_signal_handler (platform, &id_ip4_address)); - g_assert (nm_clear_g_signal_handler (platform, &id_ip6_address)); - g_assert (nm_clear_g_signal_handler (platform, &id_ip4_route)); - g_assert (nm_clear_g_signal_handler (platform, &id_ip6_route)); - g_assert (nm_clear_g_signal_handler (platform, &id_tfilter)); - g_assert (nm_clear_g_signal_handler (platform, &id_qdisc)); - - nm_clear_pointer (&data.loop, g_main_loop_unref); - - /* return the number of signals, or 0 if timeout was reached .*/ - return data.signal_counts; +nmtstp_wait_for_signal(NMPlatform *platform, gint64 timeout_msec) +{ + WaitForSignalData data = {0}; + gulong id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route; + gulong id_qdisc, id_tfilter; + + _init_platform(&platform, FALSE); + + data.loop = g_main_loop_new(NULL, FALSE); + + id_link = g_signal_connect(platform, + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(_wait_for_signal_cb), + &data); + id_ip4_address = g_signal_connect(platform, + NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, + G_CALLBACK(_wait_for_signal_cb), + &data); + id_ip6_address = g_signal_connect(platform, + NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, + G_CALLBACK(_wait_for_signal_cb), + &data); + id_ip4_route = g_signal_connect(platform, + NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + G_CALLBACK(_wait_for_signal_cb), + &data); + id_ip6_route = g_signal_connect(platform, + NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, + G_CALLBACK(_wait_for_signal_cb), + &data); + id_qdisc = g_signal_connect(platform, + NM_PLATFORM_SIGNAL_QDISC_CHANGED, + G_CALLBACK(_wait_for_signal_cb), + &data); + id_tfilter = g_signal_connect(platform, + NM_PLATFORM_SIGNAL_TFILTER_CHANGED, + G_CALLBACK(_wait_for_signal_cb), + &data); + + /* if timeout_msec is negative, it means the wait-time already expired. + * Maybe, we should do nothing and return right away, without even + * processing events from platform. However, that inconsistency (of not + * processing events from mainloop) is inconvenient. + * + * It's better that on the return of nmtstp_wait_for_signal(), we always + * have no events pending. So, a negative timeout is treated the same as + * a zero timeout: we check whether there are any events pending in platform, + * and quite the mainloop immediately afterwards. But we always check. */ + + data.id = g_timeout_add(CLAMP(timeout_msec, 0, G_MAXUINT32), _wait_for_signal_timeout, &data); + + g_main_loop_run(data.loop); + + g_assert(!data.id); + g_assert(nm_clear_g_signal_handler(platform, &id_link)); + g_assert(nm_clear_g_signal_handler(platform, &id_ip4_address)); + g_assert(nm_clear_g_signal_handler(platform, &id_ip6_address)); + g_assert(nm_clear_g_signal_handler(platform, &id_ip4_route)); + g_assert(nm_clear_g_signal_handler(platform, &id_ip6_route)); + g_assert(nm_clear_g_signal_handler(platform, &id_tfilter)); + g_assert(nm_clear_g_signal_handler(platform, &id_qdisc)); + + nm_clear_pointer(&data.loop, g_main_loop_unref); + + /* return the number of signals, or 0 if timeout was reached .*/ + return data.signal_counts; } guint -nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms) +nmtstp_wait_for_signal_until(NMPlatform *platform, gint64 until_ms) { - gint64 now; - guint signal_counts; + gint64 now; + guint signal_counts; - while (TRUE) { - now = nm_utils_get_monotonic_timestamp_msec (); + while (TRUE) { + now = nm_utils_get_monotonic_timestamp_msec(); - if (until_ms < now) - return 0; + if (until_ms < now) + return 0; - signal_counts = nmtstp_wait_for_signal (platform, until_ms - now); - if (signal_counts) - return signal_counts; - } + signal_counts = nmtstp_wait_for_signal(platform, until_ms - now); + if (signal_counts) + return signal_counts; + } } const NMPlatformLink * -nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_msec) +nmtstp_wait_for_link(NMPlatform *platform, + const char *ifname, + NMLinkType expected_link_type, + gint64 timeout_msec) { - return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, - timeout_msec - ? nm_utils_get_monotonic_timestamp_msec () + timeout_msec - : 0); + return nmtstp_wait_for_link_until( + platform, + ifname, + expected_link_type, + timeout_msec ? nm_utils_get_monotonic_timestamp_msec() + timeout_msec : 0); } const NMPlatformLink * -nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms) +nmtstp_wait_for_link_until(NMPlatform *platform, + const char *ifname, + NMLinkType expected_link_type, + gint64 until_ms) { - const NMPlatformLink *plink; - gint64 now; - gboolean waited_once = FALSE; + const NMPlatformLink *plink; + gint64 now; + gboolean waited_once = FALSE; - _init_platform (&platform, FALSE); + _init_platform(&platform, FALSE); - while (TRUE) { - now = nm_utils_get_monotonic_timestamp_msec (); + while (TRUE) { + now = nm_utils_get_monotonic_timestamp_msec(); - plink = nm_platform_link_get_by_ifname (platform, ifname); - if ( plink - && (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type)) - return plink; + plink = nm_platform_link_get_by_ifname(platform, ifname); + if (plink && (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type)) + return plink; - if (until_ms == 0) { - /* don't wait, don't even poll the socket. */ - return NULL; - } + if (until_ms == 0) { + /* don't wait, don't even poll the socket. */ + return NULL; + } - if ( waited_once - && until_ms < now) { - /* timeout reached (+ we already waited for a signal at least once). */ - return NULL; - } + if (waited_once && until_ms < now) { + /* timeout reached (+ we already waited for a signal at least once). */ + return NULL; + } - waited_once = TRUE; - /* regardless of whether timeout is already reached, we poll the netlink - * socket a bit. */ - nmtstp_wait_for_signal (platform, until_ms - now); - } + waited_once = TRUE; + /* regardless of whether timeout is already reached, we poll the netlink + * socket a bit. */ + nmtstp_wait_for_signal(platform, until_ms - now); + } } /*****************************************************************************/ int -nmtstp_run_command_check_external_global (void) +nmtstp_run_command_check_external_global(void) { - if (!nmtstp_is_root_test ()) - return FALSE; - switch (nmtst_get_rand_uint32 () % 3) { - case 0: - return -1; - case 1: - return FALSE; - default: - return TRUE; - } + if (!nmtstp_is_root_test()) + return FALSE; + switch (nmtst_get_rand_uint32() % 3) { + case 0: + return -1; + case 1: + return FALSE; + default: + return TRUE; + } } gboolean -nmtstp_run_command_check_external (int external_command) +nmtstp_run_command_check_external(int external_command) { - if (external_command != -1) { - g_assert (NM_IN_SET (external_command, FALSE, TRUE)); - g_assert (!external_command || nmtstp_is_root_test ()); - return !!external_command; - } - if (!nmtstp_is_root_test ()) - return FALSE; - return (nmtst_get_rand_uint32 () % 2) == 0; + if (external_command != -1) { + g_assert(NM_IN_SET(external_command, FALSE, TRUE)); + g_assert(!external_command || nmtstp_is_root_test()); + return !!external_command; + } + if (!nmtstp_is_root_test()) + return FALSE; + return (nmtst_get_rand_uint32() % 2) == 0; } /*****************************************************************************/ -#define CHECK_LIFETIME_MAX_DIFF 2 +#define CHECK_LIFETIME_MAX_DIFF 2 gboolean -nmtstp_ip_address_check_lifetime (const NMPlatformIPAddress *addr, - gint64 now, - guint32 expected_lifetime, - guint32 expected_preferred) +nmtstp_ip_address_check_lifetime(const NMPlatformIPAddress *addr, + gint64 now, + guint32 expected_lifetime, + guint32 expected_preferred) { - gint64 offset; - int i; + gint64 offset; + int i; - g_assert (addr); + g_assert(addr); - if (now == -1) - now = nm_utils_get_monotonic_timestamp_sec (); - g_assert (now > 0); + if (now == -1) + now = nm_utils_get_monotonic_timestamp_sec(); + g_assert(now > 0); - g_assert (expected_preferred <= expected_lifetime); + g_assert(expected_preferred <= expected_lifetime); - if ( expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT - && expected_preferred == NM_PLATFORM_LIFETIME_PERMANENT) { - return addr->timestamp == 0 - && addr->lifetime == NM_PLATFORM_LIFETIME_PERMANENT - && addr->preferred == NM_PLATFORM_LIFETIME_PERMANENT; - } + if (expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT + && expected_preferred == NM_PLATFORM_LIFETIME_PERMANENT) { + return addr->timestamp == 0 && addr->lifetime == NM_PLATFORM_LIFETIME_PERMANENT + && addr->preferred == NM_PLATFORM_LIFETIME_PERMANENT; + } - if (addr->timestamp == 0) - return FALSE; + if (addr->timestamp == 0) + return FALSE; - offset = (gint64) now - addr->timestamp; + offset = (gint64) now - addr->timestamp; - for (i = 0; i < 2; i++) { - guint32 lft = i ? expected_lifetime : expected_preferred; - guint32 adr = i ? addr->lifetime : addr->preferred; + for (i = 0; i < 2; i++) { + guint32 lft = i ? expected_lifetime : expected_preferred; + guint32 adr = i ? addr->lifetime : addr->preferred; - if (lft == NM_PLATFORM_LIFETIME_PERMANENT) { - if (adr != NM_PLATFORM_LIFETIME_PERMANENT) - return FALSE; - } else { - if ( adr - offset <= lft - CHECK_LIFETIME_MAX_DIFF - || adr - offset >= lft + CHECK_LIFETIME_MAX_DIFF) - return FALSE; - } - } - return TRUE; + if (lft == NM_PLATFORM_LIFETIME_PERMANENT) { + if (adr != NM_PLATFORM_LIFETIME_PERMANENT) + return FALSE; + } else { + if (((gint64) adr) - offset <= ((gint64) lft) - CHECK_LIFETIME_MAX_DIFF + || ((gint64) adr) - offset >= ((gint64) lft) + CHECK_LIFETIME_MAX_DIFF) + return FALSE; + } + } + return TRUE; } void -nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr, - gint64 now, - guint32 expected_lifetime, - guint32 expected_preferred) +nmtstp_ip_address_assert_lifetime(const NMPlatformIPAddress *addr, + gint64 now, + guint32 expected_lifetime, + guint32 expected_preferred) { - gint64 n = now; - gint64 offset; - int i; + gint64 n = now; + gint64 offset; + int i; - g_assert (addr); + g_assert(addr); - if (now == -1) - now = nm_utils_get_monotonic_timestamp_sec (); - g_assert (now > 0); + if (now == -1) + now = nm_utils_get_monotonic_timestamp_sec(); + g_assert(now > 0); - g_assert (expected_preferred <= expected_lifetime); + g_assert(expected_preferred <= expected_lifetime); - if ( expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT - && expected_preferred == NM_PLATFORM_LIFETIME_PERMANENT) { - g_assert_cmpint (addr->timestamp, ==, 0); - g_assert_cmpint (addr->lifetime, ==, NM_PLATFORM_LIFETIME_PERMANENT); - g_assert_cmpint (addr->preferred, ==, NM_PLATFORM_LIFETIME_PERMANENT); - return; - } + if (expected_lifetime == NM_PLATFORM_LIFETIME_PERMANENT + && expected_preferred == NM_PLATFORM_LIFETIME_PERMANENT) { + g_assert_cmpint(addr->timestamp, ==, 0); + g_assert_cmpint(addr->lifetime, ==, NM_PLATFORM_LIFETIME_PERMANENT); + g_assert_cmpint(addr->preferred, ==, NM_PLATFORM_LIFETIME_PERMANENT); + return; + } - g_assert_cmpint (addr->timestamp, >, 0); - g_assert_cmpint (addr->timestamp, <=, now); + g_assert_cmpint(addr->timestamp, >, 0); + g_assert_cmpint(addr->timestamp, <=, now); - offset = (gint64) now - addr->timestamp; - g_assert_cmpint (offset, >=, 0); + offset = (gint64) now - addr->timestamp; + g_assert_cmpint(offset, >=, 0); - for (i = 0; i < 2; i++) { - guint32 lft = i ? expected_lifetime : expected_preferred; - guint32 adr = i ? addr->lifetime : addr->preferred; + for (i = 0; i < 2; i++) { + guint32 lft = i ? expected_lifetime : expected_preferred; + guint32 adr = i ? addr->lifetime : addr->preferred; - if (lft == NM_PLATFORM_LIFETIME_PERMANENT) - g_assert_cmpint (adr, ==, NM_PLATFORM_LIFETIME_PERMANENT); - else { - g_assert_cmpint (adr - offset, <=, lft + CHECK_LIFETIME_MAX_DIFF); - g_assert_cmpint (adr - offset, >=, lft - CHECK_LIFETIME_MAX_DIFF); - } - } + if (lft == NM_PLATFORM_LIFETIME_PERMANENT) + g_assert_cmpint(adr, ==, NM_PLATFORM_LIFETIME_PERMANENT); + else { + g_assert_cmpint(adr - offset, <=, lft + CHECK_LIFETIME_MAX_DIFF); + g_assert_cmpint(adr - offset, >=, lft - CHECK_LIFETIME_MAX_DIFF); + } + } - g_assert (nmtstp_ip_address_check_lifetime (addr, n, expected_lifetime, expected_preferred)); + g_assert(nmtstp_ip_address_check_lifetime(addr, n, expected_lifetime, expected_preferred)); } /*****************************************************************************/ static void -_ip_address_add (NMPlatform *platform, - gboolean external_command, - gboolean is_v4, - int ifindex, - const NMIPAddr *address, - int plen, - const NMIPAddr *peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) -{ - gint64 end_time; - - external_command = nmtstp_run_command_check_external (external_command); - - _init_platform (&platform, external_command); - - if (external_command) { - const char *ifname; - gs_free char *s_valid = NULL; - gs_free char *s_preferred = NULL; - gs_free char *s_label = NULL; - char b1[NM_UTILS_INET_ADDRSTRLEN]; - char b2[NM_UTILS_INET_ADDRSTRLEN]; - - ifname = nm_platform_link_get_name (platform, ifindex); - g_assert (ifname); - - if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT) - s_valid = g_strdup_printf (" valid_lft %d", lifetime); - if (preferred != NM_PLATFORM_LIFETIME_PERMANENT) - s_preferred = g_strdup_printf (" preferred_lft %d", preferred); - if (label) - s_label = g_strdup_printf ("%s:%s", ifname, label); - - if (is_v4) { - char s_peer[NM_UTILS_INET_ADDRSTRLEN + 50]; - - g_assert (flags == 0); - - if ( peer_address->addr4 != address->addr4 - || nmtst_get_rand_uint32 () % 2) { - /* If the peer is the same as the local address, we can omit it. The result should be identical */ - nm_sprintf_buf (s_peer, " peer %s", _nm_utils_inet4_ntop (peer_address->addr4, b2)); - } else - s_peer[0] = '\0'; - - nmtstp_run_command_check ("ip address change %s%s/%d dev %s%s%s%s", - _nm_utils_inet4_ntop (address->addr4, b1), - s_peer, - plen, - ifname, - s_valid ?: "", - s_preferred ?: "", - s_label ?: ""); - } else { - g_assert (label == NULL); - - /* flags not implemented (yet) */ - g_assert (flags == 0); - nmtstp_run_command_check ("ip address change %s%s%s/%d dev %s%s%s%s", - _nm_utils_inet6_ntop (&address->addr6, b1), - !IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) ? " peer " : "", - !IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) ? _nm_utils_inet6_ntop (&peer_address->addr6, b2) : "", - plen, - ifname, - s_valid ?: "", - s_preferred ?: "", - s_label ?: ""); - } - } else { - gboolean success; - - if (is_v4) { - success = nm_platform_ip4_address_add (platform, - ifindex, - address->addr4, - plen, - peer_address->addr4, - 0u, - lifetime, - preferred, - flags, - label); - } else { - g_assert (label == NULL); - success = nm_platform_ip6_address_add (platform, - ifindex, - address->addr6, - plen, - peer_address->addr6, - lifetime, - preferred, - flags); - } - g_assert (success); - } - - /* Let's wait until we see the address. */ - end_time = nm_utils_get_monotonic_timestamp_msec () + 500; - do { - - if (external_command) - nm_platform_process_events (platform); - - /* let's wait until we see the address as we added it. */ - if (is_v4) { - const NMPlatformIP4Address *a; - - g_assert (flags == 0); - a = nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4); - if ( a - && a->peer_address == peer_address->addr4 - && nmtstp_ip_address_check_lifetime ((NMPlatformIPAddress*) a, -1, lifetime, preferred) - && strcmp (a->label, label ?: "") == 0) - break; - } else { - const NMPlatformIP6Address *a; - - g_assert (label == NULL); - g_assert (flags == 0); - - a = nm_platform_ip6_address_get (platform, ifindex, address->addr6); - if ( a - && !memcmp (nm_platform_ip6_address_get_peer (a), - (IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) || IN6_ARE_ADDR_EQUAL (&address->addr6, &peer_address->addr6)) - ? &address->addr6 : &peer_address->addr6, - sizeof (struct in6_addr)) - && nmtstp_ip_address_check_lifetime ((NMPlatformIPAddress*) a, -1, lifetime, preferred)) - break; - } - - /* for internal command, we expect not to reach this line.*/ - g_assert (external_command); - - nmtstp_assert_wait_for_signal_until (platform, end_time); - } while (TRUE); +_ip_address_add(NMPlatform * platform, + gboolean external_command, + gboolean is_v4, + int ifindex, + const NMIPAddr *address, + int plen, + const NMIPAddr *peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags, + const char * label) +{ + gint64 end_time; + + external_command = nmtstp_run_command_check_external(external_command); + + _init_platform(&platform, external_command); + + if (external_command) { + const char * ifname; + gs_free char *s_valid = NULL; + gs_free char *s_preferred = NULL; + gs_free char *s_label = NULL; + char b1[NM_UTILS_INET_ADDRSTRLEN]; + char b2[NM_UTILS_INET_ADDRSTRLEN]; + + ifname = nm_platform_link_get_name(platform, ifindex); + g_assert(ifname); + + if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT) + s_valid = g_strdup_printf(" valid_lft %d", lifetime); + if (preferred != NM_PLATFORM_LIFETIME_PERMANENT) + s_preferred = g_strdup_printf(" preferred_lft %d", preferred); + if (label) + s_label = g_strdup_printf("%s:%s", ifname, label); + + if (is_v4) { + char s_peer[NM_UTILS_INET_ADDRSTRLEN + 50]; + + g_assert(flags == 0); + + if (peer_address->addr4 != address->addr4 || nmtst_get_rand_uint32() % 2) { + /* If the peer is the same as the local address, we can omit it. The result should be identical */ + nm_sprintf_buf(s_peer, " peer %s", _nm_utils_inet4_ntop(peer_address->addr4, b2)); + } else + s_peer[0] = '\0'; + + nmtstp_run_command_check("ip address change %s%s/%d dev %s%s%s%s", + _nm_utils_inet4_ntop(address->addr4, b1), + s_peer, + plen, + ifname, + s_valid ?: "", + s_preferred ?: "", + s_label ?: ""); + } else { + g_assert(label == NULL); + + /* flags not implemented (yet) */ + g_assert(flags == 0); + nmtstp_run_command_check("ip address change %s%s%s/%d dev %s%s%s%s", + _nm_utils_inet6_ntop(&address->addr6, b1), + !IN6_IS_ADDR_UNSPECIFIED(&peer_address->addr6) ? " peer " : "", + !IN6_IS_ADDR_UNSPECIFIED(&peer_address->addr6) + ? _nm_utils_inet6_ntop(&peer_address->addr6, b2) + : "", + plen, + ifname, + s_valid ?: "", + s_preferred ?: "", + s_label ?: ""); + } + } else { + gboolean success; + + if (is_v4) { + success = nm_platform_ip4_address_add(platform, + ifindex, + address->addr4, + plen, + peer_address->addr4, + 0u, + lifetime, + preferred, + flags, + label); + } else { + g_assert(label == NULL); + success = nm_platform_ip6_address_add(platform, + ifindex, + address->addr6, + plen, + peer_address->addr6, + lifetime, + preferred, + flags); + } + g_assert(success); + } + + /* Let's wait until we see the address. */ + end_time = nm_utils_get_monotonic_timestamp_msec() + 500; + do { + if (external_command) + nm_platform_process_events(platform); + + /* let's wait until we see the address as we added it. */ + if (is_v4) { + const NMPlatformIP4Address *a; + + g_assert(flags == 0); + a = nm_platform_ip4_address_get(platform, + ifindex, + address->addr4, + plen, + peer_address->addr4); + if (a && a->peer_address == peer_address->addr4 + && nmtstp_ip_address_check_lifetime((NMPlatformIPAddress *) a, + -1, + lifetime, + preferred) + && strcmp(a->label, label ?: "") == 0) + break; + } else { + const NMPlatformIP6Address *a; + + g_assert(label == NULL); + g_assert(flags == 0); + + a = nm_platform_ip6_address_get(platform, ifindex, &address->addr6); + if (a + && !memcmp(nm_platform_ip6_address_get_peer(a), + (IN6_IS_ADDR_UNSPECIFIED(&peer_address->addr6) + || IN6_ARE_ADDR_EQUAL(&address->addr6, &peer_address->addr6)) + ? &address->addr6 + : &peer_address->addr6, + sizeof(struct in6_addr)) + && nmtstp_ip_address_check_lifetime((NMPlatformIPAddress *) a, + -1, + lifetime, + preferred)) + break; + } + + /* for internal command, we expect not to reach this line.*/ + g_assert(external_command); + + nmtstp_assert_wait_for_signal_until(platform, end_time); + } while (TRUE); +} + +void +nmtstp_ip4_address_add(NMPlatform *platform, + gboolean external_command, + int ifindex, + in_addr_t address, + int plen, + in_addr_t peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags, + const char *label) +{ + _ip_address_add(platform, + external_command, + TRUE, + ifindex, + (NMIPAddr *) &address, + plen, + (NMIPAddr *) &peer_address, + lifetime, + preferred, + flags, + label); +} + +void +nmtstp_ip6_address_add(NMPlatform * platform, + gboolean external_command, + int ifindex, + struct in6_addr address, + int plen, + struct in6_addr peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags) +{ + _ip_address_add(platform, + external_command, + FALSE, + ifindex, + (NMIPAddr *) &address, + plen, + (NMIPAddr *) &peer_address, + lifetime, + preferred, + flags, + NULL); } void -nmtstp_ip4_address_add (NMPlatform *platform, - gboolean external_command, - int ifindex, - in_addr_t address, - int plen, - in_addr_t peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label) -{ - _ip_address_add (platform, - external_command, - TRUE, - ifindex, - (NMIPAddr *) &address, - plen, - (NMIPAddr *) &peer_address, - lifetime, - preferred, - flags, - label); +nmtstp_ip4_route_add(NMPlatform * platform, + int ifindex, + NMIPConfigSource source, + in_addr_t network, + guint8 plen, + in_addr_t gateway, + in_addr_t pref_src, + guint32 metric, + guint32 mss) +{ + NMPlatformIP4Route route = {}; + + route.ifindex = ifindex; + route.rt_source = source; + route.network = network; + route.plen = plen; + route.gateway = gateway; + route.pref_src = pref_src; + route.metric = metric; + route.mss = mss; + + g_assert( + NMTST_NM_ERR_SUCCESS(nm_platform_ip4_route_add(platform, NMP_NLM_FLAG_REPLACE, &route))); } void -nmtstp_ip6_address_add (NMPlatform *platform, - gboolean external_command, - int ifindex, - struct in6_addr address, - int plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags) -{ - _ip_address_add (platform, - external_command, - FALSE, - ifindex, - (NMIPAddr *) &address, - plen, - (NMIPAddr *) &peer_address, - lifetime, - preferred, - flags, - NULL); -} - -void nmtstp_ip4_route_add (NMPlatform *platform, - int ifindex, - NMIPConfigSource source, - in_addr_t network, - guint8 plen, - in_addr_t gateway, - in_addr_t pref_src, - guint32 metric, - guint32 mss) -{ - NMPlatformIP4Route route = { }; - - route.ifindex = ifindex; - route.rt_source = source; - route.network = network; - route.plen = plen; - route.gateway = gateway; - route.pref_src = pref_src; - route.metric = metric; - route.mss = mss; - - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_REPLACE, &route))); -} - -void nmtstp_ip6_route_add (NMPlatform *platform, - int ifindex, - NMIPConfigSource source, - struct in6_addr network, - guint8 plen, - struct in6_addr gateway, - struct in6_addr pref_src, - guint32 metric, - guint32 mss) -{ - NMPlatformIP6Route route = { }; - - route.ifindex = ifindex; - route.rt_source = source; - route.network = network; - route.plen = plen; - route.gateway = gateway; - route.pref_src = pref_src; - route.metric = metric; - route.mss = mss; - - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_ip6_route_add (platform, NMP_NLM_FLAG_REPLACE, &route))); +nmtstp_ip6_route_add(NMPlatform * platform, + int ifindex, + NMIPConfigSource source, + struct in6_addr network, + guint8 plen, + struct in6_addr gateway, + struct in6_addr pref_src, + guint32 metric, + guint32 mss) +{ + NMPlatformIP6Route route = {}; + + route.ifindex = ifindex; + route.rt_source = source; + route.network = network; + route.plen = plen; + route.gateway = gateway; + route.pref_src = pref_src; + route.metric = metric; + route.mss = mss; + + g_assert( + NMTST_NM_ERR_SUCCESS(nm_platform_ip6_route_add(platform, NMP_NLM_FLAG_REPLACE, &route))); } /*****************************************************************************/ static void -_ip_address_del (NMPlatform *platform, - gboolean external_command, - gboolean is_v4, - int ifindex, - const NMIPAddr *address, - int plen, - const NMIPAddr *peer_address) -{ - gint64 end_time; - - external_command = nmtstp_run_command_check_external (external_command); - - _init_platform (&platform, external_command); - - if (external_command) { - const char *ifname; - char b1[NM_UTILS_INET_ADDRSTRLEN]; - char b2[NM_UTILS_INET_ADDRSTRLEN]; - int success; - gboolean had_address; - - ifname = nm_platform_link_get_name (platform, ifindex); - g_assert (ifname); - - /* let's wait until we see the address as we added it. */ - if (is_v4) - had_address = !!nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4); - else - had_address = !!nm_platform_ip6_address_get (platform, ifindex, address->addr6); - - if (is_v4) { - success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s", - _nm_utils_inet4_ntop (address->addr4, b1), - peer_address->addr4 != address->addr4 ? " peer " : "", - peer_address->addr4 != address->addr4 ? _nm_utils_inet4_ntop (peer_address->addr4, b2) : "", - plen, - ifname); - } else { - g_assert (!peer_address); - success = nmtstp_run_command ("ip address delete %s/%d dev %s", - _nm_utils_inet6_ntop (&address->addr6, b1), - plen, - ifname); - } - g_assert (success == 0 || !had_address); - } else { - gboolean success; - - if (is_v4) { - success = nm_platform_ip4_address_delete (platform, - ifindex, - address->addr4, - plen, - peer_address->addr4); - } else { - g_assert (!peer_address); - success = nm_platform_ip6_address_delete (platform, - ifindex, - address->addr6, - plen); - } - g_assert (success); - } - - /* Let's wait until we get the result */ - end_time = nm_utils_get_monotonic_timestamp_msec () + 250; - do { - if (external_command) - nm_platform_process_events (platform); - - /* let's wait until we see the address as we added it. */ - if (is_v4) { - const NMPlatformIP4Address *a; - - a = nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4); - if (!a) - break; - } else { - const NMPlatformIP6Address *a; - - a = nm_platform_ip6_address_get (platform, ifindex, address->addr6); - if (!a) - break; - } - - /* for internal command, we expect not to reach this line.*/ - g_assert (external_command); - - nmtstp_assert_wait_for_signal_until (platform, end_time); - } while (TRUE); +_ip_address_del(NMPlatform * platform, + gboolean external_command, + gboolean is_v4, + int ifindex, + const NMIPAddr *address, + int plen, + const NMIPAddr *peer_address) +{ + gint64 end_time; + + external_command = nmtstp_run_command_check_external(external_command); + + _init_platform(&platform, external_command); + + if (external_command) { + const char *ifname; + char b1[NM_UTILS_INET_ADDRSTRLEN]; + char b2[NM_UTILS_INET_ADDRSTRLEN]; + int success; + gboolean had_address; + + ifname = nm_platform_link_get_name(platform, ifindex); + g_assert(ifname); + + /* let's wait until we see the address as we added it. */ + if (is_v4) + had_address = !!nm_platform_ip4_address_get(platform, + ifindex, + address->addr4, + plen, + peer_address->addr4); + else + had_address = !!nm_platform_ip6_address_get(platform, ifindex, &address->addr6); + + if (is_v4) { + success = nmtstp_run_command("ip address delete %s%s%s/%d dev %s", + _nm_utils_inet4_ntop(address->addr4, b1), + peer_address->addr4 != address->addr4 ? " peer " : "", + peer_address->addr4 != address->addr4 + ? _nm_utils_inet4_ntop(peer_address->addr4, b2) + : "", + plen, + ifname); + } else { + g_assert(!peer_address); + success = nmtstp_run_command("ip address delete %s/%d dev %s", + _nm_utils_inet6_ntop(&address->addr6, b1), + plen, + ifname); + } + g_assert(success == 0 || !had_address); + } else { + gboolean success; + + if (is_v4) { + success = nm_platform_ip4_address_delete(platform, + ifindex, + address->addr4, + plen, + peer_address->addr4); + } else { + g_assert(!peer_address); + success = nm_platform_ip6_address_delete(platform, ifindex, address->addr6, plen); + } + g_assert(success); + } + + /* Let's wait until we get the result */ + end_time = nm_utils_get_monotonic_timestamp_msec() + 250; + do { + if (external_command) + nm_platform_process_events(platform); + + /* let's wait until we see the address as we added it. */ + if (is_v4) { + const NMPlatformIP4Address *a; + + a = nm_platform_ip4_address_get(platform, + ifindex, + address->addr4, + plen, + peer_address->addr4); + if (!a) + break; + } else { + const NMPlatformIP6Address *a; + + a = nm_platform_ip6_address_get(platform, ifindex, &address->addr6); + if (!a) + break; + } + + /* for internal command, we expect not to reach this line.*/ + g_assert(external_command); + + nmtstp_assert_wait_for_signal_until(platform, end_time); + } while (TRUE); } void -nmtstp_ip4_address_del (NMPlatform *platform, - gboolean external_command, - int ifindex, - in_addr_t address, - int plen, - in_addr_t peer_address) -{ - _ip_address_del (platform, - external_command, - TRUE, - ifindex, - (NMIPAddr *) &address, - plen, - (NMIPAddr *) &peer_address); +nmtstp_ip4_address_del(NMPlatform *platform, + gboolean external_command, + int ifindex, + in_addr_t address, + int plen, + in_addr_t peer_address) +{ + _ip_address_del(platform, + external_command, + TRUE, + ifindex, + (NMIPAddr *) &address, + plen, + (NMIPAddr *) &peer_address); } void -nmtstp_ip6_address_del (NMPlatform *platform, - gboolean external_command, - int ifindex, - struct in6_addr address, - int plen) +nmtstp_ip6_address_del(NMPlatform * platform, + gboolean external_command, + int ifindex, + struct in6_addr address, + int plen) { - _ip_address_del (platform, - external_command, - FALSE, - ifindex, - (NMIPAddr *) &address, - plen, - NULL); + _ip_address_del(platform, external_command, FALSE, ifindex, (NMIPAddr *) &address, plen, NULL); } /*****************************************************************************/ -#define _assert_pllink(platform, success, pllink, name, type) \ - G_STMT_START { \ - const NMPlatformLink *_pllink = (pllink); \ - \ - if ((success)) { \ - g_assert (_pllink); \ - g_assert (_pllink == nmtstp_link_get_typed (platform, _pllink->ifindex, (name), (type))); \ - } else { \ - g_assert (!_pllink); \ - g_assert (!nmtstp_link_get (platform, 0, (name))); \ - } \ - } G_STMT_END +#define _assert_pllink(platform, success, pllink, name, type) \ + G_STMT_START \ + { \ + const NMPlatformLink *_pllink = (pllink); \ + \ + if ((success)) { \ + g_assert(_pllink); \ + g_assert(_pllink \ + == nmtstp_link_get_typed(platform, _pllink->ifindex, (name), (type))); \ + } else { \ + g_assert(!_pllink); \ + g_assert(!nmtstp_link_get(platform, 0, (name))); \ + } \ + } \ + G_STMT_END const NMPlatformLink * -nmtstp_link_veth_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const char *peer) +nmtstp_link_bridge_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkBridge *lnk) +{ + const NMPlatformLink * pllink = NULL; + const NMPlatformLnkBridge *ll = NULL; + int r = 0; + + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); + + external_command = nmtstp_run_command_check_external(external_command); + + _init_platform(&platform, external_command); + + if (external_command) { + char sbuf_gfw[100]; + char sbuf_mhm[100]; + char sbuf_mlmc[100]; + char sbuf_mlmi[100]; + char sbuf_mmi[100]; + char sbuf_mqi[100]; + char sbuf_mqii[100]; + char sbuf_msqc[100]; + char sbuf_msqi[100]; + char sbuf_mqri[100]; + + r = nmtstp_run_command( + "ip link add %s type bridge " + "forward_delay %u " + "hello_time %u " + "max_age %u " + "ageing_time %u " + "stp_state %d " + "priority %u " + "vlan_protocol %u " + "vlan_stats_enabled %d " + "%s" /* group_fwd_mask */ + "group_address " NM_ETHER_ADDR_FORMAT_STR " " + "mcast_snooping %d " + "mcast_router %u " + "mcast_query_use_ifaddr %d " + "mcast_querier %d " + "%s" /* mcast_hash_max */ + "%s" /* mcast_last_member_count */ + "%s" /* mcast_startup_query_count */ + "%s" /* mcast_last_member_interval */ + "%s" /* mcast_membership_interval */ + "%s" /* mcast_querier_interval */ + "%s" /* mcast_query_interval */ + "%s" /* mcast_query_response_interval */ + "%s" /* mcast_startup_query_interval */ + "", + name, + lnk->forward_delay, + lnk->hello_time, + lnk->max_age, + lnk->ageing_time, + (int) lnk->stp_state, + lnk->priority, + lnk->vlan_protocol, + (int) lnk->vlan_stats_enabled, + lnk->group_fwd_mask != 0 + ? nm_sprintf_buf(sbuf_gfw, "group_fwd_mask %#x ", lnk->group_fwd_mask) + : "", + NM_ETHER_ADDR_FORMAT_VAL(lnk->group_addr), + (int) lnk->mcast_snooping, + lnk->mcast_router, + (int) lnk->mcast_query_use_ifaddr, + (int) lnk->mcast_querier, + lnk->mcast_hash_max != NM_BRIDGE_MULTICAST_HASH_MAX_DEF + ? nm_sprintf_buf(sbuf_mhm, "mcast_hash_max %u ", lnk->mcast_hash_max) + : "", + lnk->mcast_last_member_count != NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF + ? nm_sprintf_buf(sbuf_mlmc, + "mcast_last_member_count %u ", + lnk->mcast_last_member_count) + : "", + lnk->mcast_startup_query_count != NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF + ? nm_sprintf_buf(sbuf_msqc, + "mcast_startup_query_count %u ", + lnk->mcast_startup_query_count) + : "", + lnk->mcast_last_member_interval != NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF + ? nm_sprintf_buf(sbuf_mlmi, + "mcast_last_member_interval %" G_GUINT64_FORMAT " ", + lnk->mcast_last_member_interval) + : "", + lnk->mcast_membership_interval != NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF + ? nm_sprintf_buf(sbuf_mmi, + "mcast_membership_interval %" G_GUINT64_FORMAT " ", + lnk->mcast_membership_interval) + : "", + lnk->mcast_querier_interval != NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF + ? nm_sprintf_buf(sbuf_mqi, + "mcast_querier_interval %" G_GUINT64_FORMAT " ", + lnk->mcast_querier_interval) + : "", + lnk->mcast_query_interval != NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF + ? nm_sprintf_buf(sbuf_mqii, + "mcast_query_interval %" G_GUINT64_FORMAT " ", + lnk->mcast_query_interval) + : "", + lnk->mcast_query_response_interval != NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF + ? nm_sprintf_buf(sbuf_mqri, + "mcast_query_response_interval %" G_GUINT64_FORMAT " ", + lnk->mcast_query_response_interval) + : "", + lnk->mcast_startup_query_interval != NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF + ? nm_sprintf_buf(sbuf_msqi, + "mcast_startup_query_interval %" G_GUINT64_FORMAT " ", + lnk->mcast_startup_query_interval) + : ""); + if (r == 0) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_BRIDGE, 100); + else + _LOGI( + "Adding bridge device via iproute2 failed. Assume iproute2 is not up to the task."); + } + + if (!pllink) { + r = nm_platform_link_bridge_add(platform, name, NULL, 0, lnk, &pllink); + } + + _assert_pllink(platform, r == 0, pllink, name, NM_LINK_TYPE_BRIDGE); + + ll = NMP_OBJECT_CAST_LNK_BRIDGE(NMP_OBJECT_UP_CAST(pllink)->_link.netlink.lnk); + + g_assert_cmpint(lnk->forward_delay, ==, ll->forward_delay); + g_assert_cmpint(lnk->hello_time, ==, ll->hello_time); + g_assert_cmpint(lnk->max_age, ==, ll->max_age); + g_assert_cmpint(lnk->ageing_time, ==, ll->ageing_time); + g_assert_cmpint(lnk->stp_state, ==, ll->stp_state); + g_assert_cmpint(lnk->priority, ==, ll->priority); + g_assert_cmpint(lnk->vlan_stats_enabled, ==, ll->vlan_stats_enabled); + g_assert_cmpint(lnk->group_fwd_mask, ==, ll->group_fwd_mask); + g_assert_cmpint(lnk->mcast_snooping, ==, ll->mcast_snooping); + g_assert_cmpint(lnk->mcast_router, ==, ll->mcast_router); + g_assert_cmpint(lnk->mcast_query_use_ifaddr, ==, ll->mcast_query_use_ifaddr); + g_assert_cmpint(lnk->mcast_querier, ==, ll->mcast_querier); + g_assert_cmpint(lnk->mcast_hash_max, ==, ll->mcast_hash_max); + g_assert_cmpint(lnk->mcast_last_member_count, ==, ll->mcast_last_member_count); + g_assert_cmpint(lnk->mcast_startup_query_count, ==, ll->mcast_startup_query_count); + g_assert_cmpint(lnk->mcast_last_member_interval, ==, ll->mcast_last_member_interval); + g_assert_cmpint(lnk->mcast_membership_interval, ==, ll->mcast_membership_interval); + g_assert_cmpint(lnk->mcast_querier_interval, ==, ll->mcast_querier_interval); + g_assert_cmpint(lnk->mcast_query_interval, ==, ll->mcast_query_interval); + g_assert_cmpint(lnk->mcast_query_response_interval, ==, ll->mcast_query_response_interval); + g_assert_cmpint(lnk->mcast_startup_query_interval, ==, ll->mcast_startup_query_interval); + + return pllink; +} +const NMPlatformLink * +nmtstp_link_veth_add(NMPlatform *platform, + gboolean external_command, + const char *name, + const char *peer) { - const NMPlatformLink *pllink = NULL; - gboolean success; + const NMPlatformLink *pllink = NULL; + gboolean success; - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); - external_command = nmtstp_run_command_check_external (external_command); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - if (external_command) { - success = !nmtstp_run_command ("ip link add dev %s type veth peer name %s", - name, peer); - if (success) { - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VETH, 100); - nmtstp_assert_wait_for_link (platform, peer, NM_LINK_TYPE_VETH, 10); - } - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_veth_add (platform, name, peer, &pllink)); + if (external_command) { + success = !nmtstp_run_command("ip link add dev %s type veth peer name %s", name, peer); + if (success) { + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_VETH, 100); + nmtstp_assert_wait_for_link(platform, peer, NM_LINK_TYPE_VETH, 10); + } + } else + success = NMTST_NM_ERR_SUCCESS(nm_platform_link_veth_add(platform, name, peer, &pllink)); - g_assert (success); - _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_VETH); - return pllink; + g_assert(success); + _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_VETH); + return pllink; } const NMPlatformLink * -nmtstp_link_dummy_add (NMPlatform *platform, - gboolean external_command, - const char *name) +nmtstp_link_dummy_add(NMPlatform *platform, gboolean external_command, const char *name) { - const NMPlatformLink *pllink = NULL; - gboolean success; + const NMPlatformLink *pllink = NULL; + gboolean success; - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); - external_command = nmtstp_run_command_check_external (external_command); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - if (external_command) { - success = !nmtstp_run_command ("ip link add %s type dummy", - name); - if (success) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_DUMMY, 100); - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_dummy_add (platform, name, &pllink)); + if (external_command) { + success = !nmtstp_run_command("ip link add %s type dummy", name); + if (success) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_DUMMY, 100); + } else + success = NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(platform, name, &pllink)); - g_assert (success); - _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_DUMMY); - return pllink; + g_assert(success); + _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_DUMMY); + return pllink; } const NMPlatformLink * -nmtstp_link_gre_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkGre *lnk) +nmtstp_link_gre_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkGre *lnk) { - const NMPlatformLink *pllink = NULL; - gboolean success; - char b1[INET_ADDRSTRLEN]; - char b2[INET_ADDRSTRLEN]; - NMLinkType link_type; + const NMPlatformLink *pllink = NULL; + gboolean success; + char b1[INET_ADDRSTRLEN]; + char b2[INET_ADDRSTRLEN]; + NMLinkType link_type; - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); - external_command = nmtstp_run_command_check_external (external_command); - link_type = lnk->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE; + external_command = nmtstp_run_command_check_external(external_command); + link_type = lnk->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE; - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - if (external_command) { - gs_free char *dev = NULL; - char *obj, *type; + if (external_command) { + gs_free char *dev = NULL; + char * obj, *type; - if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); + if (lnk->parent_ifindex) + dev = + g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex)); - obj = lnk->is_tap ? "link" : "tunnel"; - type = lnk->is_tap ? "type gretap" : "mode gre"; + obj = lnk->is_tap ? "link" : "tunnel"; + type = lnk->is_tap ? "type gretap" : "mode gre"; - success = !nmtstp_run_command ("ip %s add %s %s %s local %s remote %s ttl %u tos %02x %s", - obj, - name, - type, - dev ?: "", - _nm_utils_inet4_ntop (lnk->local, b1), - _nm_utils_inet4_ntop (lnk->remote, b2), - lnk->ttl, - lnk->tos, - lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); - if (success) - pllink = nmtstp_assert_wait_for_link (platform, name, link_type, 100); - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_gre_add (platform, name, NULL, 0, lnk, &pllink)); + success = !nmtstp_run_command("ip %s add %s %s %s local %s remote %s ttl %u tos %02x %s", + obj, + name, + type, + dev ?: "", + _nm_utils_inet4_ntop(lnk->local, b1), + _nm_utils_inet4_ntop(lnk->remote, b2), + lnk->ttl, + lnk->tos, + lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); + if (success) + pllink = nmtstp_assert_wait_for_link(platform, name, link_type, 100); + } else + success = + NMTST_NM_ERR_SUCCESS(nm_platform_link_gre_add(platform, name, NULL, 0, lnk, &pllink)); - _assert_pllink (platform, success, pllink, name, link_type); + _assert_pllink(platform, success, pllink, name, link_type); - return pllink; + return pllink; } const NMPlatformLink * -nmtstp_link_ip6tnl_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkIp6Tnl *lnk) -{ - const NMPlatformLink *pllink = NULL; - gboolean success; - char b1[NM_UTILS_INET_ADDRSTRLEN]; - char b2[NM_UTILS_INET_ADDRSTRLEN]; - char encap[20]; - char tclass[20]; - gboolean encap_ignore; - gboolean tclass_inherit; - - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); - g_assert (!lnk->is_gre); - - external_command = nmtstp_run_command_check_external (external_command); - - _init_platform (&platform, external_command); - - if (external_command) { - gs_free char *dev = NULL; - const char *mode; - - if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); - - switch (lnk->proto) { - case IPPROTO_IPIP: - mode = "ipip6"; - break; - case IPPROTO_IPV6: - mode = "ip6ip6"; - break; - default: - g_assert_not_reached (); - } - - encap_ignore = NM_FLAGS_HAS (lnk->flags, IP6_TNL_F_IGN_ENCAP_LIMIT); - tclass_inherit = NM_FLAGS_HAS (lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS); - - success = !nmtstp_run_command ("ip -6 tunnel add %s mode %s %s local %s remote %s ttl %u tclass %s encaplimit %s flowlabel %x", - name, - mode, - dev, - _nm_utils_inet6_ntop (&lnk->local, b1), - _nm_utils_inet6_ntop (&lnk->remote, b2), - lnk->ttl, - tclass_inherit ? "inherit" : nm_sprintf_buf (tclass, "%02x", lnk->tclass), - encap_ignore ? "none" : nm_sprintf_buf (encap, "%u", lnk->encap_limit), - lnk->flow_label); - if (success) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_IP6TNL, 100); - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_ip6tnl_add (platform, name, lnk, &pllink)); - - _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_IP6TNL); - - return pllink; +nmtstp_link_ip6tnl_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkIp6Tnl *lnk) +{ + const NMPlatformLink *pllink = NULL; + gboolean success; + char b1[NM_UTILS_INET_ADDRSTRLEN]; + char b2[NM_UTILS_INET_ADDRSTRLEN]; + char encap[20]; + char tclass[20]; + gboolean encap_ignore; + gboolean tclass_inherit; + + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); + g_assert(!lnk->is_gre); + + external_command = nmtstp_run_command_check_external(external_command); + + _init_platform(&platform, external_command); + + if (external_command) { + gs_free char *dev = NULL; + const char * mode; + + if (lnk->parent_ifindex) + dev = + g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex)); + + switch (lnk->proto) { + case IPPROTO_IPIP: + mode = "ipip6"; + break; + case IPPROTO_IPV6: + mode = "ip6ip6"; + break; + default: + g_assert_not_reached(); + } + + encap_ignore = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_IGN_ENCAP_LIMIT); + tclass_inherit = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS); + + success = !nmtstp_run_command( + "ip -6 tunnel add %s mode %s %s local %s remote %s ttl %u tclass %s encaplimit %s " + "flowlabel %x", + name, + mode, + dev, + _nm_utils_inet6_ntop(&lnk->local, b1), + _nm_utils_inet6_ntop(&lnk->remote, b2), + lnk->ttl, + tclass_inherit ? "inherit" : nm_sprintf_buf(tclass, "%02x", lnk->tclass), + encap_ignore ? "none" : nm_sprintf_buf(encap, "%u", lnk->encap_limit), + lnk->flow_label); + if (success) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_IP6TNL, 100); + } else + success = NMTST_NM_ERR_SUCCESS(nm_platform_link_ip6tnl_add(platform, name, lnk, &pllink)); + + _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_IP6TNL); + + return pllink; } const NMPlatformLink * -nmtstp_link_ip6gre_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkIp6Tnl *lnk) -{ - const NMPlatformLink *pllink = NULL; - gboolean success; - char b1[NM_UTILS_INET_ADDRSTRLEN]; - char b2[NM_UTILS_INET_ADDRSTRLEN]; - char tclass[20]; - gboolean tclass_inherit; - - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); - g_assert (lnk->is_gre); - - external_command = nmtstp_run_command_check_external (external_command); - - _init_platform (&platform, external_command); - - if (external_command) { - gs_free char *dev = NULL; - - if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); - - tclass_inherit = NM_FLAGS_HAS (lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS); - - success = !nmtstp_run_command ("ip link add %s type %s %s local %s remote %s ttl %u tclass %s flowlabel %x", - name, - lnk->is_tap ? "ip6gretap" : "ip6gre", - dev, - _nm_utils_inet6_ntop (&lnk->local, b1), - _nm_utils_inet6_ntop (&lnk->remote, b2), - lnk->ttl, - tclass_inherit ? "inherit" : nm_sprintf_buf (tclass, "%02x", lnk->tclass), - lnk->flow_label); - if (success) { - pllink = nmtstp_assert_wait_for_link (platform, - name, - lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, - 100); - } - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_ip6gre_add (platform, name, NULL, 0, lnk, &pllink)); - - _assert_pllink (platform, success, pllink, name, lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE); - - return pllink; +nmtstp_link_ip6gre_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkIp6Tnl *lnk) +{ + const NMPlatformLink *pllink = NULL; + gboolean success; + char b1[NM_UTILS_INET_ADDRSTRLEN]; + char b2[NM_UTILS_INET_ADDRSTRLEN]; + char tclass[20]; + gboolean tclass_inherit; + + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); + g_assert(lnk->is_gre); + + external_command = nmtstp_run_command_check_external(external_command); + + _init_platform(&platform, external_command); + + if (external_command) { + gs_free char *dev = NULL; + + if (lnk->parent_ifindex) + dev = + g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex)); + + tclass_inherit = NM_FLAGS_HAS(lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS); + + success = !nmtstp_run_command( + "ip link add %s type %s %s local %s remote %s ttl %u tclass %s flowlabel %x", + name, + lnk->is_tap ? "ip6gretap" : "ip6gre", + dev, + _nm_utils_inet6_ntop(&lnk->local, b1), + _nm_utils_inet6_ntop(&lnk->remote, b2), + lnk->ttl, + tclass_inherit ? "inherit" : nm_sprintf_buf(tclass, "%02x", lnk->tclass), + lnk->flow_label); + if (success) { + pllink = nmtstp_assert_wait_for_link(platform, + name, + lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP + : NM_LINK_TYPE_IP6GRE, + 100); + } + } else + success = NMTST_NM_ERR_SUCCESS( + nm_platform_link_ip6gre_add(platform, name, NULL, 0, lnk, &pllink)); + + _assert_pllink(platform, + success, + pllink, + name, + lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE); + + return pllink; } const NMPlatformLink * -nmtstp_link_ipip_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkIpIp *lnk) +nmtstp_link_ipip_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkIpIp *lnk) { - const NMPlatformLink *pllink = NULL; - gboolean success; - char b1[INET_ADDRSTRLEN]; - char b2[INET_ADDRSTRLEN]; + const NMPlatformLink *pllink = NULL; + gboolean success; + char b1[INET_ADDRSTRLEN]; + char b2[INET_ADDRSTRLEN]; - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); - external_command = nmtstp_run_command_check_external (external_command); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - if (external_command) { - gs_free char *dev = NULL; + if (external_command) { + gs_free char *dev = NULL; - if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); + if (lnk->parent_ifindex) + dev = + g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex)); - success = !nmtstp_run_command ("ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s", - name, - dev, - _nm_utils_inet4_ntop (lnk->local, b1), - _nm_utils_inet4_ntop (lnk->remote, b2), - lnk->ttl, - lnk->tos, - lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); - if (success) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_IPIP, 100); - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_ipip_add (platform, name, lnk, &pllink)); + success = !nmtstp_run_command( + "ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s", + name, + dev, + _nm_utils_inet4_ntop(lnk->local, b1), + _nm_utils_inet4_ntop(lnk->remote, b2), + lnk->ttl, + lnk->tos, + lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); + if (success) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_IPIP, 100); + } else + success = NMTST_NM_ERR_SUCCESS(nm_platform_link_ipip_add(platform, name, lnk, &pllink)); - _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_IPIP); + _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_IPIP); - return pllink; + return pllink; } const NMPlatformLink * -nmtstp_link_macvlan_add (NMPlatform *platform, - gboolean external_command, - const char *name, - int parent, - const NMPlatformLnkMacvlan *lnk) +nmtstp_link_macvlan_add(NMPlatform * platform, + gboolean external_command, + const char * name, + int parent, + const NMPlatformLnkMacvlan *lnk) { - const NMPlatformLink *pllink = NULL; - gboolean success; - NMLinkType link_type; + const NMPlatformLink *pllink = NULL; + gboolean success; + NMLinkType link_type; - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); - external_command = nmtstp_run_command_check_external (external_command); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - link_type = lnk->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN; + link_type = lnk->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN; - if (external_command) { - const char *dev; - char *modes[] = { - [MACVLAN_MODE_BRIDGE] = "bridge", - [MACVLAN_MODE_VEPA] = "vepa", - [MACVLAN_MODE_PRIVATE] = "private", - [MACVLAN_MODE_PASSTHRU] = "passthru", - }; + if (external_command) { + const char *dev; + char * modes[] = { + [MACVLAN_MODE_BRIDGE] = "bridge", + [MACVLAN_MODE_VEPA] = "vepa", + [MACVLAN_MODE_PRIVATE] = "private", + [MACVLAN_MODE_PASSTHRU] = "passthru", + }; - dev = nm_platform_link_get_name (platform, parent); - g_assert (dev); - g_assert_cmpint (lnk->mode, <, G_N_ELEMENTS (modes)); + dev = nm_platform_link_get_name(platform, parent); + g_assert(dev); + g_assert_cmpint(lnk->mode, <, G_N_ELEMENTS(modes)); - success = !nmtstp_run_command ("ip link add name %s link %s type %s mode %s %s", - name, - dev, - lnk->tap ? "macvtap" : "macvlan", - modes[lnk->mode], - lnk->no_promisc ? "nopromisc" : ""); - if (success) - pllink = nmtstp_assert_wait_for_link (platform, name, link_type, 100); - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_macvlan_add (platform, name, parent, lnk, &pllink)); + success = !nmtstp_run_command("ip link add name %s link %s type %s mode %s %s", + name, + dev, + lnk->tap ? "macvtap" : "macvlan", + modes[lnk->mode], + lnk->no_promisc ? "nopromisc" : ""); + if (success) + pllink = nmtstp_assert_wait_for_link(platform, name, link_type, 100); + } else + success = NMTST_NM_ERR_SUCCESS( + nm_platform_link_macvlan_add(platform, name, parent, lnk, &pllink)); - _assert_pllink (platform, success, pllink, name, link_type); + _assert_pllink(platform, success, pllink, name, link_type); - return pllink; + return pllink; } const NMPlatformLink * -nmtstp_link_sit_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkSit *lnk) +nmtstp_link_sit_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkSit *lnk) { - const NMPlatformLink *pllink = NULL; - gboolean success; - char b1[INET_ADDRSTRLEN]; - char b2[INET_ADDRSTRLEN]; + const NMPlatformLink *pllink = NULL; + gboolean success; + char b1[INET_ADDRSTRLEN]; + char b2[INET_ADDRSTRLEN]; - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); - external_command = nmtstp_run_command_check_external (external_command); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - if (external_command) { - const char *dev = ""; + if (external_command) { + const char *dev = ""; - if (lnk->parent_ifindex) { - const char *parent_name; + if (lnk->parent_ifindex) { + const char *parent_name; - parent_name = nm_platform_link_get_name (platform, lnk->parent_ifindex); - g_assert (parent_name); - dev = nm_sprintf_bufa (100, " dev %s", parent_name); - } + parent_name = nm_platform_link_get_name(platform, lnk->parent_ifindex); + g_assert(parent_name); + dev = nm_sprintf_bufa(100, " dev %s", parent_name); + } - success = !nmtstp_run_command ("ip tunnel add %s mode sit%s local %s remote %s ttl %u tos %02x %s", - name, - dev, - _nm_utils_inet4_ntop (lnk->local, b1), - _nm_utils_inet4_ntop (lnk->remote, b2), - lnk->ttl, - lnk->tos, - lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); - if (success) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_SIT, 100); - } else - success = NMTST_NM_ERR_SUCCESS (nm_platform_link_sit_add (platform, name, lnk, &pllink)); + success = + !nmtstp_run_command("ip tunnel add %s mode sit%s local %s remote %s ttl %u tos %02x %s", + name, + dev, + _nm_utils_inet4_ntop(lnk->local, b1), + _nm_utils_inet4_ntop(lnk->remote, b2), + lnk->ttl, + lnk->tos, + lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); + if (success) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_SIT, 100); + } else + success = NMTST_NM_ERR_SUCCESS(nm_platform_link_sit_add(platform, name, lnk, &pllink)); - _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_SIT); + _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_SIT); - return pllink; + return pllink; } const NMPlatformLink * -nmtstp_link_tun_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkTun *lnk, - int *out_fd) -{ - const NMPlatformLink *pllink = NULL; - int err; - int r; - - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); - g_assert (lnk); - g_assert (NM_IN_SET (lnk->type, IFF_TUN, IFF_TAP)); - g_assert (!out_fd || *out_fd == -1); - - if (!lnk->persist) { - /* ip tuntap does not support non-persistent devices. - * - * Add this device only via NMPlatform. */ - if (external_command == -1) - external_command = FALSE; - } - - external_command = nmtstp_run_command_check_external (external_command); - - _init_platform (&platform, external_command); - - if (external_command) { - g_assert (lnk->persist); - - err = nmtstp_run_command ("ip tuntap add" - " mode %s" - "%s" /* user */ - "%s" /* group */ - "%s" /* pi */ - "%s" /* vnet_hdr */ - "%s" /* multi_queue */ - " name %s", - lnk->type == IFF_TUN ? "tun" : "tap", - lnk->owner_valid ? nm_sprintf_bufa (100, " user %u", (guint) lnk->owner) : "", - lnk->group_valid ? nm_sprintf_bufa (100, " group %u", (guint) lnk->group) : "", - lnk->pi ? " pi" : "", - lnk->vnet_hdr ? " vnet_hdr" : "", - lnk->multi_queue ? " multi_queue" : "", - name); - /* Older versions of iproute2 don't support adding devices. - * On failure, fallback to using platform code. */ - if (err == 0) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_TUN, 100); - else - g_error ("failure to add tun/tap device via ip-route"); - } else { - g_assert (lnk->persist || out_fd); - r = nm_platform_link_tun_add (platform, name, lnk, &pllink, out_fd); - g_assert_cmpint (r, ==, 0); - } - - g_assert (pllink); - g_assert_cmpint (pllink->type, ==, NM_LINK_TYPE_TUN); - g_assert_cmpstr (pllink->name, ==, name); - return pllink; +nmtstp_link_tun_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkTun *lnk, + int * out_fd) +{ + const NMPlatformLink *pllink = NULL; + int err; + int r; + + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); + g_assert(lnk); + g_assert(NM_IN_SET(lnk->type, IFF_TUN, IFF_TAP)); + g_assert(!out_fd || *out_fd == -1); + + if (!lnk->persist) { + /* ip tuntap does not support non-persistent devices. + * + * Add this device only via NMPlatform. */ + if (external_command == -1) + external_command = FALSE; + } + + external_command = nmtstp_run_command_check_external(external_command); + + _init_platform(&platform, external_command); + + if (external_command) { + g_assert(lnk->persist); + + err = nmtstp_run_command( + "ip tuntap add" + " mode %s" + "%s" /* user */ + "%s" /* group */ + "%s" /* pi */ + "%s" /* vnet_hdr */ + "%s" /* multi_queue */ + " name %s", + lnk->type == IFF_TUN ? "tun" : "tap", + lnk->owner_valid ? nm_sprintf_bufa(100, " user %u", (guint) lnk->owner) : "", + lnk->group_valid ? nm_sprintf_bufa(100, " group %u", (guint) lnk->group) : "", + lnk->pi ? " pi" : "", + lnk->vnet_hdr ? " vnet_hdr" : "", + lnk->multi_queue ? " multi_queue" : "", + name); + /* Older versions of iproute2 don't support adding devices. + * On failure, fallback to using platform code. */ + if (err == 0) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_TUN, 100); + else + g_error("failure to add tun/tap device via ip-route"); + } else { + g_assert(lnk->persist || out_fd); + r = nm_platform_link_tun_add(platform, name, lnk, &pllink, out_fd); + g_assert_cmpint(r, ==, 0); + } + + g_assert(pllink); + g_assert_cmpint(pllink->type, ==, NM_LINK_TYPE_TUN); + g_assert_cmpstr(pllink->name, ==, name); + return pllink; } const NMPlatformLink * -nmtstp_link_vrf_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkVrf *lnk, - gboolean *out_not_supported) +nmtstp_link_vrf_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkVrf *lnk, + gboolean * out_not_supported) { - const NMPlatformLink *pllink = NULL; - int r = 0; + const NMPlatformLink *pllink = NULL; + int r = 0; - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); - NM_SET_OUT (out_not_supported, FALSE); - external_command = nmtstp_run_command_check_external (external_command); + NM_SET_OUT(out_not_supported, FALSE); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - if (external_command) { - r = nmtstp_run_command ("ip link add %s type vrf table %u", - name, - lnk->table); + if (external_command) { + r = nmtstp_run_command("ip link add %s type vrf table %u", name, lnk->table); - if (r == 0) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VRF, 100); - else - _LOGI ("Adding vrf device via iproute2 failed. Assume iproute2 is not up to the task."); - } + if (r == 0) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_VRF, 100); + else + _LOGI("Adding vrf device via iproute2 failed. Assume iproute2 is not up to the task."); + } - if (!pllink) { - r = nm_platform_link_vrf_add (platform, name, lnk, &pllink); - if (r == -EOPNOTSUPP) - NM_SET_OUT (out_not_supported, TRUE); - } + if (!pllink) { + r = nm_platform_link_vrf_add(platform, name, lnk, &pllink); + if (r == -EOPNOTSUPP) + NM_SET_OUT(out_not_supported, TRUE); + } - _assert_pllink (platform, r == 0, pllink, name, NM_LINK_TYPE_VRF); + _assert_pllink(platform, r == 0, pllink, name, NM_LINK_TYPE_VRF); - return pllink; + return pllink; } const NMPlatformLink * -nmtstp_link_vxlan_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkVxlan *lnk) -{ - const NMPlatformLink *pllink = NULL; - int err; - int r; - - g_assert (nm_utils_ifname_valid_kernel (name, NULL)); - - external_command = nmtstp_run_command_check_external (external_command); - - _init_platform (&platform, external_command); - - if (external_command) { - gs_free char *dev = NULL; - char local[NM_UTILS_INET_ADDRSTRLEN]; - char group[NM_UTILS_INET_ADDRSTRLEN]; - - if (lnk->parent_ifindex) - dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); - - if (lnk->local) - _nm_utils_inet4_ntop (lnk->local, local); - else if (memcmp (&lnk->local6, &in6addr_any, sizeof (in6addr_any))) - _nm_utils_inet6_ntop (&lnk->local6, local); - else - local[0] = '\0'; - - if (lnk->group) - _nm_utils_inet4_ntop (lnk->group, group); - else if (memcmp (&lnk->group6, &in6addr_any, sizeof (in6addr_any))) - _nm_utils_inet6_ntop (&lnk->group6, group); - else - group[0] = '\0'; - - err = nmtstp_run_command ("ip link add %s type vxlan id %u %s local %s group %s ttl %u tos %02x dstport %u srcport %u %u ageing %u", - name, - lnk->id, - dev ?: "", - local, - group, - lnk->ttl, - lnk->tos, - lnk->dst_port, - lnk->src_port_min, lnk->src_port_max, - lnk->ageing); - /* Older versions of iproute2 don't support adding vxlan devices. - * On failure, fallback to using platform code. */ - if (err == 0) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VXLAN, 100); - else - _LOGI ("Adding vxlan device via iproute2 failed. Assume iproute2 is not up to the task."); - } - if (!pllink) { - r = nm_platform_link_vxlan_add (platform, name, lnk, &pllink); - g_assert (NMTST_NM_ERR_SUCCESS (r)); - g_assert (pllink); - } - - g_assert_cmpint (pllink->type, ==, NM_LINK_TYPE_VXLAN); - g_assert_cmpstr (pllink->name, ==, name); - return pllink; +nmtstp_link_vxlan_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkVxlan *lnk) +{ + const NMPlatformLink *pllink = NULL; + int err; + int r; + + g_assert(nm_utils_ifname_valid_kernel(name, NULL)); + + external_command = nmtstp_run_command_check_external(external_command); + + _init_platform(&platform, external_command); + + if (external_command) { + gs_free char *dev = NULL; + char local[NM_UTILS_INET_ADDRSTRLEN]; + char group[NM_UTILS_INET_ADDRSTRLEN]; + + if (lnk->parent_ifindex) + dev = + g_strdup_printf("dev %s", nm_platform_link_get_name(platform, lnk->parent_ifindex)); + + if (lnk->local) + _nm_utils_inet4_ntop(lnk->local, local); + else if (memcmp(&lnk->local6, &in6addr_any, sizeof(in6addr_any))) + _nm_utils_inet6_ntop(&lnk->local6, local); + else + local[0] = '\0'; + + if (lnk->group) + _nm_utils_inet4_ntop(lnk->group, group); + else if (memcmp(&lnk->group6, &in6addr_any, sizeof(in6addr_any))) + _nm_utils_inet6_ntop(&lnk->group6, group); + else + group[0] = '\0'; + + err = nmtstp_run_command("ip link add %s type vxlan id %u %s local %s group %s ttl %u tos " + "%02x dstport %u srcport %u %u ageing %u", + name, + lnk->id, + dev ?: "", + local, + group, + lnk->ttl, + lnk->tos, + lnk->dst_port, + lnk->src_port_min, + lnk->src_port_max, + lnk->ageing); + /* Older versions of iproute2 don't support adding vxlan devices. + * On failure, fallback to using platform code. */ + if (err == 0) + pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_VXLAN, 100); + else + _LOGI( + "Adding vxlan device via iproute2 failed. Assume iproute2 is not up to the task."); + } + if (!pllink) { + r = nm_platform_link_vxlan_add(platform, name, lnk, &pllink); + g_assert(NMTST_NM_ERR_SUCCESS(r)); + g_assert(pllink); + } + + g_assert_cmpint(pllink->type, ==, NM_LINK_TYPE_VXLAN); + g_assert_cmpstr(pllink->name, ==, name); + return pllink; } /*****************************************************************************/ const NMPlatformLink * -nmtstp_link_get_typed (NMPlatform *platform, - int ifindex, - const char *name, - NMLinkType link_type) +nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type) { - const NMPlatformLink *pllink = NULL; + const NMPlatformLink *pllink = NULL; - _init_platform (&platform, FALSE); + _init_platform(&platform, FALSE); - if (ifindex > 0) { - pllink = nm_platform_link_get (platform, ifindex); + if (ifindex > 0) { + pllink = nm_platform_link_get(platform, ifindex); - if (pllink) { - g_assert_cmpint (pllink->ifindex, ==, ifindex); - if (name) - g_assert_cmpstr (name, ==, pllink->name); - } else { - if (name) - g_assert (!nm_platform_link_get_by_ifname (platform, name)); - } - } else { - g_assert (name); + if (pllink) { + g_assert_cmpint(pllink->ifindex, ==, ifindex); + if (name) + g_assert_cmpstr(name, ==, pllink->name); + } else { + if (name) + g_assert(!nm_platform_link_get_by_ifname(platform, name)); + } + } else { + g_assert(name); - pllink = nm_platform_link_get_by_ifname (platform, name); + pllink = nm_platform_link_get_by_ifname(platform, name); - if (pllink) - g_assert_cmpstr (name, ==, pllink->name); - } + if (pllink) + g_assert_cmpstr(name, ==, pllink->name); + } - g_assert (!name || nm_utils_ifname_valid_kernel (name, NULL)); + g_assert(!name || nm_utils_ifname_valid_kernel(name, NULL)); - if (pllink && link_type != NM_LINK_TYPE_NONE) - g_assert_cmpint (pllink->type, ==, link_type); + if (pllink && link_type != NM_LINK_TYPE_NONE) + g_assert_cmpint(pllink->type, ==, link_type); - return pllink; + return pllink; } const NMPlatformLink * -nmtstp_link_get (NMPlatform *platform, - int ifindex, - const char *name) +nmtstp_link_get(NMPlatform *platform, int ifindex, const char *name) { - return nmtstp_link_get_typed (platform, ifindex, name, NM_LINK_TYPE_NONE); + return nmtstp_link_get_typed(platform, ifindex, name, NM_LINK_TYPE_NONE); } /*****************************************************************************/ void -nmtstp_link_delete (NMPlatform *platform, - gboolean external_command, - int ifindex, - const char *name, - gboolean require_exist) +nmtstp_link_delete(NMPlatform *platform, + gboolean external_command, + int ifindex, + const char *name, + gboolean require_exist) { - gint64 end_time; - const NMPlatformLink *pllink; - gboolean success; - gs_free char *name_copy = NULL; + gint64 end_time; + const NMPlatformLink *pllink; + gboolean success; + gs_free char * name_copy = NULL; - external_command = nmtstp_run_command_check_external (external_command); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - pllink = nmtstp_link_get (platform, ifindex, name); + pllink = nmtstp_link_get(platform, ifindex, name); - if (!pllink) { - g_assert (!require_exist); - return; - } + if (!pllink) { + g_assert(!require_exist); + return; + } - name = name_copy = g_strdup (pllink->name); - ifindex = pllink->ifindex; + name = name_copy = g_strdup(pllink->name); + ifindex = pllink->ifindex; - if (external_command) { - nmtstp_run_command_check ("ip link delete %s", name); - } else { - success = nm_platform_link_delete (platform, ifindex); - g_assert (success); - } + if (external_command) { + nmtstp_run_command_check("ip link delete %s", name); + } else { + success = nm_platform_link_delete(platform, ifindex); + g_assert(success); + } - /* Let's wait until we get the result */ - end_time = nm_utils_get_monotonic_timestamp_msec () + 250; - do { - if (external_command) - nm_platform_process_events (platform); + /* Let's wait until we get the result */ + end_time = nm_utils_get_monotonic_timestamp_msec() + 250; + do { + if (external_command) + nm_platform_process_events(platform); - if (!nm_platform_link_get (platform, ifindex)) { - g_assert (!nm_platform_link_get_by_ifname (platform, name)); - break; - } + if (!nm_platform_link_get(platform, ifindex)) { + g_assert(!nm_platform_link_get_by_ifname(platform, name)); + break; + } - /* for internal command, we expect not to reach this line.*/ - g_assert (external_command); + /* for internal command, we expect not to reach this line.*/ + g_assert(external_command); - nmtstp_assert_wait_for_signal_until (platform, end_time); - } while (TRUE); + nmtstp_assert_wait_for_signal_until(platform, end_time); + } while (TRUE); } /*****************************************************************************/ void -nmtstp_link_set_updown (NMPlatform *platform, - gboolean external_command, - int ifindex, - gboolean up) +nmtstp_link_set_updown(NMPlatform *platform, gboolean external_command, int ifindex, gboolean up) { - const NMPlatformLink *plink; - gint64 end_time; + const NMPlatformLink *plink; + gint64 end_time; - external_command = nmtstp_run_command_check_external (external_command); + external_command = nmtstp_run_command_check_external(external_command); - _init_platform (&platform, external_command); + _init_platform(&platform, external_command); - if (external_command) { - const char *ifname; + if (external_command) { + const char *ifname; - ifname = nm_platform_link_get_name (platform, ifindex); - g_assert (ifname); + ifname = nm_platform_link_get_name(platform, ifindex); + g_assert(ifname); - nmtstp_run_command_check ("ip link set %s %s", - ifname, - up ? "up" : "down"); - } else { - if (up) - g_assert (nm_platform_link_set_up (platform, ifindex, NULL)); - else - g_assert (nm_platform_link_set_down (platform, ifindex)); - } + nmtstp_run_command_check("ip link set %s %s", ifname, up ? "up" : "down"); + } else { + if (up) + g_assert(nm_platform_link_set_up(platform, ifindex, NULL)); + else + g_assert(nm_platform_link_set_down(platform, ifindex)); + } - /* Let's wait until we get the result */ - end_time = nm_utils_get_monotonic_timestamp_msec () + 250; - do { - if (external_command) - nm_platform_process_events (platform); + /* Let's wait until we get the result */ + end_time = nm_utils_get_monotonic_timestamp_msec() + 250; + do { + if (external_command) + nm_platform_process_events(platform); - /* let's wait until we see the address as we added it. */ - plink = nm_platform_link_get (platform, ifindex); - g_assert (plink); + /* let's wait until we see the address as we added it. */ + plink = nm_platform_link_get(platform, ifindex); + g_assert(plink); - if (NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP) == !!up) - break; + if (NM_FLAGS_HAS(plink->n_ifi_flags, IFF_UP) == !!up) + break; + + /* for internal command, we expect not to reach this line.*/ + g_assert(external_command); + + nmtstp_assert_wait_for_signal_until(platform, end_time); + } while (TRUE); +} + +/*****************************************************************************/ + +gboolean +nmtstp_kernel_support_get(NMPlatformKernelSupportType type) +{ + const NMPlatformLink *pllink; + NMTernary v; - /* for internal command, we expect not to reach this line.*/ - g_assert (external_command); + v = nm_platform_kernel_support_get_full(type, FALSE); + if (v != NM_TERNARY_DEFAULT) + return v != NM_TERNARY_FALSE; - nmtstp_assert_wait_for_signal_until (platform, end_time); - } while (TRUE); + switch (type) { + case NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED: + pllink = nmtstp_link_bridge_add(NULL, -1, "br-test-11", &nm_platform_lnk_bridge_default); + nmtstp_link_delete(NULL, -1, pllink->ifindex, NULL, TRUE); + v = nm_platform_kernel_support_get_full(type, FALSE); + g_assert(v != NM_TERNARY_DEFAULT); + return v; + default: + g_assert_not_reached(); + } } /*****************************************************************************/ struct _NMTstpNamespaceHandle { - pid_t pid; - int pipe_fd; + pid_t pid; + int pipe_fd; }; NMTstpNamespaceHandle * -nmtstp_namespace_create (int unshare_flags, GError **error) -{ - NMTstpNamespaceHandle *ns_handle; - int e; - int errsv; - pid_t pid, pid2; - int pipefd_c2p[2]; - int pipefd_p2c[2]; - ssize_t r; - - e = pipe2 (pipefd_c2p, O_CLOEXEC); - if (e != 0) { - errsv = errno; - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "pipe() failed with %d (%s)", errsv, nm_strerror_native (errsv)); - return FALSE; - } - - e = pipe2 (pipefd_p2c, O_CLOEXEC); - if (e != 0) { - errsv = errno; - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "pipe() failed with %d (%s)", errsv, nm_strerror_native (errsv)); - nm_close (pipefd_c2p[0]); - nm_close (pipefd_c2p[1]); - return FALSE; - } - - pid = fork (); - if (pid < 0) { - errsv = errno; - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "fork() failed with %d (%s)", errsv, nm_strerror_native (errsv)); - nm_close (pipefd_c2p[0]); - nm_close (pipefd_c2p[1]); - nm_close (pipefd_p2c[0]); - nm_close (pipefd_p2c[1]); - return FALSE; - } - - if (pid == 0) { - char read_buf[1]; - - nm_close (pipefd_c2p[0]); /* close read-end */ - nm_close (pipefd_p2c[1]); /* close write-end */ - - if (unshare (unshare_flags) != 0) { - errsv = errno; - if (errsv == 0) - errsv = -1; - } else - errsv = 0; - - /* sync with parent process and send result. */ - do { - r = write (pipefd_c2p[1], &errsv, sizeof (errsv)); - } while (r < 0 && errno == EINTR); - if (r != sizeof (errsv)) { - errsv = errno; - if (errsv == 0) - errsv = -2; - } - nm_close (pipefd_c2p[1]); - - /* wait until parent process terminates (or kills us). */ - if (errsv == 0) { - do { - r = read (pipefd_p2c[0], read_buf, sizeof (read_buf)); - } while (r < 0 && errno == EINTR); - } - nm_close (pipefd_p2c[0]); - _exit (0); - } - - nm_close (pipefd_c2p[1]); /* close write-end */ - nm_close (pipefd_p2c[0]); /* close read-end */ - - /* sync with child process. */ - do { - r = read (pipefd_c2p[0], &errsv, sizeof (errsv)); - } while (r < 0 && errno == EINTR); - - nm_close (pipefd_c2p[0]); - - if ( r != sizeof (errsv) - || errsv != 0) { - int status; - - if (r != sizeof (errsv)) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "child process failed for unknown reason"); - } else { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "child process signaled failure %d (%s)", errsv, nm_strerror_native (errsv)); - } - nm_close (pipefd_p2c[1]); - kill (pid, SIGKILL); - do { - pid2 = waitpid (pid, &status, 0); - } while (pid2 == -1 && errno == EINTR); - return FALSE; - } - - ns_handle = g_new0 (NMTstpNamespaceHandle, 1); - ns_handle->pid = pid; - ns_handle->pipe_fd = pipefd_p2c[1]; - return ns_handle; +nmtstp_namespace_create(int unshare_flags, GError **error) +{ + NMTstpNamespaceHandle *ns_handle; + int e; + int errsv; + pid_t pid, pid2; + int pipefd_c2p[2]; + int pipefd_p2c[2]; + ssize_t r; + + e = pipe2(pipefd_c2p, O_CLOEXEC); + if (e != 0) { + errsv = errno; + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "pipe() failed with %d (%s)", + errsv, + nm_strerror_native(errsv)); + return FALSE; + } + + e = pipe2(pipefd_p2c, O_CLOEXEC); + if (e != 0) { + errsv = errno; + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "pipe() failed with %d (%s)", + errsv, + nm_strerror_native(errsv)); + nm_close(pipefd_c2p[0]); + nm_close(pipefd_c2p[1]); + return FALSE; + } + + pid = fork(); + if (pid < 0) { + errsv = errno; + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "fork() failed with %d (%s)", + errsv, + nm_strerror_native(errsv)); + nm_close(pipefd_c2p[0]); + nm_close(pipefd_c2p[1]); + nm_close(pipefd_p2c[0]); + nm_close(pipefd_p2c[1]); + return FALSE; + } + + if (pid == 0) { + char read_buf[1]; + + nm_close(pipefd_c2p[0]); /* close read-end */ + nm_close(pipefd_p2c[1]); /* close write-end */ + + if (unshare(unshare_flags) != 0) { + errsv = errno; + if (errsv == 0) + errsv = -1; + } else + errsv = 0; + + /* sync with parent process and send result. */ + do { + r = write(pipefd_c2p[1], &errsv, sizeof(errsv)); + } while (r < 0 && errno == EINTR); + if (r != sizeof(errsv)) { + errsv = errno; + if (errsv == 0) + errsv = -2; + } + nm_close(pipefd_c2p[1]); + + /* wait until parent process terminates (or kills us). */ + if (errsv == 0) { + do { + r = read(pipefd_p2c[0], read_buf, sizeof(read_buf)); + } while (r < 0 && errno == EINTR); + } + nm_close(pipefd_p2c[0]); + _exit(0); + } + + nm_close(pipefd_c2p[1]); /* close write-end */ + nm_close(pipefd_p2c[0]); /* close read-end */ + + /* sync with child process. */ + do { + r = read(pipefd_c2p[0], &errsv, sizeof(errsv)); + } while (r < 0 && errno == EINTR); + + nm_close(pipefd_c2p[0]); + + if (r != sizeof(errsv) || errsv != 0) { + int status; + + if (r != sizeof(errsv)) { + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "child process failed for unknown reason"); + } else { + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_UNKNOWN, + "child process signaled failure %d (%s)", + errsv, + nm_strerror_native(errsv)); + } + nm_close(pipefd_p2c[1]); + kill(pid, SIGKILL); + do { + pid2 = waitpid(pid, &status, 0); + } while (pid2 == -1 && errno == EINTR); + return FALSE; + } + + ns_handle = g_new0(NMTstpNamespaceHandle, 1); + ns_handle->pid = pid; + ns_handle->pipe_fd = pipefd_p2c[1]; + return ns_handle; } pid_t -nmtstp_namespace_handle_get_pid (NMTstpNamespaceHandle *ns_handle) +nmtstp_namespace_handle_get_pid(NMTstpNamespaceHandle *ns_handle) { - g_return_val_if_fail (ns_handle, 0); - g_return_val_if_fail (ns_handle->pid > 0, 0); + g_return_val_if_fail(ns_handle, 0); + g_return_val_if_fail(ns_handle->pid > 0, 0); - return ns_handle->pid; + return ns_handle->pid; } void -nmtstp_namespace_handle_release (NMTstpNamespaceHandle *ns_handle) +nmtstp_namespace_handle_release(NMTstpNamespaceHandle *ns_handle) { - pid_t pid; - int status; + pid_t pid; + int status; - if (!ns_handle) - return; + if (!ns_handle) + return; - g_return_if_fail (ns_handle->pid > 0); + g_return_if_fail(ns_handle->pid > 0); - nm_close (ns_handle->pipe_fd); - ns_handle->pipe_fd = 0; + nm_close(ns_handle->pipe_fd); + ns_handle->pipe_fd = 0; - kill (ns_handle->pid, SIGKILL); + kill(ns_handle->pid, SIGKILL); - do { - pid = waitpid (ns_handle->pid, &status, 0); - } while (pid == -1 && errno == EINTR); - ns_handle->pid = 0; + do { + pid = waitpid(ns_handle->pid, &status, 0); + } while (pid == -1 && errno == EINTR); + ns_handle->pid = 0; - g_free (ns_handle); + g_free(ns_handle); } int -nmtstp_namespace_get_fd_for_process (pid_t pid, const char *ns_name) +nmtstp_namespace_get_fd_for_process(pid_t pid, const char *ns_name) { - char p[1000]; + char p[1000]; - g_return_val_if_fail (pid > 0, 0); - g_return_val_if_fail (ns_name && ns_name[0] && strlen (ns_name) < 50, 0); + g_return_val_if_fail(pid > 0, 0); + g_return_val_if_fail(ns_name && ns_name[0] && strlen(ns_name) < 50, 0); - nm_sprintf_buf (p, "/proc/%lu/ns/%s", (unsigned long) pid, ns_name); + nm_sprintf_buf(p, "/proc/%lu/ns/%s", (unsigned long) pid, ns_name); - return open(p, O_RDONLY | O_CLOEXEC); + return open(p, O_RDONLY | O_CLOEXEC); } /*****************************************************************************/ void -nmtstp_netns_select_random (NMPlatform **platforms, gsize n_platforms, NMPNetns **netns) +nmtstp_netns_select_random(NMPlatform **platforms, gsize n_platforms, NMPNetns **netns) { - int i; + int i; - g_assert (platforms); - g_assert (n_platforms && n_platforms <= G_MAXINT32); - g_assert (netns && !*netns); - for (i = 0; i < n_platforms; i++) - g_assert (NM_IS_PLATFORM (platforms[i])); + g_assert(platforms); + g_assert(n_platforms && n_platforms <= G_MAXINT32); + g_assert(netns && !*netns); + for (i = 0; i < n_platforms; i++) + g_assert(NM_IS_PLATFORM(platforms[i])); - i = nmtst_get_rand_uint32 () % (n_platforms + 1); - if (i == 0) - return; - g_assert (nm_platform_netns_push (platforms[i - 1], netns)); + i = nmtst_get_rand_uint32() % (n_platforms + 1); + if (i == 0) + return; + g_assert(nm_platform_netns_push(platforms[i - 1], netns)); } /*****************************************************************************/ @@ -2036,94 +2476,94 @@ nmtstp_netns_select_random (NMPlatform **platforms, gsize n_platforms, NMPNetns NMTST_DEFINE(); static gboolean -unshare_user (void) +unshare_user(void) { - FILE *f; - uid_t uid = geteuid (); - gid_t gid = getegid (); + FILE *f; + uid_t uid = geteuid(); + gid_t gid = getegid(); - /* Already a root? */ - if (gid == 0 && uid == 0) - return TRUE; + /* Already a root? */ + if (gid == 0 && uid == 0) + return TRUE; - /* Become a root in new user NS. */ - if (unshare (CLONE_NEWUSER) != 0) - return FALSE; + /* Become a root in new user NS. */ + if (unshare(CLONE_NEWUSER) != 0) + return FALSE; - /* Since Linux 3.19 we have to disable setgroups() in order to map users. - * Just proceed if the file is not there. */ - f = fopen ("/proc/self/setgroups", "we"); - if (f) { - fprintf (f, "deny"); - fclose (f); - } + /* Since Linux 3.19 we have to disable setgroups() in order to map users. + * Just proceed if the file is not there. */ + f = fopen("/proc/self/setgroups", "we"); + if (f) { + fprintf(f, "deny"); + fclose(f); + } - /* Map current UID to root in NS to be created. */ - f = fopen ("/proc/self/uid_map", "we"); - if (!f) - return FALSE; - fprintf (f, "0 %d 1", uid); - fclose (f); + /* Map current UID to root in NS to be created. */ + f = fopen("/proc/self/uid_map", "we"); + if (!f) + return FALSE; + fprintf(f, "0 %d 1", uid); + fclose(f); - /* Map current GID to root in NS to be created. */ - f = fopen ("/proc/self/gid_map", "we"); - if (!f) - return FALSE; - fprintf (f, "0 %d 1", gid); - fclose (f); + /* Map current GID to root in NS to be created. */ + f = fopen("/proc/self/gid_map", "we"); + if (!f) + return FALSE; + fprintf(f, "0 %d 1", gid); + fclose(f); - return TRUE; + return TRUE; } int -main (int argc, char **argv) +main(int argc, char **argv) { - int result; - const char *program = *argv; + int result; + const char *program = *argv; - _nmtstp_init_tests (&argc, &argv); + _nmtstp_init_tests(&argc, &argv); - if ( nmtstp_is_root_test () - && (geteuid () != 0 || getegid () != 0)) { - if ( g_getenv ("NMTST_FORCE_REAL_ROOT") - || !unshare_user ()) { - /* Try to exec as sudo, this function does not return, if a sudo-cmd is set. */ - nmtst_reexec_sudo (); + if (nmtstp_is_root_test() && (geteuid() != 0 || getegid() != 0)) { + if (g_getenv("NMTST_FORCE_REAL_ROOT") || !unshare_user()) { + /* Try to exec as sudo, this function does not return, if a sudo-cmd is set. */ + nmtst_reexec_sudo(); #ifdef REQUIRE_ROOT_TESTS - g_print ("Fail test: requires root privileges (%s)\n", program); - return EXIT_FAILURE; + g_print("Fail test: requires root privileges (%s)\n", program); + return EXIT_FAILURE; #else - g_print ("Skipping test: requires root privileges (%s)\n", program); - return g_test_run (); + g_print("Skipping test: requires root privileges (%s)\n", program); + return g_test_run(); #endif - } - } + } + } - if (nmtstp_is_root_test () && !g_getenv ("NMTST_NO_UNSHARE")) { - int errsv; + if (nmtstp_is_root_test() && !g_getenv("NMTST_NO_UNSHARE")) { + int errsv; - if (unshare (CLONE_NEWNET | CLONE_NEWNS) != 0) { - errsv = errno; - g_error ("unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)", nm_strerror_native (errsv), errsv); - } + if (unshare(CLONE_NEWNET | CLONE_NEWNS) != 0) { + errsv = errno; + g_error("unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)", + nm_strerror_native(errsv), + errsv); + } - /* We need a read-only /sys so that the platform knows there's no udev. */ - mount (NULL, "/sys", "sysfs", MS_SLAVE, NULL); - if (mount ("sys", "/sys", "sysfs", MS_RDONLY, NULL) != 0) { - errsv = errno; - g_error ("mount(\"/sys\") failed with %s (%d)", nm_strerror_native (errsv), errsv); - } - } + /* We need a read-only /sys so that the platform knows there's no udev. */ + mount(NULL, "/sys", "sysfs", MS_SLAVE, NULL); + if (mount("sys", "/sys", "sysfs", MS_RDONLY, NULL) != 0) { + errsv = errno; + g_error("mount(\"/sys\") failed with %s (%d)", nm_strerror_native(errsv), errsv); + } + } - nmtstp_setup_platform (); + nmtstp_setup_platform(); - _nmtstp_setup_tests (); + _nmtstp_setup_tests(); - result = g_test_run (); + result = g_test_run(); - nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); + nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); - g_object_unref (NM_PLATFORM_GET); - return result; + g_object_unref(NM_PLATFORM_GET); + return result; } diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 522c3756..1d996f46 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 - 2017 Red Hat, Inc. */ @@ -22,359 +22,476 @@ /*****************************************************************************/ -#define _NMLOG_PREFIX_NAME "platform-test" -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, __VA_ARGS__) - -#define _LOG(level, domain, ...) \ - G_STMT_START { \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ - \ - if (nm_logging_enabled (__level, __domain)) { \ - gint64 _ts = nm_utils_get_monotonic_timestamp_nsec (); \ - \ - _nm_log (__level, __domain, 0, NULL, NULL, \ - "%s[%ld.%09ld]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - (long) (_ts / NM_UTILS_NSEC_PER_SEC), \ - (long) (_ts % NM_UTILS_NSEC_PER_SEC) \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END +#define _NMLOG_PREFIX_NAME "platform-test" +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, __VA_ARGS__) + +#define _LOG(level, domain, ...) \ + G_STMT_START \ + { \ + const NMLogLevel __level = (level); \ + const NMLogDomain __domain = (domain); \ + \ + if (nm_logging_enabled(__level, __domain)) { \ + gint64 _ts = nm_utils_get_monotonic_timestamp_nsec(); \ + \ + _nm_log(__level, \ + __domain, \ + 0, \ + NULL, \ + NULL, \ + "%s[%ld.%09ld]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (long) (_ts / NM_UTILS_NSEC_PER_SEC), \ + (long) (_ts % NM_UTILS_NSEC_PER_SEC) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END /*****************************************************************************/ -gboolean nmtstp_is_root_test (void); -gboolean nmtstp_is_sysfs_writable (void); +gboolean nmtstp_is_root_test(void); +gboolean nmtstp_is_sysfs_writable(void); /*****************************************************************************/ typedef struct _NMTstpNamespaceHandle NMTstpNamespaceHandle; -NMTstpNamespaceHandle *nmtstp_namespace_create (int flags, GError **error); +NMTstpNamespaceHandle *nmtstp_namespace_create(int flags, GError **error); -void nmtstp_namespace_handle_release (NMTstpNamespaceHandle *handle); -pid_t nmtstp_namespace_handle_get_pid (NMTstpNamespaceHandle *handle); +void nmtstp_namespace_handle_release(NMTstpNamespaceHandle *handle); +pid_t nmtstp_namespace_handle_get_pid(NMTstpNamespaceHandle *handle); -int nmtstp_namespace_get_fd_for_process (pid_t pid, const char *ns_name); +int nmtstp_namespace_get_fd_for_process(pid_t pid, const char *ns_name); /*****************************************************************************/ -void nmtstp_netns_select_random (NMPlatform **platforms, gsize n_platforms, NMPNetns **netns); +void nmtstp_netns_select_random(NMPlatform **platforms, gsize n_platforms, NMPNetns **netns); /*****************************************************************************/ typedef struct { - gulong handler_id; - const char *name; - NMPlatformSignalChangeType change_type; - int received_count; - GMainLoop *loop; - int ifindex; - const char *ifname; + gulong handler_id; + const char * name; + NMPlatformSignalChangeType change_type; + int received_count; + GMainLoop * loop; + int ifindex; + const char * ifname; } SignalData; -SignalData *add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname); -#define add_signal(name, change_type, callback) add_signal_full (name, change_type, (GCallback) callback, 0, NULL) -#define add_signal_ifindex(name, change_type, callback, ifindex) add_signal_full (name, change_type, (GCallback) callback, ifindex, NULL) -#define add_signal_ifname(name, change_type, callback, ifname) add_signal_full (name, change_type, (GCallback) callback, 0, ifname) -void _accept_signal (const char *file, int line, const char *func, SignalData *data); -void _accept_signals (const char *file, int line, const char *func, SignalData *data, int min, int max); -void _wait_signal (const char *file, int line, const char *func, SignalData *data); -void _accept_or_wait_signal (const char *file, int line, const char *func, SignalData *data); -void _ensure_no_signal (const char *file, int line, const char *func, SignalData *data); -void _free_signal (const char *file, int line, const char *func, SignalData *data); +SignalData *add_signal_full(const char * name, + NMPlatformSignalChangeType change_type, + GCallback callback, + int ifindex, + const char * ifname); +#define add_signal(name, change_type, callback) \ + add_signal_full(name, change_type, (GCallback) callback, 0, NULL) +#define add_signal_ifindex(name, change_type, callback, ifindex) \ + add_signal_full(name, change_type, (GCallback) callback, ifindex, NULL) +#define add_signal_ifname(name, change_type, callback, ifname) \ + add_signal_full(name, change_type, (GCallback) callback, 0, ifname) +void _accept_signal(const char *file, int line, const char *func, SignalData *data); +void +_accept_signals(const char *file, int line, const char *func, SignalData *data, int min, int max); +void _wait_signal(const char *file, int line, const char *func, SignalData *data); +void _accept_or_wait_signal(const char *file, int line, const char *func, SignalData *data); +void _ensure_no_signal(const char *file, int line, const char *func, SignalData *data); +void _free_signal(const char *file, int line, const char *func, SignalData *data); #define accept_signal(data) _accept_signal(__FILE__, __LINE__, G_STRFUNC, data) -#define accept_signals(data, min, max) _accept_signals(__FILE__, __LINE__, G_STRFUNC, data, min, max) -#define wait_signal(data) _wait_signal(__FILE__, __LINE__, G_STRFUNC, data) +#define accept_signals(data, min, max) \ + _accept_signals(__FILE__, __LINE__, G_STRFUNC, data, min, max) +#define wait_signal(data) _wait_signal(__FILE__, __LINE__, G_STRFUNC, data) #define accept_or_wait_signal(data) _accept_or_wait_signal(__FILE__, __LINE__, G_STRFUNC, data) -#define ensure_no_signal(data) _ensure_no_signal(__FILE__, __LINE__, G_STRFUNC, data) -#define free_signal(data) _free_signal(__FILE__, __LINE__, G_STRFUNC, data) +#define ensure_no_signal(data) _ensure_no_signal(__FILE__, __LINE__, G_STRFUNC, data) +#define free_signal(data) _free_signal(__FILE__, __LINE__, G_STRFUNC, data) -void link_callback (NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink *received, int change_type_i, SignalData *data); +void link_callback(NMPlatform * platform, + int obj_type_i, + int ifindex, + NMPlatformLink *received, + int change_type_i, + SignalData * data); /*****************************************************************************/ -int nmtstp_run_command (const char *format, ...) _nm_printf (1, 2); -#define nmtstp_run_command_check(...) do { g_assert_cmpint (nmtstp_run_command (__VA_ARGS__), ==, 0); } while (0) +int nmtstp_run_command(const char *format, ...) _nm_printf(1, 2); +#define nmtstp_run_command_check(...) \ + do { \ + g_assert_cmpint(nmtstp_run_command(__VA_ARGS__), ==, 0); \ + } while (0) /*****************************************************************************/ -guint nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_msec); -guint nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms); -const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_msec); -const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms); - -#define nmtstp_assert_wait_for_signal(platform, timeout_msec) \ - G_STMT_START { \ - if (nmtstp_wait_for_signal (platform, timeout_msec) == 0) \ - g_assert_not_reached (); \ - } G_STMT_END - -#define nmtstp_assert_wait_for_signal_until(platform, until_ms) \ - G_STMT_START { \ - if (nmtstp_wait_for_signal_until (platform, until_ms) == 0) \ - g_assert_not_reached (); \ - } G_STMT_END +guint nmtstp_wait_for_signal(NMPlatform *platform, gint64 timeout_msec); +guint nmtstp_wait_for_signal_until(NMPlatform *platform, gint64 until_ms); +const NMPlatformLink *nmtstp_wait_for_link(NMPlatform *platform, + const char *ifname, + NMLinkType expected_link_type, + gint64 timeout_msec); +const NMPlatformLink *nmtstp_wait_for_link_until(NMPlatform *platform, + const char *ifname, + NMLinkType expected_link_type, + gint64 until_ms); + +#define nmtstp_assert_wait_for_signal(platform, timeout_msec) \ + G_STMT_START \ + { \ + if (nmtstp_wait_for_signal(platform, timeout_msec) == 0) \ + g_assert_not_reached(); \ + } \ + G_STMT_END + +#define nmtstp_assert_wait_for_signal_until(platform, until_ms) \ + G_STMT_START \ + { \ + if (nmtstp_wait_for_signal_until(platform, until_ms) == 0) \ + g_assert_not_reached(); \ + } \ + G_STMT_END #define nmtstp_assert_wait_for_link(platform, ifname, expected_link_type, timeout_msec) \ - nmtst_assert_nonnull (nmtstp_wait_for_link (platform, ifname, expected_link_type, timeout_msec)) + nmtst_assert_nonnull(nmtstp_wait_for_link(platform, ifname, expected_link_type, timeout_msec)) #define nmtstp_assert_wait_for_link_until(platform, ifname, expected_link_type, until_ms) \ - nmtst_assert_nonnull (nmtstp_wait_for_link_until (platform, ifname, expected_link_type, until_ms)) + nmtst_assert_nonnull(nmtstp_wait_for_link_until(platform, ifname, expected_link_type, until_ms)) /*****************************************************************************/ -int nmtstp_run_command_check_external_global (void); -gboolean nmtstp_run_command_check_external (int external_command); +int nmtstp_run_command_check_external_global(void); +gboolean nmtstp_run_command_check_external(int external_command); /*****************************************************************************/ -const NMPlatformIP4Route *_nmtstp_assert_ip4_route_exists (const char *file, - guint line, - const char *func, - NMPlatform *platform, - int c_exists, - const char *ifname, - guint32 network, - int plen, - guint32 metric, - guint8 tos); -#define nmtstp_assert_ip4_route_exists(platform, c_exists, ifname, network, plen, metric, tos) _nmtstp_assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, c_exists, ifname, network, plen, metric, tos) - -const NMPlatformIP4Route *nmtstp_ip4_route_get (NMPlatform *platform, - int ifindex, - guint32 network, - int plen, - guint32 metric, - guint8 tos); - -const NMPlatformIP6Route *_nmtstp_assert_ip6_route_exists (const char *file, - guint line, - const char *func, - NMPlatform *platform, - int c_exists, - const char *ifname, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen); -#define nmtstp_assert_ip6_route_exists(platform, c_exists, ifname, network, plen, metric, src, src_plen) _nmtstp_assert_ip6_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, c_exists, ifname, network, plen, metric, src, src_plen) - -const NMPlatformIP6Route *nmtstp_ip6_route_get (NMPlatform *platform, - int ifindex, - const struct in6_addr *network, - guint plen, - guint32 metric, - const struct in6_addr *src, - guint8 src_plen); +const NMPlatformIP4Route *_nmtstp_assert_ip4_route_exists(const char *file, + guint line, + const char *func, + NMPlatform *platform, + int c_exists, + const char *ifname, + guint32 network, + int plen, + guint32 metric, + guint8 tos); +#define nmtstp_assert_ip4_route_exists(platform, c_exists, ifname, network, plen, metric, tos) \ + _nmtstp_assert_ip4_route_exists(__FILE__, \ + __LINE__, \ + G_STRFUNC, \ + platform, \ + c_exists, \ + ifname, \ + network, \ + plen, \ + metric, \ + tos) + +const NMPlatformIP4Route *nmtstp_ip4_route_get(NMPlatform *platform, + int ifindex, + guint32 network, + int plen, + guint32 metric, + guint8 tos); + +const NMPlatformIP6Route *_nmtstp_assert_ip6_route_exists(const char * file, + guint line, + const char * func, + NMPlatform * platform, + int c_exists, + const char * ifname, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen); +#define nmtstp_assert_ip6_route_exists(platform, \ + c_exists, \ + ifname, \ + network, \ + plen, \ + metric, \ + src, \ + src_plen) \ + _nmtstp_assert_ip6_route_exists(__FILE__, \ + __LINE__, \ + G_STRFUNC, \ + platform, \ + c_exists, \ + ifname, \ + network, \ + plen, \ + metric, \ + src, \ + src_plen) + +const NMPlatformIP6Route *nmtstp_ip6_route_get(NMPlatform * platform, + int ifindex, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen); /*****************************************************************************/ -gboolean nmtstp_ip_address_check_lifetime (const NMPlatformIPAddress *addr, - gint64 now, - guint32 expected_lifetime, - guint32 expected_preferred); -void nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr, - gint64 now, - guint32 expected_lifetime, - guint32 expected_preferred); - -void nmtstp_ip4_address_add (NMPlatform *platform, - gboolean external_command, - int ifindex, - in_addr_t address, - int plen, - in_addr_t peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags, - const char *label); -void nmtstp_ip6_address_add (NMPlatform *platform, - gboolean external_command, - int ifindex, - struct in6_addr address, - int plen, - struct in6_addr peer_address, - guint32 lifetime, - guint32 preferred, - guint32 flags); -void nmtstp_ip4_address_del (NMPlatform *platform, - gboolean external_command, - int ifindex, - in_addr_t address, - int plen, - in_addr_t peer_address); -void nmtstp_ip6_address_del (NMPlatform *platform, - gboolean external_command, - int ifindex, - struct in6_addr address, - int plen); - -void nmtstp_ip4_route_add (NMPlatform *platform, - int ifindex, - NMIPConfigSource source, - in_addr_t network, - guint8 plen, - in_addr_t gateway, - in_addr_t pref_src, - guint32 metric, - guint32 mss); - -void nmtstp_ip6_route_add (NMPlatform *platform, - int ifindex, - NMIPConfigSource source, - struct in6_addr network, - guint8 plen, - struct in6_addr gateway, - struct in6_addr pref_src, - guint32 metric, - guint32 mss); +gboolean nmtstp_ip_address_check_lifetime(const NMPlatformIPAddress *addr, + gint64 now, + guint32 expected_lifetime, + guint32 expected_preferred); +void nmtstp_ip_address_assert_lifetime(const NMPlatformIPAddress *addr, + gint64 now, + guint32 expected_lifetime, + guint32 expected_preferred); + +void nmtstp_ip4_address_add(NMPlatform *platform, + gboolean external_command, + int ifindex, + in_addr_t address, + int plen, + in_addr_t peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags, + const char *label); +void nmtstp_ip6_address_add(NMPlatform * platform, + gboolean external_command, + int ifindex, + struct in6_addr address, + int plen, + struct in6_addr peer_address, + guint32 lifetime, + guint32 preferred, + guint32 flags); +void nmtstp_ip4_address_del(NMPlatform *platform, + gboolean external_command, + int ifindex, + in_addr_t address, + int plen, + in_addr_t peer_address); +void nmtstp_ip6_address_del(NMPlatform * platform, + gboolean external_command, + int ifindex, + struct in6_addr address, + int plen); + +void nmtstp_ip4_route_add(NMPlatform * platform, + int ifindex, + NMIPConfigSource source, + in_addr_t network, + guint8 plen, + in_addr_t gateway, + in_addr_t pref_src, + guint32 metric, + guint32 mss); + +void nmtstp_ip6_route_add(NMPlatform * platform, + int ifindex, + NMIPConfigSource source, + struct in6_addr network, + guint8 plen, + struct in6_addr gateway, + struct in6_addr pref_src, + guint32 metric, + guint32 mss); static inline GPtrArray * -nmtstp_ip4_route_get_all (NMPlatform *platform, - int ifindex) +nmtstp_ip4_route_get_all(NMPlatform *platform, int ifindex) { - return nm_platform_lookup_object_clone (platform, - NMP_OBJECT_TYPE_IP4_ROUTE, - ifindex, - nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel, - NULL); + return nm_platform_lookup_object_clone( + platform, + NMP_OBJECT_TYPE_IP4_ROUTE, + ifindex, + nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel, + NULL); } static inline GPtrArray * -nmtstp_ip6_route_get_all (NMPlatform *platform, - int ifindex) +nmtstp_ip6_route_get_all(NMPlatform *platform, int ifindex) { - return nm_platform_lookup_object_clone (platform, - NMP_OBJECT_TYPE_IP6_ROUTE, - ifindex, - nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel, - NULL); + return nm_platform_lookup_object_clone( + platform, + NMP_OBJECT_TYPE_IP6_ROUTE, + ifindex, + nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel, + NULL); } /*****************************************************************************/ -GArray *nmtstp_platform_ip4_address_get_all (NMPlatform *self, int ifindex); -GArray *nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex); +GArray *nmtstp_platform_ip4_address_get_all(NMPlatform *self, int ifindex); +GArray *nmtstp_platform_ip6_address_get_all(NMPlatform *self, int ifindex); + +/*****************************************************************************/ + +const NMPlatformIPAddress * +nmtstp_platform_ip_address_find(NMPlatform *self, int ifindex, int addr_family, gconstpointer addr); + +static inline const NMPlatformIP4Address * +nmtstp_platform_ip4_address_find(NMPlatform *self, int ifindex, in_addr_t addr) +{ + return (const NMPlatformIP4Address *) + nmtstp_platform_ip_address_find(self, ifindex, AF_INET, &addr); +} + +static inline const NMPlatformIP6Address * +nmtstp_platform_ip6_address_find(NMPlatform *self, int ifindex, const struct in6_addr *addr) +{ + return (const NMPlatformIP6Address *) + nmtstp_platform_ip_address_find(self, ifindex, AF_INET6, addr); +} + +void _nmtstp_platform_ip_addresses_assert(const char * filename, + int lineno, + NMPlatform * self, + int ifindex, + gboolean force_exact_4, + gboolean force_exact_6, + gboolean ignore_ll6, + guint addrs_len, + const char *const *addrs); + +#define nmtstp_platform_ip_addresses_assert(self, \ + ifindex, \ + force_exact_4, \ + force_exact_6, \ + ignore_ll6, \ + ...) \ + _nmtstp_platform_ip_addresses_assert(__FILE__, \ + __LINE__, \ + (self), \ + (ifindex), \ + (force_exact_4), \ + (force_exact_6), \ + (ignore_ll6), \ + NM_NARG(__VA_ARGS__), \ + ((const char *const[]){"dummy", ##__VA_ARGS__, NULL}) \ + + 1) /*****************************************************************************/ static inline gboolean -_nmtstp_platform_routing_rules_get_all_predicate (const NMPObject *obj, - gpointer user_data) +_nmtstp_platform_routing_rules_get_all_predicate(const NMPObject *obj, gpointer user_data) { - int addr_family = GPOINTER_TO_INT (user_data); + int addr_family = GPOINTER_TO_INT(user_data); - g_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_ROUTING_RULE); + g_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_ROUTING_RULE); - return addr_family == AF_UNSPEC - || NMP_OBJECT_CAST_ROUTING_RULE (obj)->addr_family == addr_family; + return addr_family == AF_UNSPEC + || NMP_OBJECT_CAST_ROUTING_RULE(obj)->addr_family == addr_family; } static inline GPtrArray * -nmtstp_platform_routing_rules_get_all (NMPlatform *platform, int addr_family) +nmtstp_platform_routing_rules_get_all(NMPlatform *platform, int addr_family) { - NMPLookup lookup; + NMPLookup lookup; - g_assert (NM_IS_PLATFORM (platform)); - g_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6)); + g_assert(NM_IS_PLATFORM(platform)); + g_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - return nm_platform_lookup_clone (platform, - &lookup, - _nmtstp_platform_routing_rules_get_all_predicate, - GINT_TO_POINTER (addr_family)); + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); + return nm_platform_lookup_clone(platform, + &lookup, + _nmtstp_platform_routing_rules_get_all_predicate, + GINT_TO_POINTER(addr_family)); } static inline guint -nmtstp_platform_routing_rules_get_count (NMPlatform *platform, int addr_family) +nmtstp_platform_routing_rules_get_count(NMPlatform *platform, int addr_family) { - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; - const NMPObject *obj; - NMPLookup lookup; - guint n; - - g_assert (NM_IS_PLATFORM (platform)); - g_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6)); - - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - head_entry = nm_platform_lookup (platform, &lookup); - - n = 0; - nmp_cache_iter_for_each (&iter, head_entry, &obj) { - if (_nmtstp_platform_routing_rules_get_all_predicate (obj, GINT_TO_POINTER (addr_family))) - n++; - } - return n; + const NMDedupMultiHeadEntry *head_entry; + NMDedupMultiIter iter; + const NMPObject * obj; + NMPLookup lookup; + guint n; + + g_assert(NM_IS_PLATFORM(platform)); + g_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6)); + + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); + head_entry = nm_platform_lookup(platform, &lookup); + + n = 0; + nmp_cache_iter_for_each (&iter, head_entry, &obj) { + if (_nmtstp_platform_routing_rules_get_all_predicate(obj, GINT_TO_POINTER(addr_family))) + n++; + } + return n; } -gboolean nmtstp_platform_ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric); -gboolean nmtstp_platform_ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric); - -const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type); -const NMPlatformLink *nmtstp_link_get (NMPlatform *platform, int ifindex, const char *name); - -void nmtstp_link_set_updown (NMPlatform *platform, - gboolean external_command, - int ifindex, - gboolean up); - -const NMPlatformLink *nmtstp_link_veth_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const char *peer); -const NMPlatformLink *nmtstp_link_dummy_add (NMPlatform *platform, - gboolean external_command, - const char *name); -const NMPlatformLink *nmtstp_link_gre_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkGre *lnk); -const NMPlatformLink *nmtstp_link_ip6tnl_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkIp6Tnl *lnk); -const NMPlatformLink *nmtstp_link_ip6gre_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkIp6Tnl *lnk); -const NMPlatformLink *nmtstp_link_ipip_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkIpIp *lnk); -const NMPlatformLink *nmtstp_link_macvlan_add (NMPlatform *platform, - gboolean external_command, - const char *name, - int parent, - const NMPlatformLnkMacvlan *lnk); -const NMPlatformLink *nmtstp_link_sit_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkSit *lnk); -const NMPlatformLink *nmtstp_link_tun_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkTun *lnk, - int *out_fd); -const NMPlatformLink *nmtstp_link_vrf_add (NMPlatform *platform, - gboolean external_command, +gboolean nmtstp_platform_ip4_route_delete(NMPlatform *platform, + int ifindex, + in_addr_t network, + guint8 plen, + guint32 metric); +gboolean nmtstp_platform_ip6_route_delete(NMPlatform * platform, + int ifindex, + struct in6_addr network, + guint8 plen, + guint32 metric); + +const NMPlatformLink * +nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type); +const NMPlatformLink *nmtstp_link_get(NMPlatform *platform, int ifindex, const char *name); + +gboolean nmtstp_kernel_support_get(NMPlatformKernelSupportType type); + +void +nmtstp_link_set_updown(NMPlatform *platform, gboolean external_command, int ifindex, gboolean up); + +const NMPlatformLink *nmtstp_link_bridge_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkBridge *lnk); +const NMPlatformLink *nmtstp_link_veth_add(NMPlatform *platform, + gboolean external_command, const char *name, - const NMPlatformLnkVrf *lnk, - gboolean *out_not_supported); -const NMPlatformLink *nmtstp_link_vxlan_add (NMPlatform *platform, - gboolean external_command, - const char *name, - const NMPlatformLnkVxlan *lnk); - -void nmtstp_link_delete (NMPlatform *platform, - gboolean external_command, - int ifindex, - const char *name, - gboolean require_exist); + const char *peer); +const NMPlatformLink * +nmtstp_link_dummy_add(NMPlatform *platform, gboolean external_command, const char *name); +const NMPlatformLink *nmtstp_link_gre_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkGre *lnk); +const NMPlatformLink *nmtstp_link_ip6tnl_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkIp6Tnl *lnk); +const NMPlatformLink *nmtstp_link_ip6gre_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkIp6Tnl *lnk); +const NMPlatformLink *nmtstp_link_ipip_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkIpIp *lnk); +const NMPlatformLink *nmtstp_link_macvlan_add(NMPlatform * platform, + gboolean external_command, + const char * name, + int parent, + const NMPlatformLnkMacvlan *lnk); +const NMPlatformLink *nmtstp_link_sit_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkSit *lnk); +const NMPlatformLink *nmtstp_link_tun_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkTun *lnk, + int * out_fd); +const NMPlatformLink *nmtstp_link_vrf_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkVrf *lnk, + gboolean * out_not_supported); +const NMPlatformLink *nmtstp_link_vxlan_add(NMPlatform * platform, + gboolean external_command, + const char * name, + const NMPlatformLnkVxlan *lnk); + +void nmtstp_link_delete(NMPlatform *platform, + gboolean external_command, + int ifindex, + const char *name, + gboolean require_exist); /*****************************************************************************/ @@ -382,100 +499,112 @@ extern int NMTSTP_ENV1_IFINDEX; extern int NMTSTP_ENV1_EX; static inline void -_nmtstp_env1_wrapper_setup (const NmtstTestData *test_data) +_nmtstp_env1_wrapper_setup(const NmtstTestData *test_data) { - int *p_ifindex; - gpointer p_ifup; + int * p_ifindex; + gpointer p_ifup; - nmtst_test_data_unpack (test_data, &p_ifindex, NULL, NULL, NULL, &p_ifup); + nmtst_test_data_unpack(test_data, &p_ifindex, NULL, NULL, NULL, &p_ifup); - g_assert (p_ifindex && *p_ifindex == -1); + g_assert(p_ifindex && *p_ifindex == -1); - _LOGT ("TEST[%s]: setup", test_data->testpath); + _LOGT("TEST[%s]: setup", test_data->testpath); - nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); + nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL))); + g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL))); - *p_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert_cmpint (*p_ifindex, >, 0); - g_assert_cmpint (NMTSTP_ENV1_IFINDEX, ==, -1); + *p_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert_cmpint(*p_ifindex, >, 0); + g_assert_cmpint(NMTSTP_ENV1_IFINDEX, ==, -1); - if (GPOINTER_TO_INT (p_ifup)) - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, *p_ifindex, NULL)); + if (GPOINTER_TO_INT(p_ifup)) + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, *p_ifindex, NULL)); - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events(NM_PLATFORM_GET); - NMTSTP_ENV1_IFINDEX = *p_ifindex; - NMTSTP_ENV1_EX = nmtstp_run_command_check_external_global (); + NMTSTP_ENV1_IFINDEX = *p_ifindex; + NMTSTP_ENV1_EX = nmtstp_run_command_check_external_global(); } static inline void -_nmtstp_env1_wrapper_run (gconstpointer user_data) +_nmtstp_env1_wrapper_run(gconstpointer user_data) { - const NmtstTestData *test_data = user_data; - GTestDataFunc test_func_data; - GTestFunc test_func; - gconstpointer d; - - nmtst_test_data_unpack (test_data, NULL, &test_func, &test_func_data, &d, NULL); - - _LOGT ("TEST[%s]: run", test_data->testpath); - if (test_func) - test_func (); - else - test_func_data (d); + const NmtstTestData *test_data = user_data; + GTestDataFunc test_func_data; + GTestFunc test_func; + gconstpointer d; + + nmtst_test_data_unpack(test_data, NULL, &test_func, &test_func_data, &d, NULL); + + _LOGT("TEST[%s]: run", test_data->testpath); + if (test_func) + test_func(); + else + test_func_data(d); } static inline void -_nmtstp_env1_wrapper_teardown (const NmtstTestData *test_data) +_nmtstp_env1_wrapper_teardown(const NmtstTestData *test_data) { - int *p_ifindex; + int *p_ifindex; - nmtst_test_data_unpack (test_data, &p_ifindex, NULL, NULL, NULL, NULL); + nmtst_test_data_unpack(test_data, &p_ifindex, NULL, NULL, NULL, NULL); - g_assert_cmpint (NMTSTP_ENV1_IFINDEX, ==, *p_ifindex); - NMTSTP_ENV1_IFINDEX = -1; + g_assert_cmpint(NMTSTP_ENV1_IFINDEX, ==, *p_ifindex); + NMTSTP_ENV1_IFINDEX = -1; - _LOGT ("TEST[%s]: teardown", test_data->testpath); + _LOGT("TEST[%s]: teardown", test_data->testpath); - g_assert_cmpint (*p_ifindex, ==, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert (nm_platform_link_delete (NM_PLATFORM_GET, *p_ifindex)); + g_assert_cmpint(*p_ifindex, ==, nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME)); + g_assert(nm_platform_link_delete(NM_PLATFORM_GET, *p_ifindex)); - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events(NM_PLATFORM_GET); - _LOGT ("TEST[%s]: finished", test_data->testpath); + _LOGT("TEST[%s]: finished", test_data->testpath); - *p_ifindex = -1; + *p_ifindex = -1; } /* add test function, that set's up a particular environment, consisting * of a dummy device with ifindex NMTSTP_ENV1_IFINDEX. */ #define _nmtstp_env1_add_test_func_full(testpath, test_func, test_data_func, arg, ifup) \ - nmtst_add_test_func_full (testpath, \ - _nmtstp_env1_wrapper_run, \ - _nmtstp_env1_wrapper_setup, \ - _nmtstp_env1_wrapper_teardown, \ - ({ static int _ifindex = -1; &_ifindex; }), \ - ({ GTestFunc _test_func = (test_func); _test_func; }), \ - ({ GTestDataFunc _test_func = (test_data_func); _test_func; }), \ - (arg), \ - ({ gboolean _ifup = (ifup); GINT_TO_POINTER (_ifup);})) + nmtst_add_test_func_full(testpath, \ + _nmtstp_env1_wrapper_run, \ + _nmtstp_env1_wrapper_setup, \ + _nmtstp_env1_wrapper_teardown, \ + ({ \ + static int _ifindex = -1; \ + &_ifindex; \ + }), \ + ({ \ + GTestFunc _test_func = (test_func); \ + _test_func; \ + }), \ + ({ \ + GTestDataFunc _test_func = (test_data_func); \ + _test_func; \ + }), \ + (arg), \ + ({ \ + gboolean _ifup = (ifup); \ + GINT_TO_POINTER(_ifup); \ + })) #define nmtstp_env1_add_test_func_data(testpath, test_func, arg, ifup) \ - _nmtstp_env1_add_test_func_full(testpath, NULL, test_func, arg, ifup) + _nmtstp_env1_add_test_func_full(testpath, NULL, test_func, arg, ifup) #define nmtstp_env1_add_test_func(testpath, test_func, ifup) \ - _nmtstp_env1_add_test_func_full(testpath, test_func, NULL, NULL, ifup) + _nmtstp_env1_add_test_func_full(testpath, test_func, NULL, NULL, ifup) /*****************************************************************************/ -typedef void (*NMTstpSetupFunc) (void); +typedef void (*NMTstpSetupFunc)(void); extern NMTstpSetupFunc const _nmtstp_setup_platform_func; -void nmtstp_setup_platform (void); +void nmtstp_setup_platform(void); /*****************************************************************************/ -void _nmtstp_init_tests (int *argc, char ***argv); -void _nmtstp_setup_tests (void); +void _nmtstp_init_tests(int *argc, char ***argv); +void _nmtstp_setup_tests(void); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index d7285c83..829abcc9 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 Red Hat, Inc. */ @@ -19,3305 +19,3699 @@ #include "test-common.h" #include "nm-test-utils-core.h" -#define LO_INDEX 1 -#define LO_NAME "lo" +#define LO_INDEX 1 +#define LO_NAME "lo" #define LO_TYPEDESC "loopback" #define DUMMY_TYPEDESC "dummy" -#define BOGUS_NAME "nm-bogus-device" -#define BOGUS_IFINDEX INT_MAX -#define SLAVE_NAME "nm-test-slave" -#define PARENT_NAME "nm-test-parent" -#define VLAN_ID 4077 -#define VLAN_FLAGS 0 -#define MTU 1357 +#define BOGUS_NAME "nm-bogus-device" +#define BOGUS_IFINDEX INT_MAX +#define SLAVE_NAME "nm-test-slave" +#define PARENT_NAME "nm-test-parent" +#define VLAN_ID 4077 +#define VLAN_FLAGS 0 +#define MTU 1357 #define _ADD_DUMMY(platform, name) \ - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_dummy_add ((platform), (name), NULL))) + g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add((platform), (name), NULL))) static void test_bogus(void) { - size_t addrlen; + size_t addrlen; - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, BOGUS_NAME)); - g_assert (!nm_platform_link_delete (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_get_ifindex (NM_PLATFORM_GET, BOGUS_NAME)); - g_assert (!nm_platform_link_get_name (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_get_type (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_get_type_name (NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, BOGUS_NAME)); + g_assert(!nm_platform_link_delete(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_get_ifindex(NM_PLATFORM_GET, BOGUS_NAME)); + g_assert(!nm_platform_link_get_name(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_get_type(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_get_type_name(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_set_up (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); + g_assert(!nm_platform_link_set_up(NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); - g_assert (!nm_platform_link_set_down (NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_set_down(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_set_arp (NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_set_arp(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_set_noarp (NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_set_noarp(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_get_address (NM_PLATFORM_GET, BOGUS_IFINDEX, &addrlen)); - g_assert (!addrlen); - g_assert (!nm_platform_link_get_address (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); + g_assert(!nm_platform_link_get_address(NM_PLATFORM_GET, BOGUS_IFINDEX, &addrlen)); + g_assert(!addrlen); + g_assert(!nm_platform_link_get_address(NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); - g_assert (!NMTST_NM_ERR_SUCCESS (nm_platform_link_set_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX, MTU))); + g_assert(!NMTST_NM_ERR_SUCCESS(nm_platform_link_set_mtu(NM_PLATFORM_GET, BOGUS_IFINDEX, MTU))); - g_assert (!nm_platform_link_get_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_get_mtu(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_supports_vlans (NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_supports_carrier_detect(NM_PLATFORM_GET, BOGUS_IFINDEX)); + g_assert(!nm_platform_link_supports_vlans(NM_PLATFORM_GET, BOGUS_IFINDEX)); - g_assert (!nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); - g_assert (!nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0)); - g_assert (!nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0)); + g_assert(!nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); + g_assert(!nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0)); + g_assert(!nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0)); } static void -test_loopback (void) +test_loopback(void) { - g_assert (nm_platform_link_get_by_ifname (NM_PLATFORM_GET, LO_NAME)); - g_assert_cmpint (nm_platform_link_get_type (NM_PLATFORM_GET, LO_INDEX), ==, NM_LINK_TYPE_LOOPBACK); - g_assert_cmpint (nm_platform_link_get_ifindex (NM_PLATFORM_GET, LO_NAME), ==, LO_INDEX); - g_assert_cmpstr (nm_platform_link_get_name (NM_PLATFORM_GET, LO_INDEX), ==, LO_NAME); - g_assert_cmpstr (nm_platform_link_get_type_name (NM_PLATFORM_GET, LO_INDEX), ==, LO_TYPEDESC); - - g_assert (nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, LO_INDEX)); - g_assert (!nm_platform_link_supports_vlans (NM_PLATFORM_GET, LO_INDEX)); + g_assert(nm_platform_link_get_by_ifname(NM_PLATFORM_GET, LO_NAME)); + g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, LO_INDEX), + ==, + NM_LINK_TYPE_LOOPBACK); + g_assert_cmpint(nm_platform_link_get_ifindex(NM_PLATFORM_GET, LO_NAME), ==, LO_INDEX); + g_assert_cmpstr(nm_platform_link_get_name(NM_PLATFORM_GET, LO_INDEX), ==, LO_NAME); + g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, LO_INDEX), ==, LO_TYPEDESC); + + g_assert(nm_platform_link_supports_carrier_detect(NM_PLATFORM_GET, LO_INDEX)); + g_assert(!nm_platform_link_supports_vlans(NM_PLATFORM_GET, LO_INDEX)); } static gboolean -software_add (NMLinkType link_type, const char *name) +software_add(NMLinkType link_type, const char *name) { - switch (link_type) { - case NM_LINK_TYPE_DUMMY: - return NMTST_NM_ERR_SUCCESS (nm_platform_link_dummy_add (NM_PLATFORM_GET, name, NULL)); - case NM_LINK_TYPE_BRIDGE: - return NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, name, NULL, 0, NULL)); - case NM_LINK_TYPE_BOND: - { - gboolean bond0_exists = !!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "bond0"); - int r; - - r = nm_platform_link_bond_add (NM_PLATFORM_GET, name, NULL); - - /* Check that bond0 is *not* automatically created. */ - if (!bond0_exists) - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "bond0")); - return r >= 0; - } - case NM_LINK_TYPE_TEAM: - return NMTST_NM_ERR_SUCCESS (nm_platform_link_team_add (NM_PLATFORM_GET, name, NULL)); - case NM_LINK_TYPE_VLAN: { - SignalData *parent_added; - SignalData *parent_changed; - - /* Don't call link_callback for the bridge interface */ - parent_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, PARENT_NAME); - if (NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, PARENT_NAME, NULL, 0, NULL))) - accept_signal (parent_added); - free_signal (parent_added); - - { - int parent_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME); - gboolean was_up = nm_platform_link_is_up (NM_PLATFORM_GET, parent_ifindex); - - parent_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, parent_ifindex); - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, parent_ifindex, NULL)); - if (was_up) { - /* when NM is running in the background, it will mess with addrgenmode which might cause additional signals. */ - accept_signals (parent_changed, 0, 1); - } else - accept_signals (parent_changed, 1, 2); - free_signal (parent_changed); - - return NMTST_NM_ERR_SUCCESS (nm_platform_link_vlan_add (NM_PLATFORM_GET, name, parent_ifindex, VLAN_ID, 0, NULL)); - } - } - default: - g_error ("Link type %d unhandled.", link_type); - } - g_assert_not_reached (); + switch (link_type) { + case NM_LINK_TYPE_DUMMY: + return NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, name, NULL)); + case NM_LINK_TYPE_BRIDGE: + return NMTST_NM_ERR_SUCCESS(nm_platform_link_bridge_add(NM_PLATFORM_GET, + name, + NULL, + 0, + &nm_platform_lnk_bridge_default, + NULL)); + case NM_LINK_TYPE_BOND: + { + gboolean bond0_exists = !!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "bond0"); + int r; + + r = nm_platform_link_bond_add(NM_PLATFORM_GET, name, NULL); + + /* Check that bond0 is *not* automatically created. */ + if (!bond0_exists) + g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "bond0")); + return r >= 0; + } + case NM_LINK_TYPE_TEAM: + return NMTST_NM_ERR_SUCCESS(nm_platform_link_team_add(NM_PLATFORM_GET, name, NULL)); + case NM_LINK_TYPE_VLAN: + { + SignalData *parent_added; + SignalData *parent_changed; + + /* Don't call link_callback for the bridge interface */ + parent_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + link_callback, + PARENT_NAME); + if (NMTST_NM_ERR_SUCCESS(nm_platform_link_bridge_add(NM_PLATFORM_GET, + PARENT_NAME, + NULL, + 0, + &nm_platform_lnk_bridge_default, + NULL))) + accept_signal(parent_added); + free_signal(parent_added); + + { + int parent_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME); + gboolean was_up = nm_platform_link_is_up(NM_PLATFORM_GET, parent_ifindex); + + parent_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + link_callback, + parent_ifindex); + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, parent_ifindex, NULL)); + if (was_up) { + /* when NM is running in the background, it will mess with addrgenmode which might cause additional signals. */ + accept_signals(parent_changed, 0, 1); + } else + accept_signals(parent_changed, 1, 2); + free_signal(parent_changed); + + return NMTST_NM_ERR_SUCCESS( + nm_platform_link_vlan_add(NM_PLATFORM_GET, name, parent_ifindex, VLAN_ID, 0, NULL)); + } + } + default: + g_error("Link type %d unhandled.", link_type); + } + g_assert_not_reached(); } static void -test_link_changed_signal_cb (NMPlatform *platform, - int obj_type_i, - int ifindex, - const NMPlatformIP4Route *route, - int change_type_i, - gboolean *p_test_link_changed_signal_arg) +test_link_changed_signal_cb(NMPlatform * platform, + int obj_type_i, + int ifindex, + const NMPlatformIP4Route *route, + int change_type_i, + gboolean * p_test_link_changed_signal_arg) { - const NMPObjectType obj_type = obj_type_i; - const NMPlatformSignalChangeType change_type = change_type_i; - - /* test invocation of platform signals with multiple listeners - * connected to the signal. Platform signals have enum-typed - * arguments and there seem to be an issue with invoking such - * signals on s390x and ppc64 archs. - * https://bugzilla.redhat.com/show_bug.cgi?id=1260577 - * - * As the test shows, the failure is not reproducible for - * platform signals. - */ - g_assert (NM_IS_PLATFORM (platform)); - g_assert (platform == NM_PLATFORM_GET); - - g_assert (ifindex > 0); - g_assert (route); - - g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_LINK); - - g_assert_cmpint ((gint64) change_type, !=, (gint64) 0); - g_assert_cmpint (change_type, !=, NM_PLATFORM_SIGNAL_NONE); - - *p_test_link_changed_signal_arg = TRUE; + const NMPObjectType obj_type = obj_type_i; + const NMPlatformSignalChangeType change_type = change_type_i; + + /* test invocation of platform signals with multiple listeners + * connected to the signal. Platform signals have enum-typed + * arguments and there seem to be an issue with invoking such + * signals on s390x and ppc64 archs. + * https://bugzilla.redhat.com/show_bug.cgi?id=1260577 + * + * As the test shows, the failure is not reproducible for + * platform signals. + */ + g_assert(NM_IS_PLATFORM(platform)); + g_assert(platform == NM_PLATFORM_GET); + + g_assert(ifindex > 0); + g_assert(route); + + g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_LINK); + + g_assert_cmpint((gint64) change_type, !=, (gint64) 0); + g_assert_cmpint(change_type, !=, NM_PLATFORM_SIGNAL_NONE); + + *p_test_link_changed_signal_arg = TRUE; } static void -test_slave (int master, int type, SignalData *master_changed) +test_slave(int master, int type, SignalData *master_changed) { - int ifindex; - SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, SLAVE_NAME); - SignalData *link_changed, *link_removed; - char *value; - NMLinkType link_type = nm_platform_link_get_type (NM_PLATFORM_GET, master); - gboolean test_link_changed_signal_arg1; - gboolean test_link_changed_signal_arg2; - - g_assert (NM_IN_SET (link_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE)); - - g_assert (software_add (type, SLAVE_NAME)); - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, SLAVE_NAME); - g_assert (ifindex > 0); - link_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, ifindex); - link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex); - accept_signal (link_added); - - /* Set the slave up to see whether master's IFF_LOWER_UP is set correctly. - * - * See https://bugzilla.redhat.com/show_bug.cgi?id=910348 - */ - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - ensure_no_signal (link_changed); - - /* Enslave */ - link_changed->ifindex = ifindex; - g_assert (nm_platform_link_enslave (NM_PLATFORM_GET, master, ifindex)); - g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, master); - - accept_signals (link_changed, 1, 3); - accept_signals (master_changed, 0, 2); - - /* enslaveing brings put the slave */ - if (NM_IN_SET (link_type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) - g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - else - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - - test_link_changed_signal_arg1 = FALSE; - test_link_changed_signal_arg2 = FALSE; - g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg1); - g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg2); - - /* Set master up */ - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, master, NULL)); - g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, master)); - accept_signals (master_changed, 1, 3); - - g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg1); - g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg2); - g_assert (test_link_changed_signal_arg1); - g_assert (test_link_changed_signal_arg2); - - /* Master with a disconnected slave is disconnected - * - * For some reason, bonding and teaming slaves are automatically set up. We - * need to set them back down for this test. - */ - switch (nm_platform_link_get_type (NM_PLATFORM_GET, master)) { - case NM_LINK_TYPE_BOND: - case NM_LINK_TYPE_TEAM: - g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex)); - accept_signal (link_changed); - accept_signals (master_changed, 0, 3); - break; - default: - break; - } - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - if ( nmtstp_is_root_test () - && nm_platform_link_is_connected (NM_PLATFORM_GET, master)) { - if (nm_platform_link_get_type (NM_PLATFORM_GET, master) == NM_LINK_TYPE_TEAM) { - /* Older team versions (e.g. Fedora 17) have a bug that team master stays - * IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if - * `ip link` also claims master to be up, accept it. */ - char *stdout_str = NULL; - - nmtst_spawn_sync (NULL, &stdout_str, NULL, 0, "/sbin/ip", "link", "show", "dev", nm_platform_link_get_name (NM_PLATFORM_GET, master)); - - g_assert (strstr (stdout_str, "LOWER_UP")); - g_free (stdout_str); - } else - g_assert_not_reached (); - } - - /* Set slave up and see if master gets up too */ - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL)); - g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, master)); - accept_signals (link_changed, 1, 3); - /* NM running, can cause additional change of addrgenmode */ - accept_signals (master_changed, 0, 3); - - /* Enslave again - * - * Gracefully succeed if already enslaved. - */ - ensure_no_signal (link_changed); - g_assert (nm_platform_link_enslave (NM_PLATFORM_GET, master, ifindex)); - accept_signals (link_changed, 0, 2); - accept_signals (master_changed, 0, 2); - - /* Set slave option */ - switch (type) { - case NM_LINK_TYPE_BRIDGE: - if (nmtstp_is_sysfs_writable ()) { - g_assert (nm_platform_sysctl_slave_set_option (NM_PLATFORM_GET, ifindex, "priority", "614")); - value = nm_platform_sysctl_slave_get_option (NM_PLATFORM_GET, ifindex, "priority"); - g_assert_cmpstr (value, ==, "614"); - g_free (value); - } - break; - default: - break; - } - - /* Release */ - ensure_no_signal (link_added); - ensure_no_signal (link_changed); - ensure_no_signal (link_removed); - g_assert (nm_platform_link_release (NM_PLATFORM_GET, master, ifindex)); - g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, 0); - if (link_changed->received_count > 0) { - accept_signals (link_added, 0, 1); - accept_signals (link_changed, 1, 5); - accept_signals (link_removed, 0, 1); - } else { - /* Due to https://bugzilla.redhat.com/show_bug.cgi?id=1285719 , kernel might send a - * wrong RTM_DELLINK message so that we instead see an removed+added signal. */ - accept_signal (link_added); - ensure_no_signal (link_changed); - accept_signal (link_removed); - } - accept_signals (master_changed, 0, 3); - - ensure_no_signal (master_changed); - - /* Release again */ - ensure_no_signal (link_changed); - g_assert (!nm_platform_link_release (NM_PLATFORM_GET, master, ifindex)); - - ensure_no_signal (master_changed); - - /* Remove */ - ensure_no_signal (link_added); - ensure_no_signal (link_changed); - ensure_no_signal (link_removed); - nmtstp_link_delete (NULL, -1, ifindex, NULL, TRUE); - accept_signals (master_changed, 0, 1); - accept_signals (link_changed, 0, 1); - accept_signal (link_removed); - - free_signal (link_added); - free_signal (link_changed); - free_signal (link_removed); + int ifindex; + SignalData *link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + link_callback, + SLAVE_NAME); + SignalData *link_changed, *link_removed; + char * value; + NMLinkType link_type = nm_platform_link_get_type(NM_PLATFORM_GET, master); + gboolean test_link_changed_signal_arg1; + gboolean test_link_changed_signal_arg2; + + g_assert(NM_IN_SET(link_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE)); + + g_assert(software_add(type, SLAVE_NAME)); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, SLAVE_NAME); + g_assert(ifindex > 0); + link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + link_callback, + ifindex); + link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + link_callback, + ifindex); + accept_signal(link_added); + + /* Set the slave up to see whether master's IFF_LOWER_UP is set correctly. + * + * See https://bugzilla.redhat.com/show_bug.cgi?id=910348 + */ + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + ensure_no_signal(link_changed); + + /* Enslave */ + link_changed->ifindex = ifindex; + g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, master, ifindex)); + g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex), ==, master); + + accept_signals(link_changed, 1, 3); + accept_signals(master_changed, 0, 2); + + /* enslaveing brings put the slave */ + if (NM_IN_SET(link_type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) + g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + else + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + + test_link_changed_signal_arg1 = FALSE; + test_link_changed_signal_arg2 = FALSE; + g_signal_connect(NM_PLATFORM_GET, + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(test_link_changed_signal_cb), + &test_link_changed_signal_arg1); + g_signal_connect(NM_PLATFORM_GET, + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(test_link_changed_signal_cb), + &test_link_changed_signal_arg2); + + /* Set master up */ + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, master, NULL)); + g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, master)); + accept_signals(master_changed, 1, 3); + + g_signal_handlers_disconnect_by_func(NM_PLATFORM_GET, + G_CALLBACK(test_link_changed_signal_cb), + &test_link_changed_signal_arg1); + g_signal_handlers_disconnect_by_func(NM_PLATFORM_GET, + G_CALLBACK(test_link_changed_signal_cb), + &test_link_changed_signal_arg2); + g_assert(test_link_changed_signal_arg1); + g_assert(test_link_changed_signal_arg2); + + /* Master with a disconnected slave is disconnected + * + * For some reason, bonding and teaming slaves are automatically set up. We + * need to set them back down for this test. + */ + switch (nm_platform_link_get_type(NM_PLATFORM_GET, master)) { + case NM_LINK_TYPE_BOND: + case NM_LINK_TYPE_TEAM: + g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex)); + accept_signal(link_changed); + accept_signals(master_changed, 0, 3); + break; + default: + break; + } + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + if (nmtstp_is_root_test() && nm_platform_link_is_connected(NM_PLATFORM_GET, master)) { + if (nm_platform_link_get_type(NM_PLATFORM_GET, master) == NM_LINK_TYPE_TEAM) { + /* Older team versions (e.g. Fedora 17) have a bug that team master stays + * IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if + * `ip link` also claims master to be up, accept it. */ + char *stdout_str = NULL; + + nmtst_spawn_sync(NULL, + &stdout_str, + NULL, + 0, + "/sbin/ip", + "link", + "show", + "dev", + nm_platform_link_get_name(NM_PLATFORM_GET, master)); + + g_assert(strstr(stdout_str, "LOWER_UP")); + g_free(stdout_str); + } else + g_assert_not_reached(); + } + + /* Set slave up and see if master gets up too */ + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, master)); + accept_signals(link_changed, 1, 3); + /* NM running, can cause additional change of addrgenmode */ + accept_signals(master_changed, 0, 3); + + /* Enslave again + * + * Gracefully succeed if already enslaved. + */ + ensure_no_signal(link_changed); + g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, master, ifindex)); + accept_signals(link_changed, 0, 2); + accept_signals(master_changed, 0, 2); + + /* Set slave option */ + switch (type) { + case NM_LINK_TYPE_BRIDGE: + if (nmtstp_is_sysfs_writable()) { + g_assert( + nm_platform_sysctl_slave_set_option(NM_PLATFORM_GET, ifindex, "priority", "614")); + value = nm_platform_sysctl_slave_get_option(NM_PLATFORM_GET, ifindex, "priority"); + g_assert_cmpstr(value, ==, "614"); + g_free(value); + } + break; + default: + break; + } + + /* Release */ + ensure_no_signal(link_added); + ensure_no_signal(link_changed); + ensure_no_signal(link_removed); + g_assert(nm_platform_link_release(NM_PLATFORM_GET, master, ifindex)); + g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex), ==, 0); + if (link_changed->received_count > 0) { + accept_signals(link_added, 0, 1); + accept_signals(link_changed, 1, 5); + accept_signals(link_removed, 0, 1); + } else { + /* Due to https://bugzilla.redhat.com/show_bug.cgi?id=1285719 , kernel might send a + * wrong RTM_DELLINK message so that we instead see an removed+added signal. */ + accept_signal(link_added); + ensure_no_signal(link_changed); + accept_signal(link_removed); + } + accept_signals(master_changed, 0, 3); + + ensure_no_signal(master_changed); + + /* Release again */ + ensure_no_signal(link_changed); + g_assert(!nm_platform_link_release(NM_PLATFORM_GET, master, ifindex)); + + ensure_no_signal(master_changed); + + /* Remove */ + ensure_no_signal(link_added); + ensure_no_signal(link_changed); + ensure_no_signal(link_removed); + nmtstp_link_delete(NULL, -1, ifindex, NULL, TRUE); + accept_signals(master_changed, 0, 1); + accept_signals(link_changed, 0, 1); + accept_signal(link_removed); + + free_signal(link_added); + free_signal(link_changed); + free_signal(link_removed); } static void -test_software (NMLinkType link_type, const char *link_typename) +test_software(NMLinkType link_type, const char *link_typename) { - int ifindex; - char *value; - int vlan_parent = -1, vlan_id; - - SignalData *link_added, *link_changed, *link_removed; - - /* Add */ - link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); - g_assert (software_add (link_type, DEVICE_NAME)); - accept_signal (link_added); - g_assert (nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert (ifindex >= 0); - g_assert_cmpint (nm_platform_link_get_type (NM_PLATFORM_GET, ifindex), ==, link_type); - g_assert_cmpstr (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex), ==, link_typename); - link_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, ifindex); - link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex); - if (link_type == NM_LINK_TYPE_VLAN) { - const NMPlatformLink *plink; - const NMPlatformLnkVlan *plnk; - - plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, &plink); - g_assert (plnk); - g_assert (plink); - - vlan_parent = plink->parent; - vlan_id = plnk->id; - g_assert_cmpint (vlan_parent, ==, nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME)); - g_assert_cmpint (vlan_id, ==, VLAN_ID); - } - - /* Add again */ - g_assert (!software_add (link_type, DEVICE_NAME)); - - /* Set ARP/NOARP */ - g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_set_noarp (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - accept_signals (link_changed, 1, 2); - g_assert (nm_platform_link_set_arp (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - accept_signal (link_changed); - - /* Set master option */ - if (nmtstp_is_root_test ()) { - switch (link_type) { - case NM_LINK_TYPE_BRIDGE: - if (nmtstp_is_sysfs_writable ()) { - g_assert (nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, "forward_delay", "628")); - value = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, "forward_delay"); - g_assert_cmpstr (value, ==, "628"); - g_free (value); - } - break; - case NM_LINK_TYPE_BOND: - if (nmtstp_is_sysfs_writable ()) { - g_assert (nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, "mode", "active-backup")); - value = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, "mode"); - /* When reading back, the output looks slightly different. */ - g_assert (g_str_has_prefix (value, "active-backup")); - g_free (value); - } - break; - default: - break; - } - } - - /* Enslave and release */ - switch (link_type) { - case NM_LINK_TYPE_BRIDGE: - case NM_LINK_TYPE_BOND: - case NM_LINK_TYPE_TEAM: - link_changed->ifindex = ifindex; - test_slave (ifindex, NM_LINK_TYPE_DUMMY, link_changed); - link_changed->ifindex = 0; - break; - default: - break; - } - free_signal (link_changed); - - /* Delete */ - nmtstp_link_delete (NULL, -1, ifindex, DEVICE_NAME, TRUE); - accept_signal (link_removed); - - /* Delete again */ - g_assert (nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME) <= 0); - g_assert (!nm_platform_link_delete (NM_PLATFORM_GET, ifindex)); - - /* VLAN: Delete parent */ - if (link_type == NM_LINK_TYPE_VLAN) { - SignalData *link_removed_parent = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, vlan_parent); - - nmtstp_link_delete (NULL, -1, vlan_parent, NULL, TRUE); - accept_signal (link_removed_parent); - free_signal (link_removed_parent); - } - - /* No pending signal */ - free_signal (link_added); - free_signal (link_removed); + int ifindex; + char *value; + int vlan_parent = -1, vlan_id; + + SignalData *link_added, *link_changed, *link_removed; + + /* Add */ + link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + link_callback, + DEVICE_NAME); + g_assert(software_add(link_type, DEVICE_NAME)); + accept_signal(link_added); + g_assert(nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME)); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert(ifindex >= 0); + g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, ifindex), ==, link_type); + g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, ifindex), ==, link_typename); + link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + link_callback, + ifindex); + link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + link_callback, + ifindex); + if (link_type == NM_LINK_TYPE_VLAN) { + const NMPlatformLink * plink; + const NMPlatformLnkVlan *plnk; + + plnk = nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, &plink); + g_assert(plnk); + g_assert(plink); + + vlan_parent = plink->parent; + vlan_id = plnk->id; + g_assert_cmpint(vlan_parent, + ==, + nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME)); + g_assert_cmpint(vlan_id, ==, VLAN_ID); + } + + /* Add again */ + g_assert(!software_add(link_type, DEVICE_NAME)); + + /* Set ARP/NOARP */ + g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_set_noarp(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + accept_signals(link_changed, 1, 2); + g_assert(nm_platform_link_set_arp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + accept_signal(link_changed); + + /* Set master option */ + if (nmtstp_is_root_test()) { + switch (link_type) { + case NM_LINK_TYPE_BRIDGE: + if (nmtstp_is_sysfs_writable()) { + g_assert(nm_platform_sysctl_master_set_option(NM_PLATFORM_GET, + ifindex, + "forward_delay", + "628")); + value = + nm_platform_sysctl_master_get_option(NM_PLATFORM_GET, ifindex, "forward_delay"); + g_assert_cmpstr(value, ==, "628"); + g_free(value); + } + break; + case NM_LINK_TYPE_BOND: + if (nmtstp_is_sysfs_writable()) { + g_assert(nm_platform_sysctl_master_set_option(NM_PLATFORM_GET, + ifindex, + "mode", + "active-backup")); + value = nm_platform_sysctl_master_get_option(NM_PLATFORM_GET, ifindex, "mode"); + /* When reading back, the output looks slightly different. */ + g_assert(g_str_has_prefix(value, "active-backup")); + g_free(value); + } + break; + default: + break; + } + } + + /* Enslave and release */ + switch (link_type) { + case NM_LINK_TYPE_BRIDGE: + case NM_LINK_TYPE_BOND: + case NM_LINK_TYPE_TEAM: + link_changed->ifindex = ifindex; + test_slave(ifindex, NM_LINK_TYPE_DUMMY, link_changed); + link_changed->ifindex = 0; + break; + default: + break; + } + free_signal(link_changed); + + /* Delete */ + nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE); + accept_signal(link_removed); + + /* Delete again */ + g_assert(nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME) <= 0); + g_assert(!nm_platform_link_delete(NM_PLATFORM_GET, ifindex)); + + /* VLAN: Delete parent */ + if (link_type == NM_LINK_TYPE_VLAN) { + SignalData *link_removed_parent = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + link_callback, + vlan_parent); + + nmtstp_link_delete(NULL, -1, vlan_parent, NULL, TRUE); + accept_signal(link_removed_parent); + free_signal(link_removed_parent); + } + + /* No pending signal */ + free_signal(link_added); + free_signal(link_removed); } static void -test_bridge (void) +test_bridge(void) { - test_software (NM_LINK_TYPE_BRIDGE, "bridge"); + test_software(NM_LINK_TYPE_BRIDGE, "bridge"); } static int -_system (const char *cmd) +_system(const char *cmd) { - /* some gcc version really want to warn on -Werror=unused-result. Add a bogus wrapper - * function. */ - return system (cmd); + /* some gcc version really want to warn on -Werror=unused-result. Add a bogus wrapper + * function. */ + return system(cmd); } static void -test_bond (void) +test_bond(void) { - if ( nmtstp_is_root_test () - && !g_file_test ("/proc/1/net/bonding", G_FILE_TEST_IS_DIR) - && _system("modprobe --show bonding") != 0) { - g_test_skip ("Skipping test for bonding: bonding module not available"); - return; - } - - test_software (NM_LINK_TYPE_BOND, "bond"); + if (nmtstp_is_root_test() && !g_file_test("/proc/1/net/bonding", G_FILE_TEST_IS_DIR) + && _system("modprobe --show bonding") != 0) { + g_test_skip("Skipping test for bonding: bonding module not available"); + return; + } + + test_software(NM_LINK_TYPE_BOND, "bond"); } static void -test_team (void) +test_team(void) { - int r; + int r; - if (nmtstp_is_root_test ()) { - r = nm_platform_link_team_add (NM_PLATFORM_GET, "nm-team-check", NULL); + if (nmtstp_is_root_test()) { + r = nm_platform_link_team_add(NM_PLATFORM_GET, "nm-team-check", NULL); - if (r < 0) { - g_assert_cmpint (r, ==, -EOPNOTSUPP); - g_test_skip ("Skipping test for teaming: team module not functioning"); - return; - } + if (r < 0) { + g_assert_cmpint(r, ==, -EOPNOTSUPP); + g_test_skip("Skipping test for teaming: team module not functioning"); + return; + } - nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, "nm-team-check", FALSE); - } + nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, "nm-team-check", FALSE); + } - test_software (NM_LINK_TYPE_TEAM, "team"); + test_software(NM_LINK_TYPE_TEAM, "team"); } static void -test_vlan (void) +test_vlan(void) { - test_software (NM_LINK_TYPE_VLAN, "vlan"); + test_software(NM_LINK_TYPE_VLAN, "vlan"); } /*****************************************************************************/ static void -test_bridge_addr (void) +test_bridge_addr(void) { - char addr[ETH_ALEN]; - NMPlatformLink link; - const NMPlatformLink *plink = NULL; - - nm_utils_hwaddr_aton ("de:ad:be:ef:00:11", addr, sizeof (addr)); - - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, DEVICE_NAME, addr, sizeof (addr), &plink))); - g_assert (plink); - link = *plink; - g_assert_cmpstr (link.name, ==, DEVICE_NAME); - - g_assert_cmpint (link.l_address.len, ==, sizeof (addr)); - g_assert (!memcmp (link.l_address.data, addr, sizeof (addr))); - - plink = nm_platform_link_get (NM_PLATFORM_GET, link.ifindex); - g_assert (plink); - - if (nm_platform_kernel_support_get (NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { - g_assert (!nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, link.ifindex)); - g_assert_cmpint (_nm_platform_uint8_inv (plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_EUI64); - - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, link.ifindex, TRUE))); - g_assert (nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, link.ifindex)); - plink = nm_platform_link_get (NM_PLATFORM_GET, link.ifindex); - g_assert (plink); - g_assert_cmpint (_nm_platform_uint8_inv (plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_NONE); - - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, link.ifindex, FALSE))); - g_assert (!nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, link.ifindex)); - plink = nm_platform_link_get (NM_PLATFORM_GET, link.ifindex); - g_assert (plink); - g_assert_cmpint (_nm_platform_uint8_inv (plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_EUI64); - } - - g_assert_cmpint (plink->l_address.len, ==, sizeof (addr)); - g_assert (!memcmp (plink->l_address.data, addr, sizeof (addr))); - - nmtstp_link_delete (NULL, -1, link.ifindex, link.name, TRUE); + char addr[ETH_ALEN]; + NMPlatformLink link; + const NMPlatformLink *plink = NULL; + + nm_utils_hwaddr_aton("de:ad:be:ef:00:11", addr, sizeof(addr)); + + g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_bridge_add(NM_PLATFORM_GET, + DEVICE_NAME, + addr, + sizeof(addr), + &nm_platform_lnk_bridge_default, + &plink))); + g_assert(plink); + link = *plink; + g_assert_cmpstr(link.name, ==, DEVICE_NAME); + + g_assert_cmpint(link.l_address.len, ==, sizeof(addr)); + g_assert(!memcmp(link.l_address.data, addr, sizeof(addr))); + + plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex); + g_assert(plink); + + if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL)) { + g_assert(!nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex)); + g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv), + ==, + NM_IN6_ADDR_GEN_MODE_EUI64); + + g_assert(NMTST_NM_ERR_SUCCESS( + nm_platform_link_set_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex, TRUE))); + g_assert(nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex)); + plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex); + g_assert(plink); + g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv), + ==, + NM_IN6_ADDR_GEN_MODE_NONE); + + g_assert(NMTST_NM_ERR_SUCCESS( + nm_platform_link_set_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex, FALSE))); + g_assert(!nm_platform_link_get_user_ipv6ll_enabled(NM_PLATFORM_GET, link.ifindex)); + plink = nm_platform_link_get(NM_PLATFORM_GET, link.ifindex); + g_assert(plink); + g_assert_cmpint(_nm_platform_uint8_inv(plink->inet6_addr_gen_mode_inv), + ==, + NM_IN6_ADDR_GEN_MODE_EUI64); + } + + g_assert_cmpint(plink->l_address.len, ==, sizeof(addr)); + g_assert(!memcmp(plink->l_address.data, addr, sizeof(addr))); + + nmtstp_link_delete(NULL, -1, link.ifindex, link.name, TRUE); } /*****************************************************************************/ static void -test_internal (void) +test_internal(void) { - SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); - SignalData *link_changed, *link_removed; - const char mac[6] = { 0x00, 0xff, 0x11, 0xee, 0x22, 0xdd }; - const char *address; - size_t addrlen; - int ifindex; - - /* Check the functions for non-existent devices */ - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert (!nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)); - - /* Add device */ - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL))); - accept_signal (link_added); - - /* Try to add again */ - g_assert (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == -NME_PL_EXISTS); - - /* Check device index, name and type */ - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert (ifindex > 0); - g_assert_cmpstr (nm_platform_link_get_name (NM_PLATFORM_GET, ifindex), ==, DEVICE_NAME); - g_assert_cmpint (nm_platform_link_get_type (NM_PLATFORM_GET, ifindex), ==, NM_LINK_TYPE_DUMMY); - g_assert_cmpstr (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex), ==, DUMMY_TYPEDESC); - link_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, ifindex); - link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex); - - /* Up/connected */ - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL)); - g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - accept_signals (link_changed, 1, 2); - g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - accept_signal (link_changed); - - /* arp/noarp */ - g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_set_arp (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - accept_signal (link_changed); - g_assert (nm_platform_link_set_noarp (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - accept_signal (link_changed); - - /* Features */ - g_assert (!nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_supports_vlans (NM_PLATFORM_GET, ifindex)); - - /* Set MAC address */ - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_set_address (NM_PLATFORM_GET, ifindex, mac, sizeof (mac)))); - address = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &addrlen); - g_assert (addrlen == sizeof(mac)); - g_assert (!memcmp (address, mac, addrlen)); - address = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, NULL); - g_assert (!memcmp (address, mac, addrlen)); - accept_signal (link_changed); - - /* Set MTU */ - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, MTU))); - g_assert_cmpint (nm_platform_link_get_mtu (NM_PLATFORM_GET, ifindex), ==, MTU); - accept_signal (link_changed); - - /* Delete device */ - nmtstp_link_delete (NULL, -1, ifindex, DEVICE_NAME, TRUE); - accept_signal (link_removed); - - /* Try to delete again */ - g_assert (!nm_platform_link_delete (NM_PLATFORM_GET, ifindex)); - - free_signal (link_added); - free_signal (link_changed); - free_signal (link_removed); + SignalData *link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + link_callback, + DEVICE_NAME); + SignalData *link_changed, *link_removed; + const char mac[6] = {0x00, 0xff, 0x11, 0xee, 0x22, 0xdd}; + const char *address; + size_t addrlen; + int ifindex; + + /* Check the functions for non-existent devices */ + g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME)); + g_assert(!nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME)); + + /* Add device */ + g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL))); + accept_signal(link_added); + + /* Try to add again */ + g_assert(nm_platform_link_dummy_add(NM_PLATFORM_GET, DEVICE_NAME, NULL) == -NME_PL_EXISTS); + + /* Check device index, name and type */ + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert(ifindex > 0); + g_assert_cmpstr(nm_platform_link_get_name(NM_PLATFORM_GET, ifindex), ==, DEVICE_NAME); + g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, ifindex), ==, NM_LINK_TYPE_DUMMY); + g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, ifindex), ==, DUMMY_TYPEDESC); + link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + link_callback, + ifindex); + link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + link_callback, + ifindex); + + /* Up/connected */ + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_set_up(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + accept_signals(link_changed, 1, 2); + g_assert(nm_platform_link_set_down(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + accept_signal(link_changed); + + /* arp/noarp */ + g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_set_arp(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + accept_signal(link_changed); + g_assert(nm_platform_link_set_noarp(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + accept_signal(link_changed); + + /* Features */ + g_assert(!nm_platform_link_supports_carrier_detect(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_supports_vlans(NM_PLATFORM_GET, ifindex)); + + /* Set MAC address */ + g_assert(NMTST_NM_ERR_SUCCESS( + nm_platform_link_set_address(NM_PLATFORM_GET, ifindex, mac, sizeof(mac)))); + address = nm_platform_link_get_address(NM_PLATFORM_GET, ifindex, &addrlen); + g_assert(addrlen == sizeof(mac)); + g_assert(!memcmp(address, mac, addrlen)); + address = nm_platform_link_get_address(NM_PLATFORM_GET, ifindex, NULL); + g_assert(!memcmp(address, mac, addrlen)); + accept_signal(link_changed); + + /* Set MTU */ + g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_set_mtu(NM_PLATFORM_GET, ifindex, MTU))); + g_assert_cmpint(nm_platform_link_get_mtu(NM_PLATFORM_GET, ifindex), ==, MTU); + accept_signal(link_changed); + + /* Delete device */ + nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE); + accept_signal(link_removed); + + /* Try to delete again */ + g_assert(!nm_platform_link_delete(NM_PLATFORM_GET, ifindex)); + + free_signal(link_added); + free_signal(link_changed); + free_signal(link_removed); } /*****************************************************************************/ static void -test_external (void) +test_external(void) { - const NMPlatformLink *pllink; - SignalData *link_added, *link_changed, *link_removed; - int ifindex; - - link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); - - nmtstp_run_command_check ("ip link add %s type %s", DEVICE_NAME, "dummy"); - wait_signal (link_added); - - g_assert (nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert (ifindex > 0); - g_assert_cmpstr (nm_platform_link_get_name (NM_PLATFORM_GET, ifindex), ==, DEVICE_NAME); - g_assert_cmpint (nm_platform_link_get_type (NM_PLATFORM_GET, ifindex), ==, NM_LINK_TYPE_DUMMY); - g_assert_cmpstr (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex), ==, DUMMY_TYPEDESC); - link_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, ifindex); - link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex); - - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); - g_assert (pllink); - if (!pllink->initialized) { - /* we still lack the notification via UDEV. Expect another link changed signal. */ - wait_signal (link_changed); - } - - /* Up/connected/arp */ - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - - nmtstp_run_command_check ("ip link set %s up", DEVICE_NAME); - wait_signal (link_changed); - - g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - nmtstp_run_command_check ("ip link set %s down", DEVICE_NAME); - wait_signal (link_changed); - g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); - g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - - nmtstp_run_command_check ("ip link set %s arp on", DEVICE_NAME); - wait_signal (link_changed); - g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - nmtstp_run_command_check ("ip link set %s arp off", DEVICE_NAME); - wait_signal (link_changed); - g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex)); - - nmtstp_run_command_check ("ip link del %s", DEVICE_NAME); - wait_signal (link_removed); - accept_signals (link_changed, 0, 1); - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); - - free_signal (link_added); - free_signal (link_changed); - free_signal (link_removed); + const NMPlatformLink *pllink; + SignalData * link_added, *link_changed, *link_removed; + int ifindex; + + link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + link_callback, + DEVICE_NAME); + + nmtstp_run_command_check("ip link add %s type %s", DEVICE_NAME, "dummy"); + wait_signal(link_added); + + g_assert(nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME)); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert(ifindex > 0); + g_assert_cmpstr(nm_platform_link_get_name(NM_PLATFORM_GET, ifindex), ==, DEVICE_NAME); + g_assert_cmpint(nm_platform_link_get_type(NM_PLATFORM_GET, ifindex), ==, NM_LINK_TYPE_DUMMY); + g_assert_cmpstr(nm_platform_link_get_type_name(NM_PLATFORM_GET, ifindex), ==, DUMMY_TYPEDESC); + link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + link_callback, + ifindex); + link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + link_callback, + ifindex); + + pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex); + g_assert(pllink); + if (!pllink->initialized) { + /* we still lack the notification via UDEV. Expect another link changed signal. */ + wait_signal(link_changed); + } + + /* Up/connected/arp */ + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + + nmtstp_run_command_check("ip link set %s up", DEVICE_NAME); + wait_signal(link_changed); + + g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + nmtstp_run_command_check("ip link set %s down", DEVICE_NAME); + wait_signal(link_changed); + g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex)); + + nmtstp_run_command_check("ip link set %s arp on", DEVICE_NAME); + wait_signal(link_changed); + g_assert(nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + nmtstp_run_command_check("ip link set %s arp off", DEVICE_NAME); + wait_signal(link_changed); + g_assert(!nm_platform_link_uses_arp(NM_PLATFORM_GET, ifindex)); + + nmtstp_run_command_check("ip link del %s", DEVICE_NAME); + wait_signal(link_removed); + accept_signals(link_changed, 0, 1); + g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME)); + + free_signal(link_added); + free_signal(link_changed); + free_signal(link_removed); } /*****************************************************************************/ static guint8 * -_copy_base64 (guint8 *dst, gsize dst_len, const char *base64_src) +_copy_base64(guint8 *dst, gsize dst_len, const char *base64_src) { - g_assert (dst); - g_assert (dst_len > 0); - - if (!base64_src) - memset (dst, 0, dst_len); - else { - gs_free guint8 *b = NULL; - gsize l; - - b = g_base64_decode (base64_src, &l); - g_assert (b); - g_assert (l == dst_len); - - memcpy (dst, b, dst_len); - } - return dst; + g_assert(dst); + g_assert(dst_len > 0); + + if (!base64_src) + memset(dst, 0, dst_len); + else { + gs_free guint8 *b = NULL; + gsize l; + + b = g_base64_decode(base64_src, &l); + g_assert(b); + g_assert(l == dst_len); + + memcpy(dst, b, dst_len); + } + return dst; } typedef struct { - const char *pri; - const char *pub; - const char *pre; + const char *pri; + const char *pub; + const char *pre; } KeyPair; static void -_test_wireguard_change (NMPlatform *platform, - int ifindex, - int test_mode) +_test_wireguard_change(NMPlatform *platform, int ifindex, int test_mode) { - const KeyPair self_key = - { "yOWEsaXFxX9/DOkQPzqB9RufZOpfSP4LZZCErP0N0Xo=", "s6pVT2xPwktor9O5bVOSzcPqBu9uzQOUzPQHXLU2jmk=" }; - const KeyPair keys[100] = { - { "+BDHMh11bkheGfvlQpqt8P/H7N1sPXtVi05XraZS0E8=", "QItu7PJadBVXFXGv55CMtVnbRHdrI6E2CGlu2N5oGx4=", "2IvZnKTzbF1UlChznWSsEYtGbPjhYSTT41GXO6zLxvk=" }, - { "qGZyV2BO1nyY/FGYd6elBPirwJC9QyZwqbm2OJAgLkY=", "v8L1FEitO0xo+wW/CVVUnALlw0zGveApSFdlITi/5lI=", "/R2c0JmBNGJzT594NQ0mBJ2XJjxt2QUSo+ZiqeY0EQA=" }, - { "YDgsIb0oe+9NcxIx2r0HEEPQpRMxmRN0ALoLm9Sh40Q=", "nFPs1HaU7uFBvE9xZCMF8oOAjzLpZ49AzDHOluY1O2E=", "zsYED2Ef7zIHJoRBPcen+w4ktrRsLPEfYwZhWIuXfds=" }, - { "kHkosM503LWu43tdYXbNwVOpRrtPgd9XFqcN7k4t6G4=", "b8e092WT+eNmnxCr5WE2QC/MXAjDagfG1g03cs2mBC0=", "VXz0ShGWT7H0CBCg2awfatmOJF15ZtaSMPhMsp+hc3A=" }, - { "4C2w5CEnxH59Y2aa6CJXgLdDtWoNMS2UJounRCM1Jkk=", "gC/R9umlnEQL+Qsz/Y64AlsdMge4ECe5/u/JHZCMWSs=", "2bmL5ISr+V5a7l7xFJ695BLIJyBgx8xnxzybkxiRHOg=" }, - { "KHJSzFGkXcZf/wbH2rr99SYtGKWbL680wA2AcDE94lo=", "BsN23h4aOi458Q3EgMQsodsWQxd9h/RxqskAUpsXfgg=", "nK4Zv34YKEhjuexhq1SgK4oTd4MZJT5gcpYvEuPjc7Q=" }, - { "QGMulXJ9e3AVxtpi8+UUVqPOr/YBWvCNFVsWS9IUnUA=", "kjVclP5Ifi6og2BBCEHKS/aa/WktArB4+ig06lYaVlg=", "0+mmceDPcSRK3vFnYqHd9iAfY+Nyjzf/1KgDeYGlRkQ=" }, - { "AOJiDD4y6GA7P7gugjjQG9Cctvc5Y27fajHz6aU3gU4=", "gEnHn6euHtcMEwZBlX6HANPeN9Of+voBDtltS38xDUw=", "wIH1OxgX6GLxx/bnR+t3fbmjGZDTU3WMxp7t1XGezqM=" }, - { "COsls2BlCltaIrrq1+FU51cWddlmoPPppSeIDunOxGA=", "+n6WuV8Tb1/iZArTrHsyNqkRHABbavBQt9Me72K2KEc=", "t4baiprSO9ZbKD2/RutOY9cr+yCajQWZGCTnQdrFQj0=" }, - { "uHawQq2BRyJlsTPoCa+MfBVnv4MwtRoS+S9FEpFOEVg=", "8lcmr27afeb6iI3BQCaDtvalF2Cl7gxRZgs+nyJ/fEg=", "Eh9o/6W60iujBLIHuRfNrPhOWAn7PambT2JRln9iwA0=" }, - { "yL7hmoE/JfRGAotRzx9xOpjfrDA3BFlPEemFiQw40Wk=", "BHK0PHi5kp7rOfQ46oc9xlVpB+pZeZYXTtH7EXr5TwU=", "BS2h2ZZyW0BlYMmLR29xyHEcZ4jtO7rgj1jkz/EEaxU=" }, - { "ON8YrTHQgoC5e0mAR9FakZ8hZ/9I7ysuE21sG546J1Y=", "Bm3l5I6iH1tDrv6EgdZU9PzHqp0H26Z6ggmmIypwxy8=", "qKVfbCnK1EI3eC28SsL+jyBnEnIF/nRJQJzDevBFdNQ=" }, - { "KGLO0RI0VlQFCG+ETUqk25HdaKUnUPXKOKkTh/w8BXU=", "sBDBwQFC7k8UMdMzuavKBkBjYYKigzvYmGF5rm6muQc=", "BNfZF9d7540pUGGOQCh3iDxAZcPBqX4qqM00GSLPBek=" }, - { "KGdWyEodIn7KKI2e4EFK9tT6Bt3bNMFBRFVTKjjJm2E=", "lrbjU/Xn9wDCZQiU8E5fY6igTSozghvo47QeVIIWaUk=", "LczqW48MW8qDQIZYRELsz/VCzVDc5niROvk7OqrTxR0=" }, - { "wO3xinUGABgEmX+RJZbBbOtAmBuPPFG6oVdimvoo90w=", "dCIvTzR6EerOOsRKnWly1a9WGzbJ4qc+6t3SSzLgWFk=", "wFj0zpr5PadBoBy0couLuZ1qudZbXLbV/j3UT+AyKeo=" }, - { "+JNOBlO4tp9vvQk6UO4r3sILyEgjl+BBoWketZufyn0=", "Q6LSv9y7YQkJEzQ/1mpjJEgOrO8GYPUTgcizjh7Cm34=", "kg7AG9MuN04xPJ5Z0IcNZ4a8d1b/n4GsGIeyA4FaaSE=" }, - { "+EJcThLRwjZ+h1CNNFu15HWzznf4u/lPVw8hifTm2Ec=", "Kkn2jFqwBzyIFQfD0OpmePFSmBYmhKagv4pGgkqsWgE=", "jYpxojj8WKYe/XIXMP+uv1Fv0+TKrs83tqfzP0AGdcI=" }, - { "+DKFqSMNFmxriEFj3qatuzYeTJ9+xWYspZ4ydL3eC0Q=", "3o37bsg6HhRg/M9+fTlLcFYc2w/Bz9rLQySvvYCKbRE=", "Jb9qoDIBat1EexlgfpRbXa7OflptME8/zt93bldkiVE=" }, - { "EH3MjFOMqRoDFQz+hSlJpntWBeH3lTk6WPjTIQjr42o=", "PbPewED/nxSBLdM7AXMj7uS3bCgAAg8M6F4iPLd0b1U=", "pj4+UgOGkpJwlRvX5BRXZzmzAUnDtUtJsS7LzbcJWzw=" }, - { "kL6M2KvO+vPBLEc/a0DpEHTibQ1bwaMRT9b9SkzeP0Y=", "pS3G2bHHlkOE6UHP0qVitDuxXgjEaZTviTjNc55RbVs=", "ZVZpWOtYqhX3CpF1kATg/38J6pvUJo8AS1sVYjs3rUE=" }, - { "sFlcRLDn36fnew2Ld92IHJwnKifdS3aF1MWRPs6K3Wg=", "OpjUOTiWExaDYULTINB4yQFqc3mnU3RjQzGRV+KtdFY=", "of0V/uoFRNljv/XTt/tXgoquLRH93Ty0KNiaPUpEi2w=" }, - { "UJ8hjDsg3jfsnnfPH8Gw9FnCb6taTuviurAfZu+kEFg=", "3byjHksUOv8CNjGGKvHvvrJDURBhCIL5UtfZbgyVWCE=", "9f7dbWif51gGrE7R9LeuewQSrvGFGTOB3ceJC67jSkI=" }, - { "iFFPKGIfqeUKY/w72KAZSjd/PGTqCakHYBV10xMDfnI=", "ehneHATNSXtsJTOiPjVSc0QARkihgcfcvoXKFWKfQnI=", "yKdqDBcRwA7RCg4GiY/b5IsWcExPleOBde/hjxc36a4=" }, - { "GDGocdPJTPUAllxQo7SpXZKqMPn7lpxQELQUX9ETHmE=", "n0ScNEou4ekfrXRRXvcADLu2Afj8g5D3TuDP/I4KrnY=", "8QhswqAhi/ehhcmCwQF5aSh80TvIGC/gRL5jBn5wOH8=" }, - { "UCcrlN8fX2ZdNdhaEBNwktwL+H0ZO7fhaj7rgdUutmw=", "LF8J728ilXs4TphnrgR6r0p7W3912DYnsXkGMEPQnRE=", "cYfMjxl2REYir7frGeB0u+NHAaFYF02ysgpBhOL5ygc=" }, - { "SH0657XuIiHidVmViXZF30RUWtkuWXcWWHmKZHTiOG8=", "7k6j49W1u5qgLE5MQUc1osPVW1oPPhzjrGvJ7o9YamY=", "dV2+7rNk/3LR2IcwYg/c+Wvzep1yjY7/u1I+nnlTQ00=" }, - { "qFQWs6jzrscV42pGISQyA7JDvFFAvEQCWJi584VHD2g=", "AT63nHKLC17yUvkR4lOVPxCr4DD3QhXmcmecOTn+Amc=", "2Qe2fwJbFcu1CmKpktElOFkSQMqlyvlV3ZUIAd/Dcts=" }, - { "6J+yLxgPwWtUbk9I3zbeD8RuK6XkQjJ0wTJ1zSVhflQ=", "NJzMBYyPZjk3eLmgdKaOeWyNER5YZF1mR8Umeiu9f28=", "pp+4+XHw5ZmHGJ7WbZ1xLYRsnTI17QIbb0bzHzYZrBs=" }, - { "KJGoWYNVDUWcEMg+E4tljv1LiWAbdRw2QVapYqdFa1Y=", "M2SGk9WVnzYNGnT777G/JE8uUsY2f7mszTwlue73UDE=", "Jg8N7GbhbYB400foFP+OH0v+hCaL1jW61bajSA6EZqc=" }, - { "uAgrgppPyIvk8S1CHUmaCaORsgFFfBreB8pxXmbSdXw=", "dJ22bER4fD3qF2/yIGWQ7SgmZ990sy/SbANjmUMkzws=", "mKkd0OoAR9sClmD+k3fL9weBsoCy5GQGz9BP0kAQIjc=" }, - { "EI3Q8gePNPrtFyoMcv7hOihQgroF/dfjzPn8yvpGPWQ=", "Y9QhJFeiyuuIZNPU56B6U//ZK+XTTe4EP7h/p3Q+dE8=", "qBVUYw9rTWaxn55nUd55NpCWtxOUSWLt4WJGusiDS8Q=" }, - { "oEQvdRm/yHkx+JvlhHGT5RUFrFEUleKb9DCT55EqZ30=", "8hsh/UHwWADTHntOJq4dy0o7ahcNAAlo2rDpjzzrVXk=", "/GF2inW2mPtA26IgFdgOEBbBEerT740wWuP/8NyANdc=" }, - { "6OWrGKZKNsgfRezSUw29EnHymcgKyEKvX5/pZQlLmWs=", "oaJeO6YSS2dodNEf97DvgWrYnFFelG5daEdN84jVVGw=", "T5wvTdyVxK0LY96kouLjs06oUfhGChfty8OUL1Mddro=" }, - { "mPmzQbh2R+r1DC5hSquzKM1SDrxUdfnBPRPJrpqrgkE=", "BtUHAnYWjDjBI42qBf9dJqezTUikYsF96o6PKEWPrVo=", "MxU8EMmq+vVHpuK/AkFZrZDF2b+VbSqukZLPbNsCcgo=" }, - { "8GVxuoo1Veyr+nqxr5Q4vmsMf5qfiXwSlQ4q3+BU60g=", "uSOLe/E9/OjIgUOk0NMBHB45E0+q4Rd+IUO2UOxmKlM=", "+30F+56OE0Sr3wY2clKw4kgE+2XiucMg7xjK6EemXuk=" }, - { "qORPKb+qFuU/9TpFbRUupHsqm9iyk9pa6cpik+EVDkg=", "bMZxxd+Z9I0XA1h9U8JEY+/mRxWGnvbXDZ5Dxz7YzS0=", "SmkkqOz4OhHuSL6cxuRm9+Mlt50Sfd0sMDFTC78gqOE=" }, - { "2Ko3IYhXKcdOMIJGNpASk9saNSZsI64lyJPOoxpQ2kI=", "xVOc9PxY1VFaZfemmKi+Ei2liHhmeTu+JMa+rS00gnA=", "+398DlW8kWeI2aRaC4QfcrEjwqPKCohyDeWdaI1wvv0=" }, - { "CPioGCVpxnym62nH/QoCt1RiiaaxUcuFjvh5kRhjqHA=", "W0XxlBLrZgFKhggMvvv6oFf/RJbfs92qv8JK9e+5i2o=", "bsK2U6CRAUv1uVgYQ7NpqjWWswFIDiDPDEtU1XQygSA=" }, - { "AF17siKaeiO85hikYN0IWCMGWqPm1UOoCkXMltJGUVk=", "B+PFos9aN2S5bLxzGZHljRZj41j3rIx8RWu0vDUzq1w=", "Qb8d6iDYv3m1h7PE8j0Exl2cSwpHkim/fJ1S4P7MYvY=" }, - { "wMFDBTJzx5tDCBhMkrptYJ8w9EeURjc4xeDQpevxAWo=", "4ec439EXE5WQzvtV9reSX+aMmdq5k7o9Ayt8oQp+RhQ=", "jwQlvdNH5WtSSU10H+fh/JisOlaBaohDPEp/BYnTt1Q=" }, - { "4GaJpIFigNDwd31O84pLIMM/o2qhp0ydlI/ydD/2a2Q=", "r/LdkCoK5/BPGdq2+XJO8sCRhI+8ULFmg0887V43PAI=", "Da+3ZZvEJdx4TYFMIDUlbkmytILnSTNxTKX+sQdjMd4=" }, - { "gMnojGqCLmMfGp2m31xlKZ/rIV2b8ockw9DPahRyu0c=", "H6tKCTosnM4BXKqflXrkTdJyNlCIZhQ3ZRxfrvSdrDk=", "4Z6K3LKIMV89plcjMb9CzSzJl03SWRe/++geBMZcOtY=" }, - { "wKCg22aNNoHnDJ0oAKE46FcSSsREW4AaGn5WxCSeXUs=", "9NDTFC0iPt4HbbWepLHhN5poNTN2fdxJKNadsNT7qzY=", "GSVTOCnfLpJ1VCOLHaKSjCMv7/OlcnQiP5+5woqkud8=" }, - { "oCoykq7pcJcg2X2V5TBRzGwn8hzzHC05WUreuotdznY=", "DxfwnbMqr5Wn5SAyFolfEmNQT6l84Oq69ngpg6H6Iio=", "p1RHBuqhuDa1MAQ2lbqmUQFu0CTwYlf73fWZSj9tQhA=" }, - { "UO7YVyRUVkcKr7c63VWWV2zj36XD3HyDfLZCqvrZmFc=", "360lzYtIyHq5lv/QXSCe4bL4G2J1jBXFJ8yS+Ycr7Bc=", "RRPQ1XWF1HN8Us4dtfn2eemdjgtWm7U8r7mM3y00NOk=" }, - { "eCGFYV/NuGP4H552E8Of1xU+3IvZxGyX+p5UFGW8iHI=", "LqhZ4AS9dQ/MhsQnE5Oy7Q8INXY+P+mrfGY5dtg9SlE=", "SICfqs8T5wP6IzATDCT4ovamBKPdkZ7JP4Cfsb3izec=" }, - { "oI3HBZknoIMMZw1BuYMkTBylt25reX7AbCqtWQv8cno=", "B7dUgLgvQhi0RGmvaMrmf26WdjEVrhaiBclVkCKd4AA=", "5O9K9pLXwxFAt5lfMWh4qGbwX1BM7sz0QGYxAnR77dk=" }, - { "sBfYn14EFVIS2M/E1aahP7mOmRNbNtyDChDMS1s6aGs=", "FLYv0ZvzxMkc9A7OzhC4P1ZRu1aKIQd7u6gqfdekC3c=", "kaYLcNCXnCLgiB8fleMQuboUJsj5u3YAmXL9x3ywV0M=" }, - { "qFwZESU/XYZXUtxwrGsFU9qPAFTzjm7EhTS1Q6ajGlM=", "hraQQaqJCkS2yQXv+ccMOVh9V9a/qgSZJgdMAhrt8ms=", "72oDfnWOn39gdk/ncw8Lv267I0I+m73SwxrpYojpWYk=" }, - { "YHhp6Zf/miuc2QXeI2lTezy0lL0pTv2b+nWNkmjYQWI=", "UhNO5arLzF0WlZSgNOx7+IjWN+GSxDdQxZRp8uIwsyI=", "1Q39Nzv2NGI9zWKWMpYLURAMZUg+FP+OboHHzFU8Anc=" }, - { "mLBBXKaCJ+7qeBZpS3wxGi/SQ4kLzun+K+QwwdwfJVQ=", "gIq/nh7NwCJ36MvRnyrWHaRWu8lTmwfN2NvsjVl6SXQ=", "AahcNR91GDyJBIP+vC8ZuIV8ukqjSGtd8s+cmjVC2Ao=" }, - { "OJG4LZlNNngFtAEQdbVVWVm6QAjOOauGcMZGbQrb40M=", "pFHAC6HaWAOtvTRRVfSHvzG05mp4SJZXKsN/tkSF0kM=", "IoXT3wIqWNxQhYuHWl12ODq/P7RM9LwaqglhmjKg+0g=" }, - { "OOwBFOQNhepiqDf04DehQLh1gpBNOluDF1ia752Yfng=", "u715uJ/XhdjXjThCTJ9w6zzXnIhp3VCxhtso1wk+oBQ=", "5x1Ip3Ym0KzDjGhiYjmpeWWr+dgrZlYwfr02GngPOTM=" }, - { "eNPFnwkQy1qw+IjFAlrDA6+sIsxbWDlzbNSsBW8R1UA=", "OaOXaAfPb1MRpWadawFje8YZ0oxJgdCIDIP8c5X+r1U=", "NtfaRRD0GqujnaQQoNoBbtovgO4dfVwEmEQx/YgnDpw=" }, - { "OLdaZItbtxH3mGqItkibIJp7KV27FrQavjhd5zq6s3Q=", "SLSmAYxkMCGj0DO35cMLkC3NVAqK2VmVFndbOZEdA24=", "SnBO68XQTDjxYbmYaAeEHgLwD2u4D+BPT86raRuUQZM=" }, - { "UBQOEz08izwr4eEK/SnQUpkt+TxCjo6Sya/XOGMLOE0=", "wQwrwezI9LzKevGsJJCBHDG8noR0yIEtOK5Rig97SSo=", "DpyS+0d7lrlFWkztsniG2v/j44vcuvWz3sPeghRyb5A=" }, - { "mN98iuqUKh67ggUdq9ZIQNZCZM90fgycTVqYKEo+DkY=", "GYdXVW1jpS0dN1q9zMehubP7LfYqs34kszN0bXQqxxA=", "AJPIHffB4uvvJJki4xCG0VORVBbF6bc2mZQqUx+idPc=" }, - { "OEd/1it8C3o+NOWxDI3DfLMXVBHJQg15N3E8F8d99l8=", "QL1NcuUkoXxDy7M9VjGslCejcUlnUDHRghFVnr+8fmA=", "nven9Dicl8U6QXuDO8rRNtjd4NYaa90SU+Gmv435XKY=" }, - { "AFMCGDu2oAP68miucsi4fmYX2KeRZnsEGv8tQm8JEng=", "1sNxvk8uZhFsBUgxOXmuCMjDAgBbjVeWe9oaFk5Osy0=", "t5iI5XXd56S5q0Y9HC91gzgF9uGjL9FIy6NUaKqkydo=" }, - { "CIAwfJghQHHr4YlztN9at6/iWkrEVCGFAxNVuQCuT3I=", "zpUOF1h17g7RpBzrVlN7oTRz6e+dxcDL8OsAtHwgLC8=", "kOSwC1p6Uoti9E9Eg7ViPZwCytuvp5Fr5Buw677aogU=" }, - { "sC8vrAVBU0zvhWDRfzfySjvopXm2/cTMkTLmioyO3Es=", "p6H7GWm8NfgyO5OCX/COjvVT4MAnTs9ZUj4uZMK8XHA=", "9Tzqo57V/h7+6nSNAHSBKdmU7ultlvZbAnNKSRlrLi4=" }, - { "eI63gjxCZGnzqZxPEi/ifYphXhxIRI2ZxK8jzqo3mmU=", "XyNzEuU9x37fxFCnrZH89Krs5/UqGVx5wNkGfQCAYz0=", "vZ2fTlRPnJQ+q33YdS5p1aweqPGj/kTMc4Uq80FtFjI=" }, - { "aNJlGtm79/RS4SQ/PC4YM6LFo9zAqDr2/RjLqk/z/1A=", "lgZ9akPrABmfHQMlfNFnnpAJzGtcsaU9mUjEYKfzZHc=", "d0Xt1Bcgphd1HMI0RneA4VdBbMZL1qNGJAvFhb080eA=" }, - { "oONSnHirNh3cuH93Ty0C9AXKebGY+cdF3R0DtPzIQlo=", "TuREKfA8EVQiYWsPx8veUzjN2cz/b72limSLWlrCWxw=", "vEqqKbpZf0EM6EApMUaUH65r3Zr81Y/DSODhE4H7U3Y=" }, - { "+D6RyLEaHJ9YF9WDyOlwh87KaNJcc6lqX8Arp6yqHF0=", "EpecjfIo1/EEbmsgUtzEDqLu2ut+SMmzqaBL9Z/MlCA=", "oYfO6/7XQgEYT9zmr4sqFrk0muK/fEv3FfD8MzZzjkE=" }, - { "OCmW5KQql2PRMJnsMYQjXlr6TSYUbxJBknqZtXJPSHM=", "ZZR2ghHlCwAJu/XlsEZuNS6XiGPwuXzyMPPywYFapVM=", "fqSCXq+pKJJ6yNvlOi+tyQ9E4Y6kc4kblGrVqN2WuXA=" }, - { "APWXDAe8d2ia1CUbf/IzSPXOUjR8TVuJgmISiWw0/EY=", "jrT5P5YCkG+U7cfNTvCKy0GSEgsjwmJtHg+8HBP6ZCA=", "t75aUjZXMPir8Ao0yhVClh9/BdWxSL+11CjK3iELNWk=" }, - { "8Nw4sRis7M/6Om+3w5YHXthyMzLGuP48teqdzbHNPlA=", "lj3q3ZYij3ZJ/QunK8n9I00cv/Z+O1TU1kFFl8x3DTE=", "adqB79P7gbXEYYnSd1/UPCwFffTAPXa9kHWynRBYcGo=" }, - { "yOupps5XbjV0fIZKnGhrpcxB7yDQzbBILC0UMJyVS1c=", "+MDV/t9UCIdgm3IkH3BZlxaRPJ3lejRmrm4UPApq4mk=", "AOJPmQxsU6hjOd+9mHnF0VL7Afih3P1Fr625xFT4FtY=" }, - { "cD2DEl4MBwONuTV0db5XreoVjQAUZFNXqIeFEU3KFkE=", "2CeHrjN7tBX48k4Sgv5fIHG06e57q/ucCL+8DIRmfXw=", "3EUo6MRzs6rSoY/7AFs8wiBiTXPcHzerLh6Xp3aMGKo=" }, - { "EA+S3a9ZeOLiRbhTxaT2wkpyDheAmai+UJa6SFGzSm8=", "GGByUKZx/FPa2OkJoqVTHXx+6jrIpIw5rf0rp43MHko=", "BXoDA3yn0JcMV7hHVzEqhlwAORvhToFO1qG00nas92A=" }, - { "eBeJi/imBiV52WEqrwAprUQggqdQmvTTmWtLq8pDDkM=", "zCX26ZTOZHLpq5x5aIUL1XhIVoXJLp/zcXwnmFA3jBo=", "Dm/DCxXWYXEsmQgxAD3KREK2PF0bUSnV5WRAaya8s1I=" }, - { "8C7p+EQO+CnWUSjHVu3PpeWpUIbLy48zpftZu021plM=", "DxpnF/IbKAh6kmWC5Jpj8iw387EDkrvjsjOb9fbTSng=", "bGrk0OshJB+0oQOK0QGKU8+lotnIDz3oeUnMZGienyM=" }, - { "COIez7YcBJiOJCLxxWV5UGLW5/o009YI0aszlD/PiUc=", "eD9USWV37LFIOxlDSHyOmfFqNJFpORRlzEI+HoF/czI=", "n+/ra86gUSF2pNZS51nt2JgrzXnQJl+dWswOq/Ahs94=" }, - { "iBBSTG9VLC+T9+ahNaQ4umZoig8o7w1DaeOw+cD2BGc=", "XnAxqDlvGnQ6aakv8ABGHVj07qVQfk4NChZbstTMBxg=", "7KKSwu/4yWr1UzFmNMGtiaSwdYMhP/HKbrQLlABL4UE=" }, - { "eNmwattflehr9+KsVqTuwt1YaAc5ONkaIaTQt9Gkhn8=", "1NNVvm++YTTGMKyAXfGOCZ4aDDdFFH5Um3vAg4XimDo=", "bXNrnDTP0pBay9ytZe7xpiKoSi12F7WUXqoIeI++Xvo=" }, - { "QJotpmZINx9eptKpkh9j3JlEDcHdWnjEbicdBS7gPXM=", "3gLYKeoruVZ/AYjym0gciDvRHj45UIWyHhNjWj2Wj28=", "NwuUkkE5yOWT7wed7bltgAk71miz3cSooiIDAdv6kKw=" }, - { "OAYGuxH70OPQvhVIX4BhSCWUyzAI5H2IkYxKgC/AO0M=", "Rj9iNF/FagkXfdLPqc9LHfaoGR8GlvY3gun2FilE508=", "hkNXLVMlBRsMEaQKkSzevcEK2sMu0AShGKQJMNqdzWM=" }, - { "uBrgZ7wLHrOV/0dNiEqo7FjY9VnJqL5eUDHJWAc9QXg=", "3Hnln8ZHfSaK4OzESJe5U6NcLaW56wzfZICzvzefnSo=", "DhXsehe5FAmbUidXT5ZpZIAuu1eF9rkU6cF3FBoKwOE=" }, - { "sJknn3CHvx/812EWU3ddLdLLZFBKsc+wx35GXyiRsHY=", "qqa2dNSt0jWozGyqpokP392H5/DOAUUZmUpyZDaUEEE=", "1Dyz8CvmF17oKT/wG2fu3vRzPzgQv8/OY9GJYew4FG8=" }, - { "yOumS9HN68ZwIm+5hZol3jFQ0DB4SKuW/ld3y8wioGk=", "6PowsbKj/fKSzXZMAfaSkP3fE+4AThL9xm6ysQzMDxg=", "vF8cKu9X9FxgCjyVZ5RG7nuue8RelF5Qsb8Efme4M4A=" }, - { "mISm5vQfPdK72SsaHh6O1/ARvaWCtm+KZNcpTsyt500=", "YCORDQDpb1U8vADdstBgXkg0N7QaAc5VoXJ4QFuA/UY=", "JlrBmfaCgbfEVD9YQq3c03WwwsHWc1nBwp1JkFORC3A=" }, - { "cPyu3Qry6qbsiOJKFGRziZ9LJWJ47k3ZSXiGkQXuQm0=", "/cmBZTbqEp8sababPAxGb3OvDAEE7MlwPOwEFHE+7yM=", "lp0Hhc/rVtpT5FtLLccChqDl3El48XtP6Wm6JwjI7jo=" }, - { "YKsMYU0SINbPwWw4RDCJV6GnzDlSp1ZNwUw2euGWi0A=", "/KmBReATQbFnLg8YKV0jwhqKeishRoWvlVtMX3550Vk=", "7fXpPSMo1Fw2sOXtjTtvFU+DbZvS/FWB9wAsywWx6R4=" }, - { "WD0YI3y71eIp/GXw9i+7scEiQKSBkGihZWE+s6fGmWo=", "RdthAL/qPnAZFb3xBgRMiAtGHNjgokzoKX9iO2K5qhc=", "4dk4HGkT9dBmomGNorDE/hLr/HEFhljtl4zz3M4sG58=" }, - { "oD8KWhJYZVhutJRb0kZlZnB22QUXzi2FfPRD0ll65UM=", "MYTBGHh4Ukj97pKj6qcfWmxGNQzmU3/aBOX2f1tfhG0=", "VT1gC+a9nRJzYMi/TPvRVnn3IQlaop/jKmmxZePEME0=" }, - { "0Ns/1SOiqR2CpHRG03QNzJJd5gxTm1XJmSkFlugjQ3k=", "KvQAI+ekNOa2xfEvfyc9JGcS+CTUrnnhsKrlyJGJixg=", "J8LmSX6zElX3S9q4PNvh2NKUtAiQ3oHiYjSJ7yErPlY=" }, - { "mD6TeF4ezSPXN/csN1OhoAREFSXllI+zl4DUOInVq2Q=", "WmLJ9ep2EqFcSftnYFJsmWyUxqL0zzuSzVEv94PcISM=", "U2+ILy2NDmmfgSW78C8dl8GyHESUc1lXPHPpg5F+gr8=" }, - { "SMJoXOYgHz8HSzY+ByeWLcSP5qFwv7YjRe0bcKesRnM=", "DEsNSOY3TEs9J2YgqroQ4xKq8T8xNJQjvvE4UrTItQw=", "Bws1Hk2+lO+JQ7ME16EbwAdsBkWsGvti0Gb6LY2Lrms=" }, - { "iGhXF0Hg0tqZmpwAMiolxvbvTPClQ7LlBAspSSyFEHE=", "7Xxzpwl7yRWehHNWTYVtFkdChJdXhtY4Mtw1fA9QcCg=", "Swjfv0PjuaE8Oq3a17BVno5I+q49dZlPwKK1bPUoKNI=" }, - { "MIazjx3qTi6Qz3WzhtCPw3i4Q2uZBHcuMoh++ZGFYUk=", "oni8pbFqk9Ya+Fx+911Nl1SN0FD/hR1jwb2RH3t/pRk=", "ZYAFcj67LkbNURYbSnCCWGxAG8QLDGWwbl968mA6ZA4=" }, - { "MAadYdiFM2cPuJF19q20Yoo5KJabuR9TUQ9jG5nvA1w=", "5OcE8XV+UPoBVbgqBQdVF62GZCW9DOQEdxrQsktPPBA=", "FCZsEFXouy+xtxv8X7VroXtvPG1Z1HFHL724tz1jcUI=" }, - { "+GwxMmD2dee5+QmvXNI0NdP+rNWoSXTN42otbp0aZ24=", "Y0N44baz9ihclCUnv6rRbDqCYu4BxQlBfNnTz3NNe2A=", "/LqSgkVQNkQ/oBiZSgpM9Rw7BJv0RvRpEQpvlizvHy0=" }, - { "8FREpCtncOcT7+W2nW4aYSjmSbADtVSH9rIliQZZUH4=", "fTNSd0JeREhXmPfjrmrAu6Lu/yHkB9GyxR3SyO4kZ28=", "262KN/iG/iJEaZeerFm1yVtvhFVGgQFwSvtxTcjZzeg=" }, - { "EDhaRQGtscjoSE9wJOnSXoQVtVruIqyzknty+x/vDWo=", "eMmMgws6ZxDIxZ6QSwGjZO1Mx/r5T+fJjSTKGMBk/BU=", "0CyaJV6AG9bZ0C4yeZ/RDsOs9BdNqZpUxAsD30WmJO4=" }, - { "CJV0UB2YdvVDG1cs4oiJgHAS+f1FocGr/vGCfiovsWQ=", "9/O9GWZEOXVm7On8lftL27PffRORju8OKl6gZd/74CA=", "A+kXRVNOwIrA5DUa+3v7dpRC+Gbxm23LTiYmOUAXUyY=" }, - { "gCjDsJUwZGA7BjYVoCQsvdIgN9Q4lBHlSyKwUrl751A=", "HRwS8T9y2qPYk7JVU/8Y+6cS+Bk8XCLCXxwN/ttbQiI=", "iFotjA6rhUfkDv4S/wspJgEWunEmrlGSGsXcJ0+8laQ=" }, - { "6N5pL4gsuK+shHpDxirTnAGdyKXIlYHyfIhtB0njJGA=", "CVZvW7NaN2XMEEKHodghBA9hLCwee/jrmttiWh/CmEg=", "OpPEd3Sp8r6KdjNDTN4bVHETlGJ92BCK74FCdEaDe9g=" }, - { "UIPPTUdvhlg8qEDv6JRxM4/8F5ORjJz4ud82QZrgeEY=", "7Nd13z5EpB3ChytvQC1CxvDY7n0H8r2Y7lzLEY8hdEk=", "b22PvgU0M2QfNC7ZGN+RXNe5fjOzMsY32IcHTwLNIqw=" }, - { "oBn53Q5fmxKX02PgI6F47Rb+XoLeFQO07ok2tYhk0lE=", "e0gtPDKXCZSoNW1uHqBPQXLfiYgyeqPMU2zZJgPXACI=", "wmjW2wDT2EzFkyaGui7YWNLTRu8Q4eD/GVKM2utZkEs=" }, - }; - gs_unref_ptrarray GPtrArray *allowed_ips_keep_alive = NULL; - gs_unref_array GArray *peers = NULL; - NMPlatformLnkWireGuard lnk_wireguard; - int r; - guint i; - - allowed_ips_keep_alive = g_ptr_array_new_with_free_func (g_free); - - peers = g_array_new (FALSE, TRUE, sizeof (NMPWireGuardPeer)); - - lnk_wireguard = (NMPlatformLnkWireGuard) { - .listen_port = 50754, - .fwmark = 0x1102, - }; - _copy_base64 (lnk_wireguard.private_key, sizeof (lnk_wireguard.private_key), self_key.pri); - _copy_base64 (lnk_wireguard.public_key, sizeof (lnk_wireguard.public_key), self_key.pub); - - if (test_mode == 0) { - /* no peers. */ - } else if (NM_IN_SET (test_mode, 1, 2)) { - guint num_peers = (test_mode == 1) ? 1 : G_N_ELEMENTS (keys); - - for (i = 0; i < num_peers; i++) { - NMPWireGuardPeer peer; - char s_addr[NM_UTILS_INET_ADDRSTRLEN]; - NMSockAddrUnion endpoint; - guint i_allowed_ips, n_allowed_ips; - NMPWireGuardAllowedIP *allowed_ips; - - if ((i % 2) == 1) { - endpoint = (NMSockAddrUnion) { - .in = { - .sin_family = AF_INET, - .sin_addr.s_addr = nmtst_inet4_from_string (nm_sprintf_buf (s_addr, "192.168.7.%d", i)), - .sin_port = htons (14000 + i), - }, - }; - } else { - endpoint = (NMSockAddrUnion) { - .in6 = { - .sin6_family = AF_INET6, - .sin6_addr = *nmtst_inet6_from_string (nm_sprintf_buf (s_addr, "a:b:c:e::1:%d", i)), - .sin6_port = htons (16000 + i), - }, - }; - } - - if (test_mode == 1) - n_allowed_ips = 1; - else - n_allowed_ips = i % 10; - allowed_ips = g_new0 (NMPWireGuardAllowedIP, n_allowed_ips); - g_ptr_array_add (allowed_ips_keep_alive, allowed_ips); - for (i_allowed_ips = 0; i_allowed_ips < n_allowed_ips; i_allowed_ips++) { - NMPWireGuardAllowedIP *aip = &allowed_ips[i_allowed_ips]; - - aip->family = (i_allowed_ips % 2) ? AF_INET : AF_INET6; - if (aip->family == AF_INET) { - aip->addr.addr4 = nmtst_inet4_from_string (nm_sprintf_buf (s_addr, "10.%u.%u.0", i, i_allowed_ips)); - aip->mask = 32 - (i_allowed_ips % 8); - } else { - aip->addr.addr6 = *nmtst_inet6_from_string (nm_sprintf_buf (s_addr, "a:d:f:%02x:%02x::", i, i_allowed_ips)); - aip->mask = 128 - (i_allowed_ips % 10); - } - } - - peer = (NMPWireGuardPeer) { - .persistent_keepalive_interval = 60+i, - .endpoint = endpoint, - .allowed_ips = n_allowed_ips > 0 ? allowed_ips : NULL, - .allowed_ips_len = n_allowed_ips, - }; - _copy_base64 (peer.public_key, sizeof (peer.public_key), keys[i].pub); - _copy_base64 (peer.preshared_key, sizeof (peer.preshared_key), (i % 3) ? NULL : keys[i].pre); - - g_array_append_val (peers, peer); - } - } else - g_assert_not_reached (); - - r = nm_platform_link_wireguard_change (platform, - ifindex, - &lnk_wireguard, - (const NMPWireGuardPeer *) peers->data, - NULL, - peers->len, - NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY - | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT - | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK - | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS); - g_assert (NMTST_NM_ERR_SUCCESS (r)); + const KeyPair self_key = {"yOWEsaXFxX9/DOkQPzqB9RufZOpfSP4LZZCErP0N0Xo=", + "s6pVT2xPwktor9O5bVOSzcPqBu9uzQOUzPQHXLU2jmk="}; + const KeyPair keys[100] = { + {"+BDHMh11bkheGfvlQpqt8P/H7N1sPXtVi05XraZS0E8=", + "QItu7PJadBVXFXGv55CMtVnbRHdrI6E2CGlu2N5oGx4=", + "2IvZnKTzbF1UlChznWSsEYtGbPjhYSTT41GXO6zLxvk="}, + {"qGZyV2BO1nyY/FGYd6elBPirwJC9QyZwqbm2OJAgLkY=", + "v8L1FEitO0xo+wW/CVVUnALlw0zGveApSFdlITi/5lI=", + "/R2c0JmBNGJzT594NQ0mBJ2XJjxt2QUSo+ZiqeY0EQA="}, + {"YDgsIb0oe+9NcxIx2r0HEEPQpRMxmRN0ALoLm9Sh40Q=", + "nFPs1HaU7uFBvE9xZCMF8oOAjzLpZ49AzDHOluY1O2E=", + "zsYED2Ef7zIHJoRBPcen+w4ktrRsLPEfYwZhWIuXfds="}, + {"kHkosM503LWu43tdYXbNwVOpRrtPgd9XFqcN7k4t6G4=", + "b8e092WT+eNmnxCr5WE2QC/MXAjDagfG1g03cs2mBC0=", + "VXz0ShGWT7H0CBCg2awfatmOJF15ZtaSMPhMsp+hc3A="}, + {"4C2w5CEnxH59Y2aa6CJXgLdDtWoNMS2UJounRCM1Jkk=", + "gC/R9umlnEQL+Qsz/Y64AlsdMge4ECe5/u/JHZCMWSs=", + "2bmL5ISr+V5a7l7xFJ695BLIJyBgx8xnxzybkxiRHOg="}, + {"KHJSzFGkXcZf/wbH2rr99SYtGKWbL680wA2AcDE94lo=", + "BsN23h4aOi458Q3EgMQsodsWQxd9h/RxqskAUpsXfgg=", + "nK4Zv34YKEhjuexhq1SgK4oTd4MZJT5gcpYvEuPjc7Q="}, + {"QGMulXJ9e3AVxtpi8+UUVqPOr/YBWvCNFVsWS9IUnUA=", + "kjVclP5Ifi6og2BBCEHKS/aa/WktArB4+ig06lYaVlg=", + "0+mmceDPcSRK3vFnYqHd9iAfY+Nyjzf/1KgDeYGlRkQ="}, + {"AOJiDD4y6GA7P7gugjjQG9Cctvc5Y27fajHz6aU3gU4=", + "gEnHn6euHtcMEwZBlX6HANPeN9Of+voBDtltS38xDUw=", + "wIH1OxgX6GLxx/bnR+t3fbmjGZDTU3WMxp7t1XGezqM="}, + {"COsls2BlCltaIrrq1+FU51cWddlmoPPppSeIDunOxGA=", + "+n6WuV8Tb1/iZArTrHsyNqkRHABbavBQt9Me72K2KEc=", + "t4baiprSO9ZbKD2/RutOY9cr+yCajQWZGCTnQdrFQj0="}, + {"uHawQq2BRyJlsTPoCa+MfBVnv4MwtRoS+S9FEpFOEVg=", + "8lcmr27afeb6iI3BQCaDtvalF2Cl7gxRZgs+nyJ/fEg=", + "Eh9o/6W60iujBLIHuRfNrPhOWAn7PambT2JRln9iwA0="}, + {"yL7hmoE/JfRGAotRzx9xOpjfrDA3BFlPEemFiQw40Wk=", + "BHK0PHi5kp7rOfQ46oc9xlVpB+pZeZYXTtH7EXr5TwU=", + "BS2h2ZZyW0BlYMmLR29xyHEcZ4jtO7rgj1jkz/EEaxU="}, + {"ON8YrTHQgoC5e0mAR9FakZ8hZ/9I7ysuE21sG546J1Y=", + "Bm3l5I6iH1tDrv6EgdZU9PzHqp0H26Z6ggmmIypwxy8=", + "qKVfbCnK1EI3eC28SsL+jyBnEnIF/nRJQJzDevBFdNQ="}, + {"KGLO0RI0VlQFCG+ETUqk25HdaKUnUPXKOKkTh/w8BXU=", + "sBDBwQFC7k8UMdMzuavKBkBjYYKigzvYmGF5rm6muQc=", + "BNfZF9d7540pUGGOQCh3iDxAZcPBqX4qqM00GSLPBek="}, + {"KGdWyEodIn7KKI2e4EFK9tT6Bt3bNMFBRFVTKjjJm2E=", + "lrbjU/Xn9wDCZQiU8E5fY6igTSozghvo47QeVIIWaUk=", + "LczqW48MW8qDQIZYRELsz/VCzVDc5niROvk7OqrTxR0="}, + {"wO3xinUGABgEmX+RJZbBbOtAmBuPPFG6oVdimvoo90w=", + "dCIvTzR6EerOOsRKnWly1a9WGzbJ4qc+6t3SSzLgWFk=", + "wFj0zpr5PadBoBy0couLuZ1qudZbXLbV/j3UT+AyKeo="}, + {"+JNOBlO4tp9vvQk6UO4r3sILyEgjl+BBoWketZufyn0=", + "Q6LSv9y7YQkJEzQ/1mpjJEgOrO8GYPUTgcizjh7Cm34=", + "kg7AG9MuN04xPJ5Z0IcNZ4a8d1b/n4GsGIeyA4FaaSE="}, + {"+EJcThLRwjZ+h1CNNFu15HWzznf4u/lPVw8hifTm2Ec=", + "Kkn2jFqwBzyIFQfD0OpmePFSmBYmhKagv4pGgkqsWgE=", + "jYpxojj8WKYe/XIXMP+uv1Fv0+TKrs83tqfzP0AGdcI="}, + {"+DKFqSMNFmxriEFj3qatuzYeTJ9+xWYspZ4ydL3eC0Q=", + "3o37bsg6HhRg/M9+fTlLcFYc2w/Bz9rLQySvvYCKbRE=", + "Jb9qoDIBat1EexlgfpRbXa7OflptME8/zt93bldkiVE="}, + {"EH3MjFOMqRoDFQz+hSlJpntWBeH3lTk6WPjTIQjr42o=", + "PbPewED/nxSBLdM7AXMj7uS3bCgAAg8M6F4iPLd0b1U=", + "pj4+UgOGkpJwlRvX5BRXZzmzAUnDtUtJsS7LzbcJWzw="}, + {"kL6M2KvO+vPBLEc/a0DpEHTibQ1bwaMRT9b9SkzeP0Y=", + "pS3G2bHHlkOE6UHP0qVitDuxXgjEaZTviTjNc55RbVs=", + "ZVZpWOtYqhX3CpF1kATg/38J6pvUJo8AS1sVYjs3rUE="}, + {"sFlcRLDn36fnew2Ld92IHJwnKifdS3aF1MWRPs6K3Wg=", + "OpjUOTiWExaDYULTINB4yQFqc3mnU3RjQzGRV+KtdFY=", + "of0V/uoFRNljv/XTt/tXgoquLRH93Ty0KNiaPUpEi2w="}, + {"UJ8hjDsg3jfsnnfPH8Gw9FnCb6taTuviurAfZu+kEFg=", + "3byjHksUOv8CNjGGKvHvvrJDURBhCIL5UtfZbgyVWCE=", + "9f7dbWif51gGrE7R9LeuewQSrvGFGTOB3ceJC67jSkI="}, + {"iFFPKGIfqeUKY/w72KAZSjd/PGTqCakHYBV10xMDfnI=", + "ehneHATNSXtsJTOiPjVSc0QARkihgcfcvoXKFWKfQnI=", + "yKdqDBcRwA7RCg4GiY/b5IsWcExPleOBde/hjxc36a4="}, + {"GDGocdPJTPUAllxQo7SpXZKqMPn7lpxQELQUX9ETHmE=", + "n0ScNEou4ekfrXRRXvcADLu2Afj8g5D3TuDP/I4KrnY=", + "8QhswqAhi/ehhcmCwQF5aSh80TvIGC/gRL5jBn5wOH8="}, + {"UCcrlN8fX2ZdNdhaEBNwktwL+H0ZO7fhaj7rgdUutmw=", + "LF8J728ilXs4TphnrgR6r0p7W3912DYnsXkGMEPQnRE=", + "cYfMjxl2REYir7frGeB0u+NHAaFYF02ysgpBhOL5ygc="}, + {"SH0657XuIiHidVmViXZF30RUWtkuWXcWWHmKZHTiOG8=", + "7k6j49W1u5qgLE5MQUc1osPVW1oPPhzjrGvJ7o9YamY=", + "dV2+7rNk/3LR2IcwYg/c+Wvzep1yjY7/u1I+nnlTQ00="}, + {"qFQWs6jzrscV42pGISQyA7JDvFFAvEQCWJi584VHD2g=", + "AT63nHKLC17yUvkR4lOVPxCr4DD3QhXmcmecOTn+Amc=", + "2Qe2fwJbFcu1CmKpktElOFkSQMqlyvlV3ZUIAd/Dcts="}, + {"6J+yLxgPwWtUbk9I3zbeD8RuK6XkQjJ0wTJ1zSVhflQ=", + "NJzMBYyPZjk3eLmgdKaOeWyNER5YZF1mR8Umeiu9f28=", + "pp+4+XHw5ZmHGJ7WbZ1xLYRsnTI17QIbb0bzHzYZrBs="}, + {"KJGoWYNVDUWcEMg+E4tljv1LiWAbdRw2QVapYqdFa1Y=", + "M2SGk9WVnzYNGnT777G/JE8uUsY2f7mszTwlue73UDE=", + "Jg8N7GbhbYB400foFP+OH0v+hCaL1jW61bajSA6EZqc="}, + {"uAgrgppPyIvk8S1CHUmaCaORsgFFfBreB8pxXmbSdXw=", + "dJ22bER4fD3qF2/yIGWQ7SgmZ990sy/SbANjmUMkzws=", + "mKkd0OoAR9sClmD+k3fL9weBsoCy5GQGz9BP0kAQIjc="}, + {"EI3Q8gePNPrtFyoMcv7hOihQgroF/dfjzPn8yvpGPWQ=", + "Y9QhJFeiyuuIZNPU56B6U//ZK+XTTe4EP7h/p3Q+dE8=", + "qBVUYw9rTWaxn55nUd55NpCWtxOUSWLt4WJGusiDS8Q="}, + {"oEQvdRm/yHkx+JvlhHGT5RUFrFEUleKb9DCT55EqZ30=", + "8hsh/UHwWADTHntOJq4dy0o7ahcNAAlo2rDpjzzrVXk=", + "/GF2inW2mPtA26IgFdgOEBbBEerT740wWuP/8NyANdc="}, + {"6OWrGKZKNsgfRezSUw29EnHymcgKyEKvX5/pZQlLmWs=", + "oaJeO6YSS2dodNEf97DvgWrYnFFelG5daEdN84jVVGw=", + "T5wvTdyVxK0LY96kouLjs06oUfhGChfty8OUL1Mddro="}, + {"mPmzQbh2R+r1DC5hSquzKM1SDrxUdfnBPRPJrpqrgkE=", + "BtUHAnYWjDjBI42qBf9dJqezTUikYsF96o6PKEWPrVo=", + "MxU8EMmq+vVHpuK/AkFZrZDF2b+VbSqukZLPbNsCcgo="}, + {"8GVxuoo1Veyr+nqxr5Q4vmsMf5qfiXwSlQ4q3+BU60g=", + "uSOLe/E9/OjIgUOk0NMBHB45E0+q4Rd+IUO2UOxmKlM=", + "+30F+56OE0Sr3wY2clKw4kgE+2XiucMg7xjK6EemXuk="}, + {"qORPKb+qFuU/9TpFbRUupHsqm9iyk9pa6cpik+EVDkg=", + "bMZxxd+Z9I0XA1h9U8JEY+/mRxWGnvbXDZ5Dxz7YzS0=", + "SmkkqOz4OhHuSL6cxuRm9+Mlt50Sfd0sMDFTC78gqOE="}, + {"2Ko3IYhXKcdOMIJGNpASk9saNSZsI64lyJPOoxpQ2kI=", + "xVOc9PxY1VFaZfemmKi+Ei2liHhmeTu+JMa+rS00gnA=", + "+398DlW8kWeI2aRaC4QfcrEjwqPKCohyDeWdaI1wvv0="}, + {"CPioGCVpxnym62nH/QoCt1RiiaaxUcuFjvh5kRhjqHA=", + "W0XxlBLrZgFKhggMvvv6oFf/RJbfs92qv8JK9e+5i2o=", + "bsK2U6CRAUv1uVgYQ7NpqjWWswFIDiDPDEtU1XQygSA="}, + {"AF17siKaeiO85hikYN0IWCMGWqPm1UOoCkXMltJGUVk=", + "B+PFos9aN2S5bLxzGZHljRZj41j3rIx8RWu0vDUzq1w=", + "Qb8d6iDYv3m1h7PE8j0Exl2cSwpHkim/fJ1S4P7MYvY="}, + {"wMFDBTJzx5tDCBhMkrptYJ8w9EeURjc4xeDQpevxAWo=", + "4ec439EXE5WQzvtV9reSX+aMmdq5k7o9Ayt8oQp+RhQ=", + "jwQlvdNH5WtSSU10H+fh/JisOlaBaohDPEp/BYnTt1Q="}, + {"4GaJpIFigNDwd31O84pLIMM/o2qhp0ydlI/ydD/2a2Q=", + "r/LdkCoK5/BPGdq2+XJO8sCRhI+8ULFmg0887V43PAI=", + "Da+3ZZvEJdx4TYFMIDUlbkmytILnSTNxTKX+sQdjMd4="}, + {"gMnojGqCLmMfGp2m31xlKZ/rIV2b8ockw9DPahRyu0c=", + "H6tKCTosnM4BXKqflXrkTdJyNlCIZhQ3ZRxfrvSdrDk=", + "4Z6K3LKIMV89plcjMb9CzSzJl03SWRe/++geBMZcOtY="}, + {"wKCg22aNNoHnDJ0oAKE46FcSSsREW4AaGn5WxCSeXUs=", + "9NDTFC0iPt4HbbWepLHhN5poNTN2fdxJKNadsNT7qzY=", + "GSVTOCnfLpJ1VCOLHaKSjCMv7/OlcnQiP5+5woqkud8="}, + {"oCoykq7pcJcg2X2V5TBRzGwn8hzzHC05WUreuotdznY=", + "DxfwnbMqr5Wn5SAyFolfEmNQT6l84Oq69ngpg6H6Iio=", + "p1RHBuqhuDa1MAQ2lbqmUQFu0CTwYlf73fWZSj9tQhA="}, + {"UO7YVyRUVkcKr7c63VWWV2zj36XD3HyDfLZCqvrZmFc=", + "360lzYtIyHq5lv/QXSCe4bL4G2J1jBXFJ8yS+Ycr7Bc=", + "RRPQ1XWF1HN8Us4dtfn2eemdjgtWm7U8r7mM3y00NOk="}, + {"eCGFYV/NuGP4H552E8Of1xU+3IvZxGyX+p5UFGW8iHI=", + "LqhZ4AS9dQ/MhsQnE5Oy7Q8INXY+P+mrfGY5dtg9SlE=", + "SICfqs8T5wP6IzATDCT4ovamBKPdkZ7JP4Cfsb3izec="}, + {"oI3HBZknoIMMZw1BuYMkTBylt25reX7AbCqtWQv8cno=", + "B7dUgLgvQhi0RGmvaMrmf26WdjEVrhaiBclVkCKd4AA=", + "5O9K9pLXwxFAt5lfMWh4qGbwX1BM7sz0QGYxAnR77dk="}, + {"sBfYn14EFVIS2M/E1aahP7mOmRNbNtyDChDMS1s6aGs=", + "FLYv0ZvzxMkc9A7OzhC4P1ZRu1aKIQd7u6gqfdekC3c=", + "kaYLcNCXnCLgiB8fleMQuboUJsj5u3YAmXL9x3ywV0M="}, + {"qFwZESU/XYZXUtxwrGsFU9qPAFTzjm7EhTS1Q6ajGlM=", + "hraQQaqJCkS2yQXv+ccMOVh9V9a/qgSZJgdMAhrt8ms=", + "72oDfnWOn39gdk/ncw8Lv267I0I+m73SwxrpYojpWYk="}, + {"YHhp6Zf/miuc2QXeI2lTezy0lL0pTv2b+nWNkmjYQWI=", + "UhNO5arLzF0WlZSgNOx7+IjWN+GSxDdQxZRp8uIwsyI=", + "1Q39Nzv2NGI9zWKWMpYLURAMZUg+FP+OboHHzFU8Anc="}, + {"mLBBXKaCJ+7qeBZpS3wxGi/SQ4kLzun+K+QwwdwfJVQ=", + "gIq/nh7NwCJ36MvRnyrWHaRWu8lTmwfN2NvsjVl6SXQ=", + "AahcNR91GDyJBIP+vC8ZuIV8ukqjSGtd8s+cmjVC2Ao="}, + {"OJG4LZlNNngFtAEQdbVVWVm6QAjOOauGcMZGbQrb40M=", + "pFHAC6HaWAOtvTRRVfSHvzG05mp4SJZXKsN/tkSF0kM=", + "IoXT3wIqWNxQhYuHWl12ODq/P7RM9LwaqglhmjKg+0g="}, + {"OOwBFOQNhepiqDf04DehQLh1gpBNOluDF1ia752Yfng=", + "u715uJ/XhdjXjThCTJ9w6zzXnIhp3VCxhtso1wk+oBQ=", + "5x1Ip3Ym0KzDjGhiYjmpeWWr+dgrZlYwfr02GngPOTM="}, + {"eNPFnwkQy1qw+IjFAlrDA6+sIsxbWDlzbNSsBW8R1UA=", + "OaOXaAfPb1MRpWadawFje8YZ0oxJgdCIDIP8c5X+r1U=", + "NtfaRRD0GqujnaQQoNoBbtovgO4dfVwEmEQx/YgnDpw="}, + {"OLdaZItbtxH3mGqItkibIJp7KV27FrQavjhd5zq6s3Q=", + "SLSmAYxkMCGj0DO35cMLkC3NVAqK2VmVFndbOZEdA24=", + "SnBO68XQTDjxYbmYaAeEHgLwD2u4D+BPT86raRuUQZM="}, + {"UBQOEz08izwr4eEK/SnQUpkt+TxCjo6Sya/XOGMLOE0=", + "wQwrwezI9LzKevGsJJCBHDG8noR0yIEtOK5Rig97SSo=", + "DpyS+0d7lrlFWkztsniG2v/j44vcuvWz3sPeghRyb5A="}, + {"mN98iuqUKh67ggUdq9ZIQNZCZM90fgycTVqYKEo+DkY=", + "GYdXVW1jpS0dN1q9zMehubP7LfYqs34kszN0bXQqxxA=", + "AJPIHffB4uvvJJki4xCG0VORVBbF6bc2mZQqUx+idPc="}, + {"OEd/1it8C3o+NOWxDI3DfLMXVBHJQg15N3E8F8d99l8=", + "QL1NcuUkoXxDy7M9VjGslCejcUlnUDHRghFVnr+8fmA=", + "nven9Dicl8U6QXuDO8rRNtjd4NYaa90SU+Gmv435XKY="}, + {"AFMCGDu2oAP68miucsi4fmYX2KeRZnsEGv8tQm8JEng=", + "1sNxvk8uZhFsBUgxOXmuCMjDAgBbjVeWe9oaFk5Osy0=", + "t5iI5XXd56S5q0Y9HC91gzgF9uGjL9FIy6NUaKqkydo="}, + {"CIAwfJghQHHr4YlztN9at6/iWkrEVCGFAxNVuQCuT3I=", + "zpUOF1h17g7RpBzrVlN7oTRz6e+dxcDL8OsAtHwgLC8=", + "kOSwC1p6Uoti9E9Eg7ViPZwCytuvp5Fr5Buw677aogU="}, + {"sC8vrAVBU0zvhWDRfzfySjvopXm2/cTMkTLmioyO3Es=", + "p6H7GWm8NfgyO5OCX/COjvVT4MAnTs9ZUj4uZMK8XHA=", + "9Tzqo57V/h7+6nSNAHSBKdmU7ultlvZbAnNKSRlrLi4="}, + {"eI63gjxCZGnzqZxPEi/ifYphXhxIRI2ZxK8jzqo3mmU=", + "XyNzEuU9x37fxFCnrZH89Krs5/UqGVx5wNkGfQCAYz0=", + "vZ2fTlRPnJQ+q33YdS5p1aweqPGj/kTMc4Uq80FtFjI="}, + {"aNJlGtm79/RS4SQ/PC4YM6LFo9zAqDr2/RjLqk/z/1A=", + "lgZ9akPrABmfHQMlfNFnnpAJzGtcsaU9mUjEYKfzZHc=", + "d0Xt1Bcgphd1HMI0RneA4VdBbMZL1qNGJAvFhb080eA="}, + {"oONSnHirNh3cuH93Ty0C9AXKebGY+cdF3R0DtPzIQlo=", + "TuREKfA8EVQiYWsPx8veUzjN2cz/b72limSLWlrCWxw=", + "vEqqKbpZf0EM6EApMUaUH65r3Zr81Y/DSODhE4H7U3Y="}, + {"+D6RyLEaHJ9YF9WDyOlwh87KaNJcc6lqX8Arp6yqHF0=", + "EpecjfIo1/EEbmsgUtzEDqLu2ut+SMmzqaBL9Z/MlCA=", + "oYfO6/7XQgEYT9zmr4sqFrk0muK/fEv3FfD8MzZzjkE="}, + {"OCmW5KQql2PRMJnsMYQjXlr6TSYUbxJBknqZtXJPSHM=", + "ZZR2ghHlCwAJu/XlsEZuNS6XiGPwuXzyMPPywYFapVM=", + "fqSCXq+pKJJ6yNvlOi+tyQ9E4Y6kc4kblGrVqN2WuXA="}, + {"APWXDAe8d2ia1CUbf/IzSPXOUjR8TVuJgmISiWw0/EY=", + "jrT5P5YCkG+U7cfNTvCKy0GSEgsjwmJtHg+8HBP6ZCA=", + "t75aUjZXMPir8Ao0yhVClh9/BdWxSL+11CjK3iELNWk="}, + {"8Nw4sRis7M/6Om+3w5YHXthyMzLGuP48teqdzbHNPlA=", + "lj3q3ZYij3ZJ/QunK8n9I00cv/Z+O1TU1kFFl8x3DTE=", + "adqB79P7gbXEYYnSd1/UPCwFffTAPXa9kHWynRBYcGo="}, + {"yOupps5XbjV0fIZKnGhrpcxB7yDQzbBILC0UMJyVS1c=", + "+MDV/t9UCIdgm3IkH3BZlxaRPJ3lejRmrm4UPApq4mk=", + "AOJPmQxsU6hjOd+9mHnF0VL7Afih3P1Fr625xFT4FtY="}, + {"cD2DEl4MBwONuTV0db5XreoVjQAUZFNXqIeFEU3KFkE=", + "2CeHrjN7tBX48k4Sgv5fIHG06e57q/ucCL+8DIRmfXw=", + "3EUo6MRzs6rSoY/7AFs8wiBiTXPcHzerLh6Xp3aMGKo="}, + {"EA+S3a9ZeOLiRbhTxaT2wkpyDheAmai+UJa6SFGzSm8=", + "GGByUKZx/FPa2OkJoqVTHXx+6jrIpIw5rf0rp43MHko=", + "BXoDA3yn0JcMV7hHVzEqhlwAORvhToFO1qG00nas92A="}, + {"eBeJi/imBiV52WEqrwAprUQggqdQmvTTmWtLq8pDDkM=", + "zCX26ZTOZHLpq5x5aIUL1XhIVoXJLp/zcXwnmFA3jBo=", + "Dm/DCxXWYXEsmQgxAD3KREK2PF0bUSnV5WRAaya8s1I="}, + {"8C7p+EQO+CnWUSjHVu3PpeWpUIbLy48zpftZu021plM=", + "DxpnF/IbKAh6kmWC5Jpj8iw387EDkrvjsjOb9fbTSng=", + "bGrk0OshJB+0oQOK0QGKU8+lotnIDz3oeUnMZGienyM="}, + {"COIez7YcBJiOJCLxxWV5UGLW5/o009YI0aszlD/PiUc=", + "eD9USWV37LFIOxlDSHyOmfFqNJFpORRlzEI+HoF/czI=", + "n+/ra86gUSF2pNZS51nt2JgrzXnQJl+dWswOq/Ahs94="}, + {"iBBSTG9VLC+T9+ahNaQ4umZoig8o7w1DaeOw+cD2BGc=", + "XnAxqDlvGnQ6aakv8ABGHVj07qVQfk4NChZbstTMBxg=", + "7KKSwu/4yWr1UzFmNMGtiaSwdYMhP/HKbrQLlABL4UE="}, + {"eNmwattflehr9+KsVqTuwt1YaAc5ONkaIaTQt9Gkhn8=", + "1NNVvm++YTTGMKyAXfGOCZ4aDDdFFH5Um3vAg4XimDo=", + "bXNrnDTP0pBay9ytZe7xpiKoSi12F7WUXqoIeI++Xvo="}, + {"QJotpmZINx9eptKpkh9j3JlEDcHdWnjEbicdBS7gPXM=", + "3gLYKeoruVZ/AYjym0gciDvRHj45UIWyHhNjWj2Wj28=", + "NwuUkkE5yOWT7wed7bltgAk71miz3cSooiIDAdv6kKw="}, + {"OAYGuxH70OPQvhVIX4BhSCWUyzAI5H2IkYxKgC/AO0M=", + "Rj9iNF/FagkXfdLPqc9LHfaoGR8GlvY3gun2FilE508=", + "hkNXLVMlBRsMEaQKkSzevcEK2sMu0AShGKQJMNqdzWM="}, + {"uBrgZ7wLHrOV/0dNiEqo7FjY9VnJqL5eUDHJWAc9QXg=", + "3Hnln8ZHfSaK4OzESJe5U6NcLaW56wzfZICzvzefnSo=", + "DhXsehe5FAmbUidXT5ZpZIAuu1eF9rkU6cF3FBoKwOE="}, + {"sJknn3CHvx/812EWU3ddLdLLZFBKsc+wx35GXyiRsHY=", + "qqa2dNSt0jWozGyqpokP392H5/DOAUUZmUpyZDaUEEE=", + "1Dyz8CvmF17oKT/wG2fu3vRzPzgQv8/OY9GJYew4FG8="}, + {"yOumS9HN68ZwIm+5hZol3jFQ0DB4SKuW/ld3y8wioGk=", + "6PowsbKj/fKSzXZMAfaSkP3fE+4AThL9xm6ysQzMDxg=", + "vF8cKu9X9FxgCjyVZ5RG7nuue8RelF5Qsb8Efme4M4A="}, + {"mISm5vQfPdK72SsaHh6O1/ARvaWCtm+KZNcpTsyt500=", + "YCORDQDpb1U8vADdstBgXkg0N7QaAc5VoXJ4QFuA/UY=", + "JlrBmfaCgbfEVD9YQq3c03WwwsHWc1nBwp1JkFORC3A="}, + {"cPyu3Qry6qbsiOJKFGRziZ9LJWJ47k3ZSXiGkQXuQm0=", + "/cmBZTbqEp8sababPAxGb3OvDAEE7MlwPOwEFHE+7yM=", + "lp0Hhc/rVtpT5FtLLccChqDl3El48XtP6Wm6JwjI7jo="}, + {"YKsMYU0SINbPwWw4RDCJV6GnzDlSp1ZNwUw2euGWi0A=", + "/KmBReATQbFnLg8YKV0jwhqKeishRoWvlVtMX3550Vk=", + "7fXpPSMo1Fw2sOXtjTtvFU+DbZvS/FWB9wAsywWx6R4="}, + {"WD0YI3y71eIp/GXw9i+7scEiQKSBkGihZWE+s6fGmWo=", + "RdthAL/qPnAZFb3xBgRMiAtGHNjgokzoKX9iO2K5qhc=", + "4dk4HGkT9dBmomGNorDE/hLr/HEFhljtl4zz3M4sG58="}, + {"oD8KWhJYZVhutJRb0kZlZnB22QUXzi2FfPRD0ll65UM=", + "MYTBGHh4Ukj97pKj6qcfWmxGNQzmU3/aBOX2f1tfhG0=", + "VT1gC+a9nRJzYMi/TPvRVnn3IQlaop/jKmmxZePEME0="}, + {"0Ns/1SOiqR2CpHRG03QNzJJd5gxTm1XJmSkFlugjQ3k=", + "KvQAI+ekNOa2xfEvfyc9JGcS+CTUrnnhsKrlyJGJixg=", + "J8LmSX6zElX3S9q4PNvh2NKUtAiQ3oHiYjSJ7yErPlY="}, + {"mD6TeF4ezSPXN/csN1OhoAREFSXllI+zl4DUOInVq2Q=", + "WmLJ9ep2EqFcSftnYFJsmWyUxqL0zzuSzVEv94PcISM=", + "U2+ILy2NDmmfgSW78C8dl8GyHESUc1lXPHPpg5F+gr8="}, + {"SMJoXOYgHz8HSzY+ByeWLcSP5qFwv7YjRe0bcKesRnM=", + "DEsNSOY3TEs9J2YgqroQ4xKq8T8xNJQjvvE4UrTItQw=", + "Bws1Hk2+lO+JQ7ME16EbwAdsBkWsGvti0Gb6LY2Lrms="}, + {"iGhXF0Hg0tqZmpwAMiolxvbvTPClQ7LlBAspSSyFEHE=", + "7Xxzpwl7yRWehHNWTYVtFkdChJdXhtY4Mtw1fA9QcCg=", + "Swjfv0PjuaE8Oq3a17BVno5I+q49dZlPwKK1bPUoKNI="}, + {"MIazjx3qTi6Qz3WzhtCPw3i4Q2uZBHcuMoh++ZGFYUk=", + "oni8pbFqk9Ya+Fx+911Nl1SN0FD/hR1jwb2RH3t/pRk=", + "ZYAFcj67LkbNURYbSnCCWGxAG8QLDGWwbl968mA6ZA4="}, + {"MAadYdiFM2cPuJF19q20Yoo5KJabuR9TUQ9jG5nvA1w=", + "5OcE8XV+UPoBVbgqBQdVF62GZCW9DOQEdxrQsktPPBA=", + "FCZsEFXouy+xtxv8X7VroXtvPG1Z1HFHL724tz1jcUI="}, + {"+GwxMmD2dee5+QmvXNI0NdP+rNWoSXTN42otbp0aZ24=", + "Y0N44baz9ihclCUnv6rRbDqCYu4BxQlBfNnTz3NNe2A=", + "/LqSgkVQNkQ/oBiZSgpM9Rw7BJv0RvRpEQpvlizvHy0="}, + {"8FREpCtncOcT7+W2nW4aYSjmSbADtVSH9rIliQZZUH4=", + "fTNSd0JeREhXmPfjrmrAu6Lu/yHkB9GyxR3SyO4kZ28=", + "262KN/iG/iJEaZeerFm1yVtvhFVGgQFwSvtxTcjZzeg="}, + {"EDhaRQGtscjoSE9wJOnSXoQVtVruIqyzknty+x/vDWo=", + "eMmMgws6ZxDIxZ6QSwGjZO1Mx/r5T+fJjSTKGMBk/BU=", + "0CyaJV6AG9bZ0C4yeZ/RDsOs9BdNqZpUxAsD30WmJO4="}, + {"CJV0UB2YdvVDG1cs4oiJgHAS+f1FocGr/vGCfiovsWQ=", + "9/O9GWZEOXVm7On8lftL27PffRORju8OKl6gZd/74CA=", + "A+kXRVNOwIrA5DUa+3v7dpRC+Gbxm23LTiYmOUAXUyY="}, + {"gCjDsJUwZGA7BjYVoCQsvdIgN9Q4lBHlSyKwUrl751A=", + "HRwS8T9y2qPYk7JVU/8Y+6cS+Bk8XCLCXxwN/ttbQiI=", + "iFotjA6rhUfkDv4S/wspJgEWunEmrlGSGsXcJ0+8laQ="}, + {"6N5pL4gsuK+shHpDxirTnAGdyKXIlYHyfIhtB0njJGA=", + "CVZvW7NaN2XMEEKHodghBA9hLCwee/jrmttiWh/CmEg=", + "OpPEd3Sp8r6KdjNDTN4bVHETlGJ92BCK74FCdEaDe9g="}, + {"UIPPTUdvhlg8qEDv6JRxM4/8F5ORjJz4ud82QZrgeEY=", + "7Nd13z5EpB3ChytvQC1CxvDY7n0H8r2Y7lzLEY8hdEk=", + "b22PvgU0M2QfNC7ZGN+RXNe5fjOzMsY32IcHTwLNIqw="}, + {"oBn53Q5fmxKX02PgI6F47Rb+XoLeFQO07ok2tYhk0lE=", + "e0gtPDKXCZSoNW1uHqBPQXLfiYgyeqPMU2zZJgPXACI=", + "wmjW2wDT2EzFkyaGui7YWNLTRu8Q4eD/GVKM2utZkEs="}, + }; + gs_unref_ptrarray GPtrArray *allowed_ips_keep_alive = NULL; + gs_unref_array GArray *peers = NULL; + NMPlatformLnkWireGuard lnk_wireguard; + int r; + guint i; + + allowed_ips_keep_alive = g_ptr_array_new_with_free_func(g_free); + + peers = g_array_new(FALSE, TRUE, sizeof(NMPWireGuardPeer)); + + lnk_wireguard = (NMPlatformLnkWireGuard){ + .listen_port = 50754, + .fwmark = 0x1102, + }; + _copy_base64(lnk_wireguard.private_key, sizeof(lnk_wireguard.private_key), self_key.pri); + _copy_base64(lnk_wireguard.public_key, sizeof(lnk_wireguard.public_key), self_key.pub); + + if (test_mode == 0) { + /* no peers. */ + } else if (NM_IN_SET(test_mode, 1, 2)) { + guint num_peers = (test_mode == 1) ? 1 : G_N_ELEMENTS(keys); + + for (i = 0; i < num_peers; i++) { + NMPWireGuardPeer peer; + char s_addr[NM_UTILS_INET_ADDRSTRLEN]; + NMSockAddrUnion endpoint; + guint i_allowed_ips, n_allowed_ips; + NMPWireGuardAllowedIP *allowed_ips; + + if ((i % 2) == 1) { + endpoint = (NMSockAddrUnion){ + .in = + { + .sin_family = AF_INET, + .sin_addr.s_addr = + nmtst_inet4_from_string(nm_sprintf_buf(s_addr, "192.168.7.%d", i)), + .sin_port = htons(14000 + i), + }, + }; + } else { + endpoint = (NMSockAddrUnion){ + .in6 = + { + .sin6_family = AF_INET6, + .sin6_addr = *nmtst_inet6_from_string( + nm_sprintf_buf(s_addr, "a:b:c:e::1:%d", i)), + .sin6_port = htons(16000 + i), + }, + }; + } + + if (test_mode == 1) + n_allowed_ips = 1; + else + n_allowed_ips = i % 10; + allowed_ips = g_new0(NMPWireGuardAllowedIP, n_allowed_ips); + g_ptr_array_add(allowed_ips_keep_alive, allowed_ips); + for (i_allowed_ips = 0; i_allowed_ips < n_allowed_ips; i_allowed_ips++) { + NMPWireGuardAllowedIP *aip = &allowed_ips[i_allowed_ips]; + + aip->family = (i_allowed_ips % 2) ? AF_INET : AF_INET6; + if (aip->family == AF_INET) { + aip->addr.addr4 = nmtst_inet4_from_string( + nm_sprintf_buf(s_addr, "10.%u.%u.0", i, i_allowed_ips)); + aip->mask = 32 - (i_allowed_ips % 8); + } else { + aip->addr.addr6 = *nmtst_inet6_from_string( + nm_sprintf_buf(s_addr, "a:d:f:%02x:%02x::", i, i_allowed_ips)); + aip->mask = 128 - (i_allowed_ips % 10); + } + } + + peer = (NMPWireGuardPeer){ + .persistent_keepalive_interval = 60 + i, + .endpoint = endpoint, + .allowed_ips = n_allowed_ips > 0 ? allowed_ips : NULL, + .allowed_ips_len = n_allowed_ips, + }; + _copy_base64(peer.public_key, sizeof(peer.public_key), keys[i].pub); + _copy_base64(peer.preshared_key, + sizeof(peer.preshared_key), + (i % 3) ? NULL : keys[i].pre); + + g_array_append_val(peers, peer); + } + } else + g_assert_not_reached(); + + r = nm_platform_link_wireguard_change(platform, + ifindex, + &lnk_wireguard, + (const NMPWireGuardPeer *) peers->data, + NULL, + peers->len, + NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY + | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT + | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK + | NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS); + g_assert(NMTST_NM_ERR_SUCCESS(r)); } /*****************************************************************************/ typedef struct { - NMLinkType link_type; - int test_mode; - gboolean external_command; + NMLinkType link_type; + int test_mode; + gboolean external_command; } TestAddSoftwareDetectData; static void -test_software_detect (gconstpointer user_data) +test_software_detect(gconstpointer user_data) { - const TestAddSoftwareDetectData *test_data = user_data; - int ifindex, ifindex_parent; - const NMPlatformLink *plink; - const NMPObject *lnk; - int r; - guint i_step; - const gboolean ext = test_data->external_command; - NMPlatformLnkTun lnk_tun; - NMPlatformLnkGre lnk_gre = { }; - nm_auto_close int tun_fd = -1; - - nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME); - ifindex_parent = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; - - switch (test_data->link_type) { - case NM_LINK_TYPE_GRE: { - gboolean gracefully_skip = FALSE; - - lnk_gre.local = nmtst_inet4_from_string ("192.168.233.204"); - lnk_gre.remote = nmtst_inet4_from_string ("172.168.10.25"); - lnk_gre.parent_ifindex = ifindex_parent; - lnk_gre.ttl = 174; - lnk_gre.tos = 37; - lnk_gre.path_mtu_discovery = TRUE; - - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "gre0")) { - /* Seems that the ip_gre module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip_gre", NULL) != 0; - } - - if (!nmtstp_link_gre_add (NULL, ext, DEVICE_NAME, &lnk_gre)) { - if (gracefully_skip) { - g_test_skip ("Cannot create gre tunnel because of missing ip_gre module (modprobe ip_gre)"); - goto out_delete_parent; - } - g_error ("Failed adding GRE tunnel"); - } - break; - } - case NM_LINK_TYPE_GRETAP: { - gboolean gracefully_skip = FALSE; - - lnk_gre.local = nmtst_inet4_from_string ("192.168.1.133"); - lnk_gre.remote = nmtst_inet4_from_string ("172.168.101.2"); - lnk_gre.parent_ifindex = ifindex_parent; - lnk_gre.ttl = 39; - lnk_gre.tos = 12; - lnk_gre.path_mtu_discovery = FALSE; - lnk_gre.is_tap = TRUE; - - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "gretap0")) { - /* Seems that the ip_gre module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip_gre", NULL) != 0; - } - - if (!nmtstp_link_gre_add (NULL, ext, DEVICE_NAME, &lnk_gre)) { - if (gracefully_skip) { - g_test_skip ("Cannot create gretap tunnel because of missing ip_gre module (modprobe ip_gre)"); - goto out_delete_parent; - } - g_error ("Failed adding GRETAP tunnel"); - } - break; - } - case NM_LINK_TYPE_IPIP: { - NMPlatformLnkIpIp lnk_ipip = { }; - gboolean gracefully_skip = FALSE; - - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "tunl0")) { - /* Seems that the ipip module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ipip", NULL) != 0; - } - - lnk_ipip.local = nmtst_inet4_from_string ("1.2.3.4"); - lnk_ipip.remote = nmtst_inet4_from_string ("5.6.7.8"); - lnk_ipip.parent_ifindex = ifindex_parent; - lnk_ipip.tos = 32; - lnk_ipip.path_mtu_discovery = FALSE; - - if (!nmtstp_link_ipip_add (NULL, ext, DEVICE_NAME, &lnk_ipip)) { - if (gracefully_skip) { - g_test_skip ("Cannot create ipip tunnel because of missing ipip module (modprobe ipip)"); - goto out_delete_parent; - } - g_error ("Failed adding IPIP tunnel"); - } - break; - } - case NM_LINK_TYPE_IP6TNL: { - NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; - gboolean gracefully_skip = FALSE; - - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "ip6tnl0")) { - /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip6_tunnel", NULL) != 0; - } - - switch (test_data->test_mode) { - case 0: - lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::15"); - lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::16"); - lnk_ip6tnl.parent_ifindex = ifindex_parent; - lnk_ip6tnl.tclass = 20; - lnk_ip6tnl.encap_limit = 6; - lnk_ip6tnl.flow_label = 1337; - lnk_ip6tnl.proto = IPPROTO_IPV6; - break; - case 1: - lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::17"); - lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::18"); - lnk_ip6tnl.parent_ifindex = ifindex_parent; - lnk_ip6tnl.tclass = 0; - lnk_ip6tnl.encap_limit = 0; - lnk_ip6tnl.flow_label = 1338; - lnk_ip6tnl.proto = IPPROTO_IPV6; - lnk_ip6tnl.flags = IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS; - break; - } - - if (!nmtstp_link_ip6tnl_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { - if (gracefully_skip) { - g_test_skip ("Cannot create ip6tnl tunnel because of missing ip6_tunnel module (modprobe ip6_tunnel)"); - goto out_delete_parent; - } - g_error ("Failed adding IP6TNL tunnel"); - } - break; - } - case NM_LINK_TYPE_IP6GRE: { - NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; - gboolean gracefully_skip = FALSE; - - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "ip6gre0")) { - /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip6_gre", NULL) != 0; - } - - lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::42"); - lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::aaaa"); - lnk_ip6tnl.parent_ifindex = ifindex_parent; - lnk_ip6tnl.tclass = 21; - lnk_ip6tnl.flow_label = 1338; - lnk_ip6tnl.is_gre = TRUE; - - if (!nmtstp_link_ip6gre_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { - if (gracefully_skip) { - g_test_skip ("Cannot create ip6gre tunnel because of missing ip6_gre module (modprobe ip6_gre)"); - goto out_delete_parent; - } - g_error ("Failed adding IP6GRE tunnel"); - } - break; - } - case NM_LINK_TYPE_IP6GRETAP: { - NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; - gboolean gracefully_skip = FALSE; - - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "ip6gre0")) { - /* Seems that the ip6_tunnel module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip6_gre", NULL) != 0; - } - - lnk_ip6tnl.local = *nmtst_inet6_from_string ("fe80::abcd"); - lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fc01::bbbb"); - lnk_ip6tnl.parent_ifindex = ifindex_parent; - lnk_ip6tnl.ttl = 10; - lnk_ip6tnl.tclass = 22; - lnk_ip6tnl.flow_label = 1339; - lnk_ip6tnl.is_gre = TRUE; - lnk_ip6tnl.is_tap = TRUE; - - if (!nmtstp_link_ip6gre_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { - if (gracefully_skip) { - g_test_skip ("Cannot create ip6gretap tunnel because of missing ip6_gre module (modprobe ip6_gre)"); - goto out_delete_parent; - } - g_error ("Failed adding IP6GRETAP tunnel"); - } - break; - } - case NM_LINK_TYPE_MACVLAN: { - NMPlatformLnkMacvlan lnk_macvlan = { }; - const NMPlatformLink *dummy; - char buf[256]; - int i; - - lnk_macvlan.mode = MACVLAN_MODE_BRIDGE; - lnk_macvlan.no_promisc = FALSE; - lnk_macvlan.tap = FALSE; - - /* Since in old kernel versions sysfs files for macvtaps are not - * namespaced, the creation can fail if a macvtap in another namespace - * has the same index. Try to detect this situation and skip already - * used indexes. - * The fix (17af2bce) is included kernel 4.7, dated 24 July, 2016. - */ - for (i = ifindex_parent + 1; i < ifindex_parent + 100; i++) { - snprintf (buf, sizeof (buf), "/sys/class/macvtap/tap%d", i); - if (!g_file_test (buf, G_FILE_TEST_IS_SYMLINK)) - break; - - _LOGD ("skipping ifindex %d as already used by a macvtap", i); - - dummy = nmtstp_link_dummy_add (NM_PLATFORM_GET, FALSE, "dummy-tmp"); - g_assert_cmpint (dummy->ifindex, ==, i); - nmtstp_link_delete (NM_PLATFORM_GET, FALSE, dummy->ifindex, NULL, TRUE); - } - - if (!nmtstp_link_macvlan_add (NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvlan)) - g_error ("Failed adding MACVLAN interface"); - break; - } - case NM_LINK_TYPE_MACVTAP: { - NMPlatformLnkMacvlan lnk_macvtap = { }; - - lnk_macvtap.mode = MACVLAN_MODE_PRIVATE; - lnk_macvtap.no_promisc = FALSE; - lnk_macvtap.tap = TRUE; - - if (!nmtstp_link_macvlan_add (NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvtap)) - g_error ("Failed adding MACVTAP interface"); - break; - } - case NM_LINK_TYPE_SIT: { - NMPlatformLnkSit lnk_sit = { }; - gboolean gracefully_skip = FALSE; - - lnk_sit.local = nmtst_inet4_from_string ("192.168.200.1"); - lnk_sit.remote = nmtst_inet4_from_string ("172.25.100.14"); - lnk_sit.parent_ifindex = ifindex_parent; - lnk_sit.ttl = 0; - lnk_sit.tos = 31; - lnk_sit.path_mtu_discovery = FALSE; - - if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "sit0")) { - /* Seems that the sit module is not loaded... try to load it. */ - gracefully_skip = nm_utils_modprobe (NULL, TRUE, "sit", NULL) != 0; - } - - if (!nmtstp_link_sit_add (NULL, ext, DEVICE_NAME, &lnk_sit)) { - if (gracefully_skip) { - g_test_skip ("Cannot create sit tunnel because of missing sit module (modprobe sit)"); - goto out_delete_parent; - } - g_error ("Failed adding SIT tunnel"); - } - break; - } - case NM_LINK_TYPE_VLAN: - nmtstp_run_command_check ("ip link add name %s link %s type vlan id 1242", DEVICE_NAME, PARENT_NAME); - break; - case NM_LINK_TYPE_VRF: { - NMPlatformLnkVrf lnk_vrf = { }; - gboolean not_supported; - - lnk_vrf.table = 9876; - - if (!nmtstp_link_vrf_add (NULL, ext, DEVICE_NAME, &lnk_vrf, ¬_supported)) { - if (not_supported) { - g_test_skip ("Cannot create VRF interface because of missing kernel support"); - goto out_delete_parent; - } - g_error ("Failed adding VRF interface"); - } - break; - } - case NM_LINK_TYPE_VXLAN: { - NMPlatformLnkVxlan lnk_vxlan = { }; - - switch (test_data->test_mode) { - case 0: - lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME); - lnk_vxlan.id = 42; - lnk_vxlan.local = nmtst_inet4_from_string ("23.1.2.164"); - lnk_vxlan.group = nmtst_inet4_from_string ("239.1.2.134"); - lnk_vxlan.dst_port = 4789; - lnk_vxlan.learning = TRUE; - lnk_vxlan.ageing = 1245; - break; - case 1: - lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME); - lnk_vxlan.id = 11214423; - lnk_vxlan.local6 = *nmtst_inet6_from_string ("1:2:3:4:334:23::23"); - lnk_vxlan.group6 = *nmtst_inet6_from_string ("ff0e::115"); - lnk_vxlan.ttl = 32; - lnk_vxlan.dst_port = 57412; - lnk_vxlan.src_port_min = 1000; - lnk_vxlan.src_port_max = 1003; - lnk_vxlan.learning = TRUE; - lnk_vxlan.ageing = 3245; - break; - } - - g_assert (nmtstp_link_vxlan_add (NULL, ext, DEVICE_NAME, &lnk_vxlan)); - break; - } - case NM_LINK_TYPE_TUN: { - gboolean owner_valid = nmtst_get_rand_bool (); - gboolean group_valid = nmtst_get_rand_bool (); - - switch (test_data->test_mode) { - case 0: - lnk_tun = (NMPlatformLnkTun) { - .type = nmtst_get_rand_bool () ? IFF_TUN : IFF_TAP, - .owner = owner_valid ? getuid () : 0, - .owner_valid = owner_valid, - .group = group_valid ? getgid () : 0, - .group_valid = group_valid, - .pi = nmtst_get_rand_bool (), - .vnet_hdr = nmtst_get_rand_bool (), - .multi_queue = nmtst_get_rand_bool (), - - /* if we add the device via iproute2 (external), we can only - * create persistent devices. */ - .persist = (ext == 1) ? TRUE : nmtst_get_rand_bool (), - }; - break; - default: - g_assert_not_reached (); - break; - } - - g_assert (nmtstp_link_tun_add (NULL, ext, DEVICE_NAME, &lnk_tun, - (!lnk_tun.persist || nmtst_get_rand_bool ()) - ? &tun_fd - : NULL)); - break; - } - case NM_LINK_TYPE_WIREGUARD: { - const NMPlatformLink *link; - - r = nm_platform_link_wireguard_add (NM_PLATFORM_GET, DEVICE_NAME, &link); - if (r == -EOPNOTSUPP) { - g_test_skip ("wireguard not supported (modprobe wireguard?)"); - goto out_delete_parent; - } - - g_assert (NMTST_NM_ERR_SUCCESS (r)); - g_assert (NMP_OBJECT_GET_TYPE (NMP_OBJECT_UP_CAST (link)) == NMP_OBJECT_TYPE_LINK); - break; - } - default: - g_assert_not_reached (); - } - - ifindex = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, DEVICE_NAME, test_data->link_type, 100)->ifindex; - - nmtstp_link_set_updown (NULL, -1, ifindex_parent, TRUE); - - for (i_step = 0; i_step < 5; i_step++) { - - _LOGD ("test-software-detect: step %u", i_step); - if (nmtst_is_debug ()) - nmtstp_run_command_check ("ip -d link show %s", DEVICE_NAME); - - if (i_step > 0) { - gboolean set_up = (i_step % 2) == 1; - - if ( test_data->link_type == NM_LINK_TYPE_VXLAN - && set_up) { - /* On RHEL-7, we need to add a tiny sleep here, otherwise, - * upping the vxlan device fails with EADDRINUSE. - * https://bugzilla.redhat.com/show_bug.cgi?id=1277131 */ - g_usleep (1); - } - nmtstp_link_set_updown (NULL, -1, ifindex, set_up); - } - - lnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, test_data->link_type, &plink); - g_assert (plink); - g_assert_cmpint (plink->ifindex, ==, ifindex); - - if ( !lnk - && test_data->link_type == NM_LINK_TYPE_TUN) { - /* this is ok. Kernel apparently does not support tun properties via netlink. We - * fetch them from sysfs below. */ - } else - g_assert (lnk); - - switch (test_data->link_type) { - case NM_LINK_TYPE_GRE: { - const NMPlatformLnkGre *plnk = &lnk->lnk_gre; - - g_assert (plnk == nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL)); - g_assert (nm_platform_lnk_gre_cmp (plnk, &lnk_gre) == 0); - - break; - } - case NM_LINK_TYPE_GRETAP: { - const NMPlatformLnkGre *plnk = &lnk->lnk_gre; - - g_assert (plnk == nm_platform_link_get_lnk_gretap (NM_PLATFORM_GET, ifindex, NULL)); - g_assert (nm_platform_lnk_gre_cmp (plnk, &lnk_gre) == 0); - break; - } - case NM_LINK_TYPE_IP6TNL: { - const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; - - switch (test_data->test_mode) { - case 0: - g_assert (plnk == nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); - nmtst_assert_ip6_address (&plnk->local, "fd01::15"); - nmtst_assert_ip6_address (&plnk->remote, "fd01::16"); - g_assert_cmpint (plnk->ttl, ==, 0); - g_assert_cmpint (plnk->tclass, ==, 20); - g_assert_cmpint (plnk->encap_limit, ==, 6); - g_assert_cmpint (plnk->flow_label, ==, 1337); - g_assert_cmpint (plnk->proto, ==, IPPROTO_IPV6); - break; - case 1: - g_assert (plnk == nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); - nmtst_assert_ip6_address (&plnk->local, "fd01::17"); - nmtst_assert_ip6_address (&plnk->remote, "fd01::18"); - g_assert_cmpint (plnk->ttl, ==, 0); - g_assert_cmpint (plnk->flow_label, ==, 1338); - g_assert_cmpint (plnk->proto, ==, IPPROTO_IPV6); - g_assert_cmpint (plnk->flags & 0xFFFF, /* ignore kernel internal flags */ - ==, - IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS); - break; - } - break; - } - case NM_LINK_TYPE_IP6GRE: { - const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; - - g_assert (plnk == nm_platform_link_get_lnk_ip6gre (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); - nmtst_assert_ip6_address (&plnk->local, "fd01::42"); - nmtst_assert_ip6_address (&plnk->remote, "fd01::aaaa"); - g_assert_cmpint (plnk->tclass, ==, 21); - g_assert_cmpint (plnk->flow_label, ==, 1338); - g_assert_cmpint (plnk->is_gre, ==, TRUE); - g_assert_cmpint (plnk->is_tap, ==, FALSE); - break; - } - case NM_LINK_TYPE_IP6GRETAP: { - const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; - - g_assert (plnk == nm_platform_link_get_lnk_ip6gretap (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); - nmtst_assert_ip6_address (&plnk->local, "fe80::abcd"); - nmtst_assert_ip6_address (&plnk->remote, "fc01::bbbb"); - g_assert_cmpint (plnk->ttl, ==, 10); - g_assert_cmpint (plnk->tclass, ==, 22); - g_assert_cmpint (plnk->flow_label, ==, 1339); - g_assert_cmpint (plnk->is_gre, ==, TRUE); - g_assert_cmpint (plnk->is_tap, ==, TRUE); - break; - } - case NM_LINK_TYPE_IPIP: { - const NMPlatformLnkIpIp *plnk = &lnk->lnk_ipip; - - g_assert (plnk == nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); - nmtst_assert_ip4_address (plnk->local, "1.2.3.4"); - nmtst_assert_ip4_address (plnk->remote, "5.6.7.8"); - g_assert_cmpint (plnk->ttl, ==, 0); - g_assert_cmpint (plnk->tos, ==, 32); - g_assert_cmpint (plnk->path_mtu_discovery, ==, FALSE); - break; - } - case NM_LINK_TYPE_MACVLAN: { - const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan; - - g_assert (plnk == nm_platform_link_get_lnk_macvlan (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->no_promisc, ==, FALSE); - g_assert_cmpint (plnk->mode, ==, MACVLAN_MODE_BRIDGE); - break; - } - case NM_LINK_TYPE_MACVTAP: { - const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan; - - g_assert (plnk == nm_platform_link_get_lnk_macvtap (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->no_promisc, ==, FALSE); - g_assert_cmpint (plnk->mode, ==, MACVLAN_MODE_PRIVATE); - break; - } - case NM_LINK_TYPE_SIT: { - const NMPlatformLnkSit *plnk = &lnk->lnk_sit; - - g_assert (plnk == nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); - nmtst_assert_ip4_address (plnk->local, "192.168.200.1"); - nmtst_assert_ip4_address (plnk->remote, "172.25.100.14"); - g_assert_cmpint (plnk->ttl, ==, 0); - g_assert_cmpint (plnk->tos, ==, 31); - g_assert_cmpint (plnk->path_mtu_discovery, ==, FALSE); - break; - } - case NM_LINK_TYPE_TUN: { - const NMPlatformLnkTun *plnk; - NMPlatformLnkTun lnk_tun2; - - g_assert ((lnk ? &lnk->lnk_tun : NULL) == nm_platform_link_get_lnk_tun (NM_PLATFORM_GET, ifindex, NULL)); - - /* kernel might not expose tun options via netlink. Either way, try - * to read them (either from platform cache, or fallback to sysfs). - * See also: rh#1547213. */ - if (!nm_platform_link_tun_get_properties (NM_PLATFORM_GET, - ifindex, - &lnk_tun2)) - g_assert_not_reached (); - - plnk = lnk ? &lnk->lnk_tun : &lnk_tun2; - if (lnk) - g_assert (memcmp (plnk, &lnk_tun2, sizeof (NMPlatformLnkTun)) == 0); - - if (i_step == 0) { - /* Before we upped the device for the first time the kernel didn't notify - * us of the owner set after the link creation: - * https://bugzilla.redhat.com/show_bug.cgi?id=1566062 - */ - break; - } - - g_assert (nm_platform_lnk_tun_cmp (plnk, &lnk_tun) == 0); - break; - } - case NM_LINK_TYPE_VLAN: { - const NMPlatformLnkVlan *plnk = &lnk->lnk_vlan; - - g_assert (plnk == nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->id, ==, 1242); - break; - } - case NM_LINK_TYPE_VRF: { - const NMPlatformLnkVrf *plnk = &lnk->lnk_vrf; - - g_assert (plnk == nm_platform_link_get_lnk_vrf (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->table, ==, 9876); - break; - } - case NM_LINK_TYPE_VXLAN: { - const NMPlatformLnkVxlan *plnk = &lnk->lnk_vxlan; - - g_assert (plnk == nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, !=, 0); - g_assert_cmpint (plnk->tos, ==, 0); - g_assert_cmpint (plnk->learning, ==, TRUE); - g_assert_cmpint (plnk->limit, ==, 0); - g_assert_cmpint (plnk->proxy, ==, FALSE); - g_assert_cmpint (plnk->rsc, ==, FALSE); - g_assert_cmpint (plnk->l2miss, ==, FALSE); - g_assert_cmpint (plnk->l3miss, ==, FALSE); - - switch (test_data->test_mode) { - case 0: - g_assert_cmpint (plnk->id, ==, 42); - nmtst_assert_ip4_address (plnk->local, "23.1.2.164"); - nmtst_assert_ip4_address (plnk->group, "239.1.2.134"); - nmtst_assert_ip6_address (&plnk->group6, "::"); - nmtst_assert_ip6_address (&plnk->local6, "::"); - g_assert_cmpint (plnk->ttl, ==, 0); - g_assert_cmpint (plnk->ageing, ==, 1245); - g_assert_cmpint (plnk->dst_port, ==, 4789); - if ( plnk->src_port_min != 0 - || plnk->src_port_max != 0) { - /* on some kernels, omitting the port range results in setting - * following default port range. */ - g_assert_cmpint (plnk->src_port_min, ==, 32768); - g_assert_cmpint (plnk->src_port_max, ==, 61000); - } - break; - case 1: - g_assert_cmpint (plnk->id, ==, 11214423); - nmtst_assert_ip4_address (plnk->local, "0.0.0.0"); - nmtst_assert_ip4_address (plnk->group, "0.0.0.0"); - nmtst_assert_ip6_address (&plnk->group6, "ff0e::115"); - nmtst_assert_ip6_address (&plnk->local6, "1:2:3:4:334:23::23"); - g_assert_cmpint (plnk->ageing, ==, 3245); - g_assert_cmpint (plnk->dst_port, ==, 57412); - g_assert_cmpint (plnk->ttl, ==, 32); - g_assert_cmpint (plnk->src_port_min, ==, 1000); - g_assert_cmpint (plnk->src_port_max, ==, 1003); - break; - } - break; - } - case NM_LINK_TYPE_WIREGUARD: { - const NMPlatformLnkWireGuard *plnk = &lnk->lnk_wireguard; - - g_assert (plnk == nm_platform_link_get_lnk_wireguard (NM_PLATFORM_GET, ifindex, NULL)); - - if (plink->n_ifi_flags & IFF_UP) { - _test_wireguard_change (NM_PLATFORM_GET, plink->ifindex, test_data->test_mode); - if (_LOGD_ENABLED ()) - _system ("WG_HIDE_KEYS=never wg show all"); - } - break; - } - default: - g_assert_not_reached (); - } - } - - nmtstp_link_delete (NULL, -1, ifindex, DEVICE_NAME, TRUE); + const TestAddSoftwareDetectData *test_data = user_data; + int ifindex, ifindex_parent; + const NMPlatformLink * plink; + const NMPObject * lnk; + int r; + guint i_step; + const gboolean ext = test_data->external_command; + NMPlatformLnkBridge lnk_bridge = {}; + NMPlatformLnkTun lnk_tun; + NMPlatformLnkGre lnk_gre = {}; + nm_auto_close int tun_fd = -1; + + nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME); + ifindex_parent = + nmtstp_assert_wait_for_link(NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; + + switch (test_data->link_type) { + case NM_LINK_TYPE_BRIDGE: + + lnk_bridge.forward_delay = 1560; + lnk_bridge.hello_time = 150; + lnk_bridge.max_age = 2100; + lnk_bridge.ageing_time = 2200; + lnk_bridge.stp_state = TRUE; + lnk_bridge.priority = 22; + lnk_bridge.vlan_protocol = 0x8100; + lnk_bridge.vlan_stats_enabled = + nmtstp_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED) + ? TRUE + : FALSE; + lnk_bridge.group_fwd_mask = 8; + lnk_bridge.group_addr = (NMEtherAddr){{0x01, 0x80, 0xC2, 0x00, 0x00, 0x08}}; + lnk_bridge.mcast_snooping = TRUE; + lnk_bridge.mcast_router = 1; + lnk_bridge.mcast_query_use_ifaddr = TRUE; + lnk_bridge.mcast_querier = TRUE; + lnk_bridge.mcast_hash_max = 1024; + lnk_bridge.mcast_last_member_count = 2; + lnk_bridge.mcast_startup_query_count = 3; + lnk_bridge.mcast_last_member_interval = 5000; + lnk_bridge.mcast_membership_interval = 25000; + lnk_bridge.mcast_querier_interval = 26000; + lnk_bridge.mcast_query_interval = 12000; + lnk_bridge.mcast_query_response_interval = 5200; + lnk_bridge.mcast_startup_query_interval = 3000; + + if (!nmtstp_link_bridge_add(NULL, ext, DEVICE_NAME, &lnk_bridge)) + g_error("Failed adding Bridge interface"); + break; + + case NM_LINK_TYPE_GRE: + { + gboolean gracefully_skip = FALSE; + + lnk_gre.local = nmtst_inet4_from_string("192.168.233.204"); + lnk_gre.remote = nmtst_inet4_from_string("172.168.10.25"); + lnk_gre.parent_ifindex = ifindex_parent; + lnk_gre.ttl = 174; + lnk_gre.tos = 37; + lnk_gre.path_mtu_discovery = TRUE; + + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gre0")) { + /* Seems that the ip_gre module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; + } + + if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) { + if (gracefully_skip) { + g_test_skip( + "Cannot create gre tunnel because of missing ip_gre module (modprobe ip_gre)"); + goto out_delete_parent; + } + g_error("Failed adding GRE tunnel"); + } + break; + } + case NM_LINK_TYPE_GRETAP: + { + gboolean gracefully_skip = FALSE; + + lnk_gre.local = nmtst_inet4_from_string("192.168.1.133"); + lnk_gre.remote = nmtst_inet4_from_string("172.168.101.2"); + lnk_gre.parent_ifindex = ifindex_parent; + lnk_gre.ttl = 39; + lnk_gre.tos = 12; + lnk_gre.path_mtu_discovery = FALSE; + lnk_gre.is_tap = TRUE; + + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "gretap0")) { + /* Seems that the ip_gre module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip_gre", NULL) != 0; + } + + if (!nmtstp_link_gre_add(NULL, ext, DEVICE_NAME, &lnk_gre)) { + if (gracefully_skip) { + g_test_skip("Cannot create gretap tunnel because of missing ip_gre module " + "(modprobe ip_gre)"); + goto out_delete_parent; + } + g_error("Failed adding GRETAP tunnel"); + } + break; + } + case NM_LINK_TYPE_IPIP: + { + NMPlatformLnkIpIp lnk_ipip = {}; + gboolean gracefully_skip = FALSE; + + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "tunl0")) { + /* Seems that the ipip module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ipip", NULL) != 0; + } + + lnk_ipip.local = nmtst_inet4_from_string("1.2.3.4"); + lnk_ipip.remote = nmtst_inet4_from_string("5.6.7.8"); + lnk_ipip.parent_ifindex = ifindex_parent; + lnk_ipip.tos = 32; + lnk_ipip.path_mtu_discovery = FALSE; + + if (!nmtstp_link_ipip_add(NULL, ext, DEVICE_NAME, &lnk_ipip)) { + if (gracefully_skip) { + g_test_skip( + "Cannot create ipip tunnel because of missing ipip module (modprobe ipip)"); + goto out_delete_parent; + } + g_error("Failed adding IPIP tunnel"); + } + break; + } + case NM_LINK_TYPE_IP6TNL: + { + NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; + gboolean gracefully_skip = FALSE; + + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6tnl0")) { + /* Seems that the ip6_tunnel module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_tunnel", NULL) != 0; + } + + switch (test_data->test_mode) { + case 0: + lnk_ip6tnl.local = *nmtst_inet6_from_string("fd01::15"); + lnk_ip6tnl.remote = *nmtst_inet6_from_string("fd01::16"); + lnk_ip6tnl.parent_ifindex = ifindex_parent; + lnk_ip6tnl.tclass = 20; + lnk_ip6tnl.encap_limit = 6; + lnk_ip6tnl.flow_label = 1337; + lnk_ip6tnl.proto = IPPROTO_IPV6; + break; + case 1: + lnk_ip6tnl.local = *nmtst_inet6_from_string("fd01::17"); + lnk_ip6tnl.remote = *nmtst_inet6_from_string("fd01::18"); + lnk_ip6tnl.parent_ifindex = ifindex_parent; + lnk_ip6tnl.tclass = 0; + lnk_ip6tnl.encap_limit = 0; + lnk_ip6tnl.flow_label = 1338; + lnk_ip6tnl.proto = IPPROTO_IPV6; + lnk_ip6tnl.flags = IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS; + break; + } + + if (!nmtstp_link_ip6tnl_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { + if (gracefully_skip) { + g_test_skip("Cannot create ip6tnl tunnel because of missing ip6_tunnel module " + "(modprobe ip6_tunnel)"); + goto out_delete_parent; + } + g_error("Failed adding IP6TNL tunnel"); + } + break; + } + case NM_LINK_TYPE_IP6GRE: + { + NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; + gboolean gracefully_skip = FALSE; + + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) { + /* Seems that the ip6_tunnel module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; + } + + lnk_ip6tnl.local = *nmtst_inet6_from_string("fd01::42"); + lnk_ip6tnl.remote = *nmtst_inet6_from_string("fd01::aaaa"); + lnk_ip6tnl.parent_ifindex = ifindex_parent; + lnk_ip6tnl.tclass = 21; + lnk_ip6tnl.flow_label = 1338; + lnk_ip6tnl.is_gre = TRUE; + + if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { + if (gracefully_skip) { + g_test_skip("Cannot create ip6gre tunnel because of missing ip6_gre module " + "(modprobe ip6_gre)"); + goto out_delete_parent; + } + g_error("Failed adding IP6GRE tunnel"); + } + break; + } + case NM_LINK_TYPE_IP6GRETAP: + { + NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; + gboolean gracefully_skip = FALSE; + + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "ip6gre0")) { + /* Seems that the ip6_tunnel module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe(NULL, TRUE, "ip6_gre", NULL) != 0; + } + + lnk_ip6tnl.local = *nmtst_inet6_from_string("fe80::abcd"); + lnk_ip6tnl.remote = *nmtst_inet6_from_string("fc01::bbbb"); + lnk_ip6tnl.parent_ifindex = ifindex_parent; + lnk_ip6tnl.ttl = 10; + lnk_ip6tnl.tclass = 22; + lnk_ip6tnl.flow_label = 1339; + lnk_ip6tnl.is_gre = TRUE; + lnk_ip6tnl.is_tap = TRUE; + + if (!nmtstp_link_ip6gre_add(NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { + if (gracefully_skip) { + g_test_skip("Cannot create ip6gretap tunnel because of missing ip6_gre module " + "(modprobe ip6_gre)"); + goto out_delete_parent; + } + g_error("Failed adding IP6GRETAP tunnel"); + } + break; + } + case NM_LINK_TYPE_MACVLAN: + { + NMPlatformLnkMacvlan lnk_macvlan = {}; + const NMPlatformLink *dummy; + char buf[256]; + int i; + + lnk_macvlan.mode = MACVLAN_MODE_BRIDGE; + lnk_macvlan.no_promisc = FALSE; + lnk_macvlan.tap = FALSE; + + /* Since in old kernel versions sysfs files for macvtaps are not + * namespaced, the creation can fail if a macvtap in another namespace + * has the same index. Try to detect this situation and skip already + * used indexes. + * The fix (17af2bce) is included kernel 4.7, dated 24 July, 2016. + */ + for (i = ifindex_parent + 1; i < ifindex_parent + 100; i++) { + snprintf(buf, sizeof(buf), "/sys/class/macvtap/tap%d", i); + if (!g_file_test(buf, G_FILE_TEST_IS_SYMLINK)) + break; + + _LOGD("skipping ifindex %d as already used by a macvtap", i); + + dummy = nmtstp_link_dummy_add(NM_PLATFORM_GET, FALSE, "dummy-tmp"); + g_assert_cmpint(dummy->ifindex, ==, i); + nmtstp_link_delete(NM_PLATFORM_GET, FALSE, dummy->ifindex, NULL, TRUE); + } + + if (!nmtstp_link_macvlan_add(NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvlan)) + g_error("Failed adding MACVLAN interface"); + break; + } + case NM_LINK_TYPE_MACVTAP: + { + NMPlatformLnkMacvlan lnk_macvtap = {}; + + lnk_macvtap.mode = MACVLAN_MODE_PRIVATE; + lnk_macvtap.no_promisc = FALSE; + lnk_macvtap.tap = TRUE; + + if (!nmtstp_link_macvlan_add(NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvtap)) + g_error("Failed adding MACVTAP interface"); + break; + } + case NM_LINK_TYPE_SIT: + { + NMPlatformLnkSit lnk_sit = {}; + gboolean gracefully_skip = FALSE; + + lnk_sit.local = nmtst_inet4_from_string("192.168.200.1"); + lnk_sit.remote = nmtst_inet4_from_string("172.25.100.14"); + lnk_sit.parent_ifindex = ifindex_parent; + lnk_sit.ttl = 0; + lnk_sit.tos = 31; + lnk_sit.path_mtu_discovery = FALSE; + + if (!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "sit0")) { + /* Seems that the sit module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe(NULL, TRUE, "sit", NULL) != 0; + } + + if (!nmtstp_link_sit_add(NULL, ext, DEVICE_NAME, &lnk_sit)) { + if (gracefully_skip) { + g_test_skip( + "Cannot create sit tunnel because of missing sit module (modprobe sit)"); + goto out_delete_parent; + } + g_error("Failed adding SIT tunnel"); + } + break; + } + case NM_LINK_TYPE_VLAN: + nmtstp_run_command_check("ip link add name %s link %s type vlan id 1242", + DEVICE_NAME, + PARENT_NAME); + break; + case NM_LINK_TYPE_VRF: + { + NMPlatformLnkVrf lnk_vrf = {}; + gboolean not_supported; + + lnk_vrf.table = 9876; + + if (!nmtstp_link_vrf_add(NULL, ext, DEVICE_NAME, &lnk_vrf, ¬_supported)) { + if (not_supported) { + g_test_skip("Cannot create VRF interface because of missing kernel support"); + goto out_delete_parent; + } + g_error("Failed adding VRF interface"); + } + break; + } + case NM_LINK_TYPE_VXLAN: + { + NMPlatformLnkVxlan lnk_vxlan = {}; + + switch (test_data->test_mode) { + case 0: + lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME); + lnk_vxlan.id = 42; + lnk_vxlan.local = nmtst_inet4_from_string("23.1.2.164"); + lnk_vxlan.group = nmtst_inet4_from_string("239.1.2.134"); + lnk_vxlan.dst_port = 4789; + lnk_vxlan.learning = TRUE; + lnk_vxlan.ageing = 1245; + break; + case 1: + lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, PARENT_NAME); + lnk_vxlan.id = 11214423; + lnk_vxlan.local6 = *nmtst_inet6_from_string("1:2:3:4:334:23::23"); + lnk_vxlan.group6 = *nmtst_inet6_from_string("ff0e::115"); + lnk_vxlan.ttl = 32; + lnk_vxlan.dst_port = 57412; + lnk_vxlan.src_port_min = 1000; + lnk_vxlan.src_port_max = 1003; + lnk_vxlan.learning = TRUE; + lnk_vxlan.ageing = 3245; + break; + } + + g_assert(nmtstp_link_vxlan_add(NULL, ext, DEVICE_NAME, &lnk_vxlan)); + break; + } + case NM_LINK_TYPE_TUN: + { + gboolean owner_valid = nmtst_get_rand_bool(); + gboolean group_valid = nmtst_get_rand_bool(); + + switch (test_data->test_mode) { + case 0: + lnk_tun = (NMPlatformLnkTun){ + .type = nmtst_get_rand_bool() ? IFF_TUN : IFF_TAP, + .owner = owner_valid ? getuid() : 0, + .owner_valid = owner_valid, + .group = group_valid ? getgid() : 0, + .group_valid = group_valid, + .pi = nmtst_get_rand_bool(), + .vnet_hdr = nmtst_get_rand_bool(), + .multi_queue = nmtst_get_rand_bool(), + + /* if we add the device via iproute2 (external), we can only + * create persistent devices. */ + .persist = (ext == 1) ? TRUE : nmtst_get_rand_bool(), + }; + break; + default: + g_assert_not_reached(); + break; + } + + g_assert(nmtstp_link_tun_add(NULL, + ext, + DEVICE_NAME, + &lnk_tun, + (!lnk_tun.persist || nmtst_get_rand_bool()) ? &tun_fd : NULL)); + break; + } + case NM_LINK_TYPE_WIREGUARD: + { + const NMPlatformLink *link; + + r = nm_platform_link_wireguard_add(NM_PLATFORM_GET, DEVICE_NAME, &link); + if (r == -EOPNOTSUPP) { + g_test_skip("wireguard not supported (modprobe wireguard?)"); + goto out_delete_parent; + } + + g_assert(NMTST_NM_ERR_SUCCESS(r)); + g_assert(NMP_OBJECT_GET_TYPE(NMP_OBJECT_UP_CAST(link)) == NMP_OBJECT_TYPE_LINK); + break; + } + default: + g_assert_not_reached(); + } + + ifindex = nmtstp_assert_wait_for_link(NM_PLATFORM_GET, DEVICE_NAME, test_data->link_type, 100) + ->ifindex; + + nmtstp_link_set_updown(NULL, -1, ifindex_parent, TRUE); + + for (i_step = 0; i_step < 5; i_step++) { + _LOGD("test-software-detect: step %u", i_step); + if (nmtst_is_debug()) + nmtstp_run_command_check("ip -d link show %s", DEVICE_NAME); + + if (i_step > 0) { + gboolean set_up = (i_step % 2) == 1; + + if (test_data->link_type == NM_LINK_TYPE_VXLAN && set_up) { + /* On RHEL-7, we need to add a tiny sleep here, otherwise, + * upping the vxlan device fails with EADDRINUSE. + * https://bugzilla.redhat.com/show_bug.cgi?id=1277131 */ + g_usleep(1); + } + nmtstp_link_set_updown(NULL, -1, ifindex, set_up); + } + + lnk = nm_platform_link_get_lnk(NM_PLATFORM_GET, ifindex, test_data->link_type, &plink); + g_assert(plink); + g_assert_cmpint(plink->ifindex, ==, ifindex); + + if (!lnk && test_data->link_type == NM_LINK_TYPE_TUN) { + /* this is ok. Kernel apparently does not support tun properties via netlink. We + * fetch them from sysfs below. */ + } else + g_assert(lnk); + + switch (test_data->link_type) { + case NM_LINK_TYPE_BRIDGE: + { + const NMPlatformLnkBridge *plnk = &lnk->lnk_bridge; + + g_assert(plnk == nm_platform_link_get_lnk_bridge(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(nm_platform_lnk_bridge_cmp(&lnk_bridge, plnk), ==, 0); + g_assert_cmpint(plnk->forward_delay, ==, 1560); + g_assert_cmpint(plnk->hello_time, ==, 150); + g_assert_cmpint(plnk->max_age, ==, 2100); + g_assert_cmpint(plnk->ageing_time, ==, 2200); + g_assert_cmpint(plnk->stp_state, ==, TRUE); + g_assert_cmpint(plnk->priority, ==, 22); + g_assert_cmpint(plnk->vlan_protocol, ==, 0x8100); + g_assert_cmpint(plnk->vlan_stats_enabled, ==, lnk_bridge.vlan_stats_enabled); + g_assert_cmpint(plnk->group_fwd_mask, ==, 8); + g_assert_cmpint(plnk->mcast_snooping, ==, TRUE); + g_assert_cmpint(plnk->mcast_router, ==, 1); + g_assert_cmpint(plnk->mcast_query_use_ifaddr, ==, TRUE); + g_assert_cmpint(plnk->mcast_querier, ==, TRUE); + g_assert_cmpint(plnk->mcast_hash_max, ==, 1024); + g_assert_cmpint(plnk->mcast_last_member_count, ==, 2); + g_assert_cmpint(plnk->mcast_startup_query_count, ==, 3); + g_assert_cmpint(plnk->mcast_last_member_interval, ==, 5000); + g_assert_cmpint(plnk->mcast_membership_interval, ==, 25000); + g_assert_cmpint(plnk->mcast_querier_interval, ==, 26000); + g_assert_cmpint(plnk->mcast_query_interval, ==, 12000); + g_assert_cmpint(plnk->mcast_query_response_interval, ==, 5200); + g_assert_cmpint(plnk->mcast_startup_query_interval, ==, 3000); + g_assert_cmpint(nm_platform_lnk_bridge_cmp(&lnk_bridge, plnk), ==, 0); + break; + } + case NM_LINK_TYPE_GRE: + { + const NMPlatformLnkGre *plnk = &lnk->lnk_gre; + + g_assert(plnk == nm_platform_link_get_lnk_gre(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_lnk_gre_cmp(plnk, &lnk_gre) == 0); + + break; + } + case NM_LINK_TYPE_GRETAP: + { + const NMPlatformLnkGre *plnk = &lnk->lnk_gre; + + g_assert(plnk == nm_platform_link_get_lnk_gretap(NM_PLATFORM_GET, ifindex, NULL)); + g_assert(nm_platform_lnk_gre_cmp(plnk, &lnk_gre) == 0); + break; + } + case NM_LINK_TYPE_IP6TNL: + { + const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; + + switch (test_data->test_mode) { + case 0: + g_assert(plnk == nm_platform_link_get_lnk_ip6tnl(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip6_address(&plnk->local, "fd01::15"); + nmtst_assert_ip6_address(&plnk->remote, "fd01::16"); + g_assert_cmpint(plnk->ttl, ==, 0); + g_assert_cmpint(plnk->tclass, ==, 20); + g_assert_cmpint(plnk->encap_limit, ==, 6); + g_assert_cmpint(plnk->flow_label, ==, 1337); + g_assert_cmpint(plnk->proto, ==, IPPROTO_IPV6); + break; + case 1: + g_assert(plnk == nm_platform_link_get_lnk_ip6tnl(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip6_address(&plnk->local, "fd01::17"); + nmtst_assert_ip6_address(&plnk->remote, "fd01::18"); + g_assert_cmpint(plnk->ttl, ==, 0); + g_assert_cmpint(plnk->flow_label, ==, 1338); + g_assert_cmpint(plnk->proto, ==, IPPROTO_IPV6); + g_assert_cmpint(plnk->flags & 0xFFFF, /* ignore kernel internal flags */ + ==, + IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS); + break; + } + break; + } + case NM_LINK_TYPE_IP6GRE: + { + const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; + + g_assert(plnk == nm_platform_link_get_lnk_ip6gre(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip6_address(&plnk->local, "fd01::42"); + nmtst_assert_ip6_address(&plnk->remote, "fd01::aaaa"); + g_assert_cmpint(plnk->tclass, ==, 21); + g_assert_cmpint(plnk->flow_label, ==, 1338); + g_assert_cmpint(plnk->is_gre, ==, TRUE); + g_assert_cmpint(plnk->is_tap, ==, FALSE); + break; + } + case NM_LINK_TYPE_IP6GRETAP: + { + const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; + + g_assert(plnk == nm_platform_link_get_lnk_ip6gretap(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip6_address(&plnk->local, "fe80::abcd"); + nmtst_assert_ip6_address(&plnk->remote, "fc01::bbbb"); + g_assert_cmpint(plnk->ttl, ==, 10); + g_assert_cmpint(plnk->tclass, ==, 22); + g_assert_cmpint(plnk->flow_label, ==, 1339); + g_assert_cmpint(plnk->is_gre, ==, TRUE); + g_assert_cmpint(plnk->is_tap, ==, TRUE); + break; + } + case NM_LINK_TYPE_IPIP: + { + const NMPlatformLnkIpIp *plnk = &lnk->lnk_ipip; + + g_assert(plnk == nm_platform_link_get_lnk_ipip(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip4_address(plnk->local, "1.2.3.4"); + nmtst_assert_ip4_address(plnk->remote, "5.6.7.8"); + g_assert_cmpint(plnk->ttl, ==, 0); + g_assert_cmpint(plnk->tos, ==, 32); + g_assert_cmpint(plnk->path_mtu_discovery, ==, FALSE); + break; + } + case NM_LINK_TYPE_MACVLAN: + { + const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan; + + g_assert(plnk == nm_platform_link_get_lnk_macvlan(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->no_promisc, ==, FALSE); + g_assert_cmpint(plnk->mode, ==, MACVLAN_MODE_BRIDGE); + break; + } + case NM_LINK_TYPE_MACVTAP: + { + const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan; + + g_assert(plnk == nm_platform_link_get_lnk_macvtap(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->no_promisc, ==, FALSE); + g_assert_cmpint(plnk->mode, ==, MACVLAN_MODE_PRIVATE); + break; + } + case NM_LINK_TYPE_SIT: + { + const NMPlatformLnkSit *plnk = &lnk->lnk_sit; + + g_assert(plnk == nm_platform_link_get_lnk_sit(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip4_address(plnk->local, "192.168.200.1"); + nmtst_assert_ip4_address(plnk->remote, "172.25.100.14"); + g_assert_cmpint(plnk->ttl, ==, 0); + g_assert_cmpint(plnk->tos, ==, 31); + g_assert_cmpint(plnk->path_mtu_discovery, ==, FALSE); + break; + } + case NM_LINK_TYPE_TUN: + { + const NMPlatformLnkTun *plnk; + NMPlatformLnkTun lnk_tun2; + + g_assert((lnk ? &lnk->lnk_tun : NULL) + == nm_platform_link_get_lnk_tun(NM_PLATFORM_GET, ifindex, NULL)); + + /* kernel might not expose tun options via netlink. Either way, try + * to read them (either from platform cache, or fallback to sysfs). + * See also: rh#1547213. */ + if (!nm_platform_link_tun_get_properties(NM_PLATFORM_GET, ifindex, &lnk_tun2)) + g_assert_not_reached(); + + plnk = lnk ? &lnk->lnk_tun : &lnk_tun2; + if (lnk) + g_assert(memcmp(plnk, &lnk_tun2, sizeof(NMPlatformLnkTun)) == 0); + + if (i_step == 0) { + /* Before we upped the device for the first time the kernel didn't notify + * us of the owner set after the link creation: + * https://bugzilla.redhat.com/show_bug.cgi?id=1566062 + */ + break; + } + + g_assert(nm_platform_lnk_tun_cmp(plnk, &lnk_tun) == 0); + break; + } + case NM_LINK_TYPE_VLAN: + { + const NMPlatformLnkVlan *plnk = &lnk->lnk_vlan; + + g_assert(plnk == nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->id, ==, 1242); + break; + } + case NM_LINK_TYPE_VRF: + { + const NMPlatformLnkVrf *plnk = &lnk->lnk_vrf; + + g_assert(plnk == nm_platform_link_get_lnk_vrf(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->table, ==, 9876); + break; + } + case NM_LINK_TYPE_VXLAN: + { + const NMPlatformLnkVxlan *plnk = &lnk->lnk_vxlan; + + g_assert(plnk == nm_platform_link_get_lnk_vxlan(NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint(plnk->parent_ifindex, !=, 0); + g_assert_cmpint(plnk->tos, ==, 0); + g_assert_cmpint(plnk->learning, ==, TRUE); + g_assert_cmpint(plnk->limit, ==, 0); + g_assert_cmpint(plnk->proxy, ==, FALSE); + g_assert_cmpint(plnk->rsc, ==, FALSE); + g_assert_cmpint(plnk->l2miss, ==, FALSE); + g_assert_cmpint(plnk->l3miss, ==, FALSE); + + switch (test_data->test_mode) { + case 0: + g_assert_cmpint(plnk->id, ==, 42); + nmtst_assert_ip4_address(plnk->local, "23.1.2.164"); + nmtst_assert_ip4_address(plnk->group, "239.1.2.134"); + nmtst_assert_ip6_address(&plnk->group6, "::"); + nmtst_assert_ip6_address(&plnk->local6, "::"); + g_assert_cmpint(plnk->ttl, ==, 0); + g_assert_cmpint(plnk->ageing, ==, 1245); + g_assert_cmpint(plnk->dst_port, ==, 4789); + if (plnk->src_port_min != 0 || plnk->src_port_max != 0) { + /* on some kernels, omitting the port range results in setting + * following default port range. */ + g_assert_cmpint(plnk->src_port_min, ==, 32768); + g_assert_cmpint(plnk->src_port_max, ==, 61000); + } + break; + case 1: + g_assert_cmpint(plnk->id, ==, 11214423); + nmtst_assert_ip4_address(plnk->local, "0.0.0.0"); + nmtst_assert_ip4_address(plnk->group, "0.0.0.0"); + nmtst_assert_ip6_address(&plnk->group6, "ff0e::115"); + nmtst_assert_ip6_address(&plnk->local6, "1:2:3:4:334:23::23"); + g_assert_cmpint(plnk->ageing, ==, 3245); + g_assert_cmpint(plnk->dst_port, ==, 57412); + g_assert_cmpint(plnk->ttl, ==, 32); + g_assert_cmpint(plnk->src_port_min, ==, 1000); + g_assert_cmpint(plnk->src_port_max, ==, 1003); + break; + } + break; + } + case NM_LINK_TYPE_WIREGUARD: + { + const NMPlatformLnkWireGuard *plnk = &lnk->lnk_wireguard; + + g_assert(plnk == nm_platform_link_get_lnk_wireguard(NM_PLATFORM_GET, ifindex, NULL)); + + if (plink->n_ifi_flags & IFF_UP) { + _test_wireguard_change(NM_PLATFORM_GET, plink->ifindex, test_data->test_mode); + if (_LOGD_ENABLED()) + _system("WG_HIDE_KEYS=never wg show all"); + } + break; + } + default: + g_assert_not_reached(); + } + } + + nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE); out_delete_parent: - nmtstp_link_delete (NULL, -1, ifindex_parent, PARENT_NAME, TRUE); + nmtstp_link_delete(NULL, -1, ifindex_parent, PARENT_NAME, TRUE); } static void -test_software_detect_add (const char *testpath, - NMLinkType link_type, - int test_mode) +test_software_detect_add(const char *testpath, NMLinkType link_type, int test_mode) { - TestAddSoftwareDetectData *test_data; - char *path; - - test_data = g_new0 (TestAddSoftwareDetectData, 1); - test_data->link_type = link_type; - test_data->test_mode = test_mode; - test_data->external_command = TRUE; - - path = g_strdup_printf ("%s/external", testpath); - g_test_add_data_func_full (path, test_data, test_software_detect, g_free); - g_free (path); - - test_data = g_new0 (TestAddSoftwareDetectData, 1); - test_data->link_type = link_type; - test_data->test_mode = test_mode; - test_data->external_command = FALSE; - - path = g_strdup_printf ("%s/platform", testpath); - g_test_add_data_func_full (path, test_data, test_software_detect, g_free); - g_free (path); - - test_data = g_new0 (TestAddSoftwareDetectData, 1); - test_data->link_type = link_type; - test_data->test_mode = test_mode; - test_data->external_command = -1; - - path = g_strdup_printf ("%s/random", testpath); - g_test_add_data_func_full (path, test_data, test_software_detect, g_free); - g_free (path); + TestAddSoftwareDetectData *test_data; + char * path; + + test_data = g_new0(TestAddSoftwareDetectData, 1); + test_data->link_type = link_type; + test_data->test_mode = test_mode; + test_data->external_command = TRUE; + + path = g_strdup_printf("%s/external", testpath); + g_test_add_data_func_full(path, test_data, test_software_detect, g_free); + g_free(path); + + test_data = g_new0(TestAddSoftwareDetectData, 1); + test_data->link_type = link_type; + test_data->test_mode = test_mode; + test_data->external_command = FALSE; + + path = g_strdup_printf("%s/platform", testpath); + g_test_add_data_func_full(path, test_data, test_software_detect, g_free); + g_free(path); + + test_data = g_new0(TestAddSoftwareDetectData, 1); + test_data->link_type = link_type; + test_data->test_mode = test_mode; + test_data->external_command = -1; + + path = g_strdup_printf("%s/random", testpath); + g_test_add_data_func_full(path, test_data, test_software_detect, g_free); + g_free(path); } /*****************************************************************************/ static void -_assert_xgress_qos_mappings_impl (int ifindex, - gboolean is_ingress_map , - int n_entries, - int n, - ...) +_assert_xgress_qos_mappings_impl(int ifindex, gboolean is_ingress_map, int n_entries, int n, ...) { - const NMPlatformLink *plink; - const NMPObject *lnk; - guint n_map; - const NMVlanQosMapping *map; - va_list ap; - guint i; - - lnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, NM_LINK_TYPE_VLAN, &plink); - - g_assert (plink); - g_assert_cmpint (plink->ifindex, ==, ifindex); - g_assert (lnk); - g_assert (&lnk->lnk_vlan == nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, NULL)); - - if (nmtst_is_debug ()) - nmtstp_run_command_check ("ip -d link show %s", plink->name); - - if (is_ingress_map) { - map = lnk->_lnk_vlan.ingress_qos_map; - n_map = lnk->_lnk_vlan.n_ingress_qos_map; - } else { - map = lnk->_lnk_vlan.egress_qos_map; - n_map = lnk->_lnk_vlan.n_egress_qos_map; - } - - if (n_entries != -1) - g_assert_cmpint (n_map, ==, n_entries); - - for (i = 0; i < n_map; i++) { - if (is_ingress_map) { - g_assert_cmpint (map[i].from, >=, 0); - g_assert_cmpint (map[i].from, <=, 7); - } - if (i > 0) - g_assert_cmpint (map[i - 1].from, <, map[i].from); - } - - va_start (ap, n); - for (; n > 0; n--) { - gboolean found = FALSE; - guint from = va_arg (ap, guint); - guint to = va_arg (ap, guint); - - for (i = 0; i < n_map; i++) { - if (map[i].from == from) { - g_assert (!found); - found = TRUE; - - g_assert (map[i].to == to); - } - } - g_assert (found); - } - va_end (ap); + const NMPlatformLink * plink; + const NMPObject * lnk; + guint n_map; + const NMVlanQosMapping *map; + va_list ap; + guint i; + + lnk = nm_platform_link_get_lnk(NM_PLATFORM_GET, ifindex, NM_LINK_TYPE_VLAN, &plink); + + g_assert(plink); + g_assert_cmpint(plink->ifindex, ==, ifindex); + g_assert(lnk); + g_assert(&lnk->lnk_vlan == nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, NULL)); + + if (nmtst_is_debug()) + nmtstp_run_command_check("ip -d link show %s", plink->name); + + if (is_ingress_map) { + map = lnk->_lnk_vlan.ingress_qos_map; + n_map = lnk->_lnk_vlan.n_ingress_qos_map; + } else { + map = lnk->_lnk_vlan.egress_qos_map; + n_map = lnk->_lnk_vlan.n_egress_qos_map; + } + + if (n_entries != -1) + g_assert_cmpint(n_map, ==, n_entries); + + for (i = 0; i < n_map; i++) { + if (is_ingress_map) { + g_assert_cmpint(map[i].from, >=, 0); + g_assert_cmpint(map[i].from, <=, 7); + } + if (i > 0) + g_assert_cmpint(map[i - 1].from, <, map[i].from); + } + + va_start(ap, n); + for (; n > 0; n--) { + gboolean found = FALSE; + guint from = va_arg(ap, guint); + guint to = va_arg(ap, guint); + + for (i = 0; i < n_map; i++) { + if (map[i].from == from) { + g_assert(!found); + found = TRUE; + + g_assert(map[i].to == to); + } + } + g_assert(found); + } + va_end(ap); } -#define _assert_xgress_qos_mappings(ifindex, is_ingress_map, n_entries, ...) \ - _assert_xgress_qos_mappings_impl ((ifindex), (is_ingress_map), (n_entries), \ - (G_STATIC_ASSERT_EXPR ((NM_NARG (__VA_ARGS__) % 2) == 0), NM_NARG (__VA_ARGS__) / 2), \ - __VA_ARGS__) -#define _assert_ingress_qos_mappings(ifindex, n_entries, ...) _assert_xgress_qos_mappings (ifindex, TRUE, n_entries, __VA_ARGS__) -#define _assert_egress_qos_mappings(ifindex, n_entries, ...) _assert_xgress_qos_mappings (ifindex, FALSE, n_entries, __VA_ARGS__) +#define _assert_xgress_qos_mappings(ifindex, is_ingress_map, n_entries, ...) \ + _assert_xgress_qos_mappings_impl( \ + (ifindex), \ + (is_ingress_map), \ + (n_entries), \ + (G_STATIC_ASSERT_EXPR((NM_NARG(__VA_ARGS__) % 2) == 0), NM_NARG(__VA_ARGS__) / 2), \ + __VA_ARGS__) +#define _assert_ingress_qos_mappings(ifindex, n_entries, ...) \ + _assert_xgress_qos_mappings(ifindex, TRUE, n_entries, __VA_ARGS__) +#define _assert_egress_qos_mappings(ifindex, n_entries, ...) \ + _assert_xgress_qos_mappings(ifindex, FALSE, n_entries, __VA_ARGS__) static void -_assert_vlan_flags (int ifindex, NMVlanFlags flags) +_assert_vlan_flags(int ifindex, NMVlanFlags flags) { - const NMPlatformLnkVlan *plnk; + const NMPlatformLnkVlan *plnk; - plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, NULL); - g_assert (plnk); - g_assert_cmpint (plnk->flags, ==, flags); + plnk = nm_platform_link_get_lnk_vlan(NM_PLATFORM_GET, ifindex, NULL); + g_assert(plnk); + g_assert_cmpint(plnk->flags, ==, flags); } static void -test_vlan_set_xgress (void) +test_vlan_set_xgress(void) { - int ifindex, ifindex_parent; - - nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME); - ifindex_parent = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; - - nmtstp_run_command_check ("ip link add name %s link %s type vlan id 1245", DEVICE_NAME, PARENT_NAME); - ifindex = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, DEVICE_NAME, NM_LINK_TYPE_VLAN, 100)->ifindex; - - /* ingress-qos-map */ - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 4, 5)); - _assert_ingress_qos_mappings (ifindex, 1, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 3, 7)); - _assert_ingress_qos_mappings (ifindex, 2, - 3, 7, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 3, 8)); - _assert_ingress_qos_mappings (ifindex, 2, - 3, 8, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 0, 4)); - _assert_ingress_qos_mappings (ifindex, 3, - 0, 4, - 3, 8, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 0, G_MAXUINT32)); - _assert_ingress_qos_mappings (ifindex, 3, - 0, G_MAXUINT32, - 3, 8, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 0, G_MAXUINT32 - 1)); - _assert_ingress_qos_mappings (ifindex, 3, - 0, G_MAXUINT32 - 1, - 3, 8, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 0, 5)); - _assert_ingress_qos_mappings (ifindex, 3, - 0, 5, - 3, 8, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 0, 5)); - _assert_ingress_qos_mappings (ifindex, 3, - 0, 5, - 3, 8, - 4, 5); - - /* Set invalid values: */ - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 8, 3)); - _assert_ingress_qos_mappings (ifindex, 3, - 0, 5, - 3, 8, - 4, 5); - - g_assert (nm_platform_link_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, 9, 4)); - _assert_ingress_qos_mappings (ifindex, 3, - 0, 5, - 3, 8, - 4, 5); - - /* egress-qos-map */ - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 7, 3)); - _assert_egress_qos_mappings (ifindex, 1, - 7, 3); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 8, 4)); - _assert_egress_qos_mappings (ifindex, 2, - 7, 3, - 8, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 0, 4)); - _assert_egress_qos_mappings (ifindex, 3, - 0, 4, - 7, 3, - 8, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 1, 4)); - _assert_egress_qos_mappings (ifindex, 4, - 0, 4, - 1, 4, - 7, 3, - 8, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 1, 5)); - _assert_egress_qos_mappings (ifindex, 4, - 0, 4, - 1, 5, - 7, 3, - 8, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 9, 5)); - _assert_egress_qos_mappings (ifindex, 5, - 0, 4, - 1, 5, - 7, 3, - 8, 4, - 9, 5); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 8, 5)); - _assert_egress_qos_mappings (ifindex, 5, - 0, 4, - 1, 5, - 7, 3, - 8, 5, - 9, 5); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 8, 0)); - _assert_egress_qos_mappings (ifindex, 4, - 0, 4, - 1, 5, - 7, 3, - 9, 5); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 0, 0)); - _assert_egress_qos_mappings (ifindex, 3, - 1, 5, - 7, 3, - 9, 5); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 100, 4)); - _assert_egress_qos_mappings (ifindex, 4, - 1, 5, - 7, 3, - 9, 5, - 100, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, G_MAXUINT32, 4)); - _assert_egress_qos_mappings (ifindex, 5, - 1, 5, - 7, 3, - 9, 5, - 100, 4, - G_MAXUINT32, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, G_MAXUINT32, 8)); - _assert_egress_qos_mappings (ifindex, 5, - 1, 5, - 7, 3, - 9, 5, - 100, 4, - G_MAXUINT32, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, G_MAXUINT32, 0)); - _assert_egress_qos_mappings (ifindex, 4, - 1, 5, - 7, 3, - 9, 5, - 100, 4); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 100, 0)); - _assert_egress_qos_mappings (ifindex, 3, - 1, 5, - 7, 3, - 9, 5); - - g_assert (nm_platform_link_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, 1, 0)); - _assert_egress_qos_mappings (ifindex, 2, - 7, 3, - 9, 5); - - { - const NMVlanQosMapping ingress_map[] = { - { .from = 1, .to = 5 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - TRUE, - ingress_map, - G_N_ELEMENTS (ingress_map), - FALSE, - NULL, - 0)); - _assert_ingress_qos_mappings (ifindex, 1, - 1, 5); - } - - { - const NMVlanQosMapping ingress_map[] = { - { .from = 3, .to = 5 }, - { .from = 7, .to = 1655 }, - { .from = 7, .to = 17655 }, - { .from = 5, .to = 754 }, - { .from = 4, .to = 12 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - TRUE, - ingress_map, - G_N_ELEMENTS (ingress_map), - FALSE, - NULL, - 0)); - _assert_ingress_qos_mappings (ifindex, 4, - 3, 5, - 4, 12, - 7, 17655, - 5, 754); - } - - { - const NMVlanQosMapping ingress_map[] = { - { .from = 3, .to = 18 }, - { .from = 6, .to = 121 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - FALSE, - ingress_map, - G_N_ELEMENTS (ingress_map), - FALSE, - NULL, - 0)); - _assert_ingress_qos_mappings (ifindex, 5, - 3, 18, - 4, 12, - 6, 121, - 7, 17655, - 5, 754); - } - - { - const NMVlanQosMapping ingress_map[] = { - { .from = 3, .to = 0 }, - { .from = 6, .to = 7 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - TRUE, - ingress_map, - G_N_ELEMENTS (ingress_map), - FALSE, - NULL, - 0)); - _assert_ingress_qos_mappings (ifindex, 1, - 6, 7); - } - - { - const NMVlanQosMapping ingress_map[] = { - { .from = 1, .to = 5 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - TRUE, - ingress_map, - G_N_ELEMENTS (ingress_map), - FALSE, - NULL, - 0)); - _assert_ingress_qos_mappings (ifindex, 1, - 1, 5); - } - - { - const NMVlanQosMapping egress_map[] = { - { .from = 5, .to = 1 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - FALSE, - NULL, - 0, - TRUE, - egress_map, - G_N_ELEMENTS (egress_map))); - _assert_egress_qos_mappings (ifindex, 1, - 5, 1); - } - - { - const NMVlanQosMapping egress_map[] = { - { .from = 5, .to = 3 }, - { .from = 1655, .to = 5 }, - { .from = 1655, .to = 7 }, - { .from = G_MAXUINT32, .to = 6 }, - { .from = G_MAXUINT32, .to = 8 }, - { .from = 754, .to = 4 }, - { .from = 3, .to = 2 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - FALSE, - NULL, - 0, - TRUE, - egress_map, - G_N_ELEMENTS (egress_map))); - _assert_egress_qos_mappings (ifindex, 5, - 3, 2, - 5, 3, - 754, 4, - 1655, 7, - G_MAXUINT32, 6); - } - - { - const NMVlanQosMapping egress_map[] = { - { .from = 754, .to = 3 }, - { .from = 755, .to = 8 }, - { .from = 1655, .to = 0 }, - { .from = 6, .to = 1 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - FALSE, - NULL, - 0, - FALSE, - egress_map, - G_N_ELEMENTS (egress_map))); - _assert_egress_qos_mappings (ifindex, 5, - 3, 2, - 5, 3, - 6, 1, - 754, 3, - G_MAXUINT32, 6); - } - - { - const NMVlanQosMapping egress_map[] = { - { .from = 6, .to = 0 }, - { .from = 3, .to = 4 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - FALSE, - NULL, - 0, - TRUE, - egress_map, - G_N_ELEMENTS (egress_map))); - _assert_egress_qos_mappings (ifindex, 1, - 3, 4); - } - - { - const NMVlanQosMapping egress_map[] = { - { .from = 1, .to = 5 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - 0, - 0, - FALSE, - NULL, - 0, - TRUE, - egress_map, - G_N_ELEMENTS (egress_map))); - _assert_egress_qos_mappings (ifindex, 1, - 1, 5); - } - - { - const NMVlanQosMapping ingress_map[] = { - { .from = 6, .to = 145 }, - { .from = 4, .to = 1 }, - { .from = 6, .to = 12 }, - }; - const NMVlanQosMapping egress_map[] = { - { .from = 1, .to = 5 }, - { .from = 3232, .to = 7 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP, - NM_VLAN_FLAG_REORDER_HEADERS, - TRUE, - ingress_map, - G_N_ELEMENTS (ingress_map), - TRUE, - egress_map, - G_N_ELEMENTS (egress_map))); - _assert_ingress_qos_mappings (ifindex, 2, - 4, 1, - 6, 12); - _assert_egress_qos_mappings (ifindex, 2, - 1, 5, - 3232, 7); - _assert_vlan_flags (ifindex, NM_VLAN_FLAG_REORDER_HEADERS); - } - - { - const NMVlanQosMapping ingress_map[] = { - { .from = 6, .to = 145 }, - { .from = 4, .to = 1 }, - { .from = 6, .to = 12 }, - }; - const NMVlanQosMapping egress_map[] = { - { .from = 1, .to = 7 }, - { .from = 64, .to = 10 }, - { .from = 64, .to = 10 }, - { .from = 64, .to = 10 }, - { .from = 64, .to = 10 }, - { .from = 3232, .to = 0 }, - { .from = 64, .to = 4 }, - }; - - g_assert (nm_platform_link_vlan_change (NM_PLATFORM_GET, - ifindex, - NM_VLAN_FLAG_GVRP, - NM_VLAN_FLAG_GVRP, - FALSE, - ingress_map, - G_N_ELEMENTS (ingress_map), - FALSE, - egress_map, - G_N_ELEMENTS (egress_map))); - _assert_ingress_qos_mappings (ifindex, 2, - 4, 1, - 6, 12); - _assert_egress_qos_mappings (ifindex, 2, - 1, 7, - 64, 4); - _assert_vlan_flags (ifindex, NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP); - } - - nmtstp_link_delete (NULL, -1, ifindex, DEVICE_NAME, TRUE); - nmtstp_link_delete (NULL, -1, ifindex_parent, PARENT_NAME, TRUE); + int ifindex, ifindex_parent; + + nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME); + ifindex_parent = + nmtstp_assert_wait_for_link(NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; + + nmtstp_run_command_check("ip link add name %s link %s type vlan id 1245", + DEVICE_NAME, + PARENT_NAME); + ifindex = + nmtstp_assert_wait_for_link(NM_PLATFORM_GET, DEVICE_NAME, NM_LINK_TYPE_VLAN, 100)->ifindex; + + /* ingress-qos-map */ + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 4, 5)); + _assert_ingress_qos_mappings(ifindex, 1, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 3, 7)); + _assert_ingress_qos_mappings(ifindex, 2, 3, 7, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 3, 8)); + _assert_ingress_qos_mappings(ifindex, 2, 3, 8, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, 4)); + _assert_ingress_qos_mappings(ifindex, 3, 0, 4, 3, 8, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, G_MAXUINT32)); + _assert_ingress_qos_mappings(ifindex, 3, 0, G_MAXUINT32, 3, 8, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, G_MAXUINT32 - 1)); + _assert_ingress_qos_mappings(ifindex, 3, 0, G_MAXUINT32 - 1, 3, 8, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, 5)); + _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, 5)); + _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5); + + /* Set invalid values: */ + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 8, 3)); + _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5); + + g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 9, 4)); + _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5); + + /* egress-qos-map */ + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 7, 3)); + _assert_egress_qos_mappings(ifindex, 1, 7, 3); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 8, 4)); + _assert_egress_qos_mappings(ifindex, 2, 7, 3, 8, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 0, 4)); + _assert_egress_qos_mappings(ifindex, 3, 0, 4, 7, 3, 8, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 1, 4)); + _assert_egress_qos_mappings(ifindex, 4, 0, 4, 1, 4, 7, 3, 8, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 1, 5)); + _assert_egress_qos_mappings(ifindex, 4, 0, 4, 1, 5, 7, 3, 8, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 9, 5)); + _assert_egress_qos_mappings(ifindex, 5, 0, 4, 1, 5, 7, 3, 8, 4, 9, 5); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 8, 5)); + _assert_egress_qos_mappings(ifindex, 5, 0, 4, 1, 5, 7, 3, 8, 5, 9, 5); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 8, 0)); + _assert_egress_qos_mappings(ifindex, 4, 0, 4, 1, 5, 7, 3, 9, 5); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 0, 0)); + _assert_egress_qos_mappings(ifindex, 3, 1, 5, 7, 3, 9, 5); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 100, 4)); + _assert_egress_qos_mappings(ifindex, 4, 1, 5, 7, 3, 9, 5, 100, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, G_MAXUINT32, 4)); + _assert_egress_qos_mappings(ifindex, 5, 1, 5, 7, 3, 9, 5, 100, 4, G_MAXUINT32, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, G_MAXUINT32, 8)); + _assert_egress_qos_mappings(ifindex, 5, 1, 5, 7, 3, 9, 5, 100, 4, G_MAXUINT32, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, G_MAXUINT32, 0)); + _assert_egress_qos_mappings(ifindex, 4, 1, 5, 7, 3, 9, 5, 100, 4); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 100, 0)); + _assert_egress_qos_mappings(ifindex, 3, 1, 5, 7, 3, 9, 5); + + g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 1, 0)); + _assert_egress_qos_mappings(ifindex, 2, 7, 3, 9, 5); + + { + const NMVlanQosMapping ingress_map[] = { + {.from = 1, .to = 5}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + TRUE, + ingress_map, + G_N_ELEMENTS(ingress_map), + FALSE, + NULL, + 0)); + _assert_ingress_qos_mappings(ifindex, 1, 1, 5); + } + + { + const NMVlanQosMapping ingress_map[] = { + {.from = 3, .to = 5}, + {.from = 7, .to = 1655}, + {.from = 7, .to = 17655}, + {.from = 5, .to = 754}, + {.from = 4, .to = 12}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + TRUE, + ingress_map, + G_N_ELEMENTS(ingress_map), + FALSE, + NULL, + 0)); + _assert_ingress_qos_mappings(ifindex, 4, 3, 5, 4, 12, 7, 17655, 5, 754); + } + + { + const NMVlanQosMapping ingress_map[] = { + {.from = 3, .to = 18}, + {.from = 6, .to = 121}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + FALSE, + ingress_map, + G_N_ELEMENTS(ingress_map), + FALSE, + NULL, + 0)); + _assert_ingress_qos_mappings(ifindex, 5, 3, 18, 4, 12, 6, 121, 7, 17655, 5, 754); + } + + { + const NMVlanQosMapping ingress_map[] = { + {.from = 3, .to = 0}, + {.from = 6, .to = 7}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + TRUE, + ingress_map, + G_N_ELEMENTS(ingress_map), + FALSE, + NULL, + 0)); + _assert_ingress_qos_mappings(ifindex, 1, 6, 7); + } + + { + const NMVlanQosMapping ingress_map[] = { + {.from = 1, .to = 5}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + TRUE, + ingress_map, + G_N_ELEMENTS(ingress_map), + FALSE, + NULL, + 0)); + _assert_ingress_qos_mappings(ifindex, 1, 1, 5); + } + + { + const NMVlanQosMapping egress_map[] = { + {.from = 5, .to = 1}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + FALSE, + NULL, + 0, + TRUE, + egress_map, + G_N_ELEMENTS(egress_map))); + _assert_egress_qos_mappings(ifindex, 1, 5, 1); + } + + { + const NMVlanQosMapping egress_map[] = { + {.from = 5, .to = 3}, + {.from = 1655, .to = 5}, + {.from = 1655, .to = 7}, + {.from = G_MAXUINT32, .to = 6}, + {.from = G_MAXUINT32, .to = 8}, + {.from = 754, .to = 4}, + {.from = 3, .to = 2}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + FALSE, + NULL, + 0, + TRUE, + egress_map, + G_N_ELEMENTS(egress_map))); + _assert_egress_qos_mappings(ifindex, 5, 3, 2, 5, 3, 754, 4, 1655, 7, G_MAXUINT32, 6); + } + + { + const NMVlanQosMapping egress_map[] = { + {.from = 754, .to = 3}, + {.from = 755, .to = 8}, + {.from = 1655, .to = 0}, + {.from = 6, .to = 1}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + FALSE, + NULL, + 0, + FALSE, + egress_map, + G_N_ELEMENTS(egress_map))); + _assert_egress_qos_mappings(ifindex, 5, 3, 2, 5, 3, 6, 1, 754, 3, G_MAXUINT32, 6); + } + + { + const NMVlanQosMapping egress_map[] = { + {.from = 6, .to = 0}, + {.from = 3, .to = 4}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + FALSE, + NULL, + 0, + TRUE, + egress_map, + G_N_ELEMENTS(egress_map))); + _assert_egress_qos_mappings(ifindex, 1, 3, 4); + } + + { + const NMVlanQosMapping egress_map[] = { + {.from = 1, .to = 5}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + 0, + 0, + FALSE, + NULL, + 0, + TRUE, + egress_map, + G_N_ELEMENTS(egress_map))); + _assert_egress_qos_mappings(ifindex, 1, 1, 5); + } + + { + const NMVlanQosMapping ingress_map[] = { + {.from = 6, .to = 145}, + {.from = 4, .to = 1}, + {.from = 6, .to = 12}, + }; + const NMVlanQosMapping egress_map[] = { + {.from = 1, .to = 5}, + {.from = 3232, .to = 7}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP, + NM_VLAN_FLAG_REORDER_HEADERS, + TRUE, + ingress_map, + G_N_ELEMENTS(ingress_map), + TRUE, + egress_map, + G_N_ELEMENTS(egress_map))); + _assert_ingress_qos_mappings(ifindex, 2, 4, 1, 6, 12); + _assert_egress_qos_mappings(ifindex, 2, 1, 5, 3232, 7); + _assert_vlan_flags(ifindex, NM_VLAN_FLAG_REORDER_HEADERS); + } + + { + const NMVlanQosMapping ingress_map[] = { + {.from = 6, .to = 145}, + {.from = 4, .to = 1}, + {.from = 6, .to = 12}, + }; + const NMVlanQosMapping egress_map[] = { + {.from = 1, .to = 7}, + {.from = 64, .to = 10}, + {.from = 64, .to = 10}, + {.from = 64, .to = 10}, + {.from = 64, .to = 10}, + {.from = 3232, .to = 0}, + {.from = 64, .to = 4}, + }; + + g_assert(nm_platform_link_vlan_change(NM_PLATFORM_GET, + ifindex, + NM_VLAN_FLAG_GVRP, + NM_VLAN_FLAG_GVRP, + FALSE, + ingress_map, + G_N_ELEMENTS(ingress_map), + FALSE, + egress_map, + G_N_ELEMENTS(egress_map))); + _assert_ingress_qos_mappings(ifindex, 2, 4, 1, 6, 12); + _assert_egress_qos_mappings(ifindex, 2, 1, 7, 64, 4); + _assert_vlan_flags(ifindex, NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP); + } + + nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE); + nmtstp_link_delete(NULL, -1, ifindex_parent, PARENT_NAME, TRUE); } /*****************************************************************************/ static void -test_create_many_links_do (guint n_devices) +test_create_many_links_do(guint n_devices) { - gint64 time, start_time = nm_utils_get_monotonic_timestamp_nsec (); - guint i; - char name[64]; - const NMPlatformLink *pllink; - gs_unref_array GArray *ifindexes = g_array_sized_new (FALSE, FALSE, sizeof (int), n_devices); - const int EX = ((int) (nmtst_get_rand_uint32 () % 4)) - 1; + gint64 time, start_time = nm_utils_get_monotonic_timestamp_nsec(); + guint i; + char name[64]; + const NMPlatformLink *pllink; + gs_unref_array GArray *ifindexes = g_array_sized_new(FALSE, FALSE, sizeof(int), n_devices); + const int EX = ((int) (nmtst_get_rand_uint32() % 4)) - 1; - g_assert (EX >= -1 && EX <= 2); + g_assert(EX >= -1 && EX <= 2); - _LOGI (">>> create devices (EX=%d)...", EX); + _LOGI(">>> create devices (EX=%d)...", EX); - for (i = 0; i < n_devices; i++) { - nm_sprintf_buf (name, "t-%05u", i); - if (EX == 2) { - /* This mode is different from letting nmtstp_link_dummy_add() - * because in this case we don't process any platform events - * while adding all the links. */ - nmtstp_run_command_check ("ip link add %s type dummy", name); - } else - nmtstp_link_dummy_add (NULL, EX, name); - } + for (i = 0; i < n_devices; i++) { + nm_sprintf_buf(name, "t-%05u", i); + if (EX == 2) { + /* This mode is different from letting nmtstp_link_dummy_add() + * because in this case we don't process any platform events + * while adding all the links. */ + nmtstp_run_command_check("ip link add %s type dummy", name); + } else + nmtstp_link_dummy_add(NULL, EX, name); + } - _LOGI (">>> process events after creating devices..."); + _LOGI(">>> process events after creating devices..."); - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events(NM_PLATFORM_GET); - _LOGI (">>> check devices..."); + _LOGI(">>> check devices..."); - for (i = 0; i < n_devices; i++) { - nm_sprintf_buf (name, "t-%05u", i); + for (i = 0; i < n_devices; i++) { + nm_sprintf_buf(name, "t-%05u", i); - pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, name); - g_assert (pllink); - g_assert_cmpint (pllink->type, ==, NM_LINK_TYPE_DUMMY); - g_assert_cmpstr (pllink->name, ==, name); + pllink = nm_platform_link_get_by_ifname(NM_PLATFORM_GET, name); + g_assert(pllink); + g_assert_cmpint(pllink->type, ==, NM_LINK_TYPE_DUMMY); + g_assert_cmpstr(pllink->name, ==, name); - g_array_append_val (ifindexes, pllink->ifindex); - } + g_array_append_val(ifindexes, pllink->ifindex); + } - _LOGI (">>> delete devices..."); + _LOGI(">>> delete devices..."); - g_assert_cmpint (ifindexes->len, ==, n_devices); - for (i = 0; i < n_devices; i++) { - nm_sprintf_buf (name, "t-%05u", i); + g_assert_cmpint(ifindexes->len, ==, n_devices); + for (i = 0; i < n_devices; i++) { + nm_sprintf_buf(name, "t-%05u", i); - if (EX == 2) - nmtstp_run_command_check ("ip link delete %s", name); - else - nmtstp_link_delete (NULL, EX, g_array_index (ifindexes, int, i), name, TRUE); - } + if (EX == 2) + nmtstp_run_command_check("ip link delete %s", name); + else + nmtstp_link_delete(NULL, EX, g_array_index(ifindexes, int, i), name, TRUE); + } - _LOGI (">>> process events after deleting devices..."); - nm_platform_process_events (NM_PLATFORM_GET); + _LOGI(">>> process events after deleting devices..."); + nm_platform_process_events(NM_PLATFORM_GET); - time = nm_utils_get_monotonic_timestamp_nsec () - start_time; - _LOGI (">>> finished in %ld.%09ld seconds", (long) (time / NM_UTILS_NSEC_PER_SEC), (long) (time % NM_UTILS_NSEC_PER_SEC)); + time = nm_utils_get_monotonic_timestamp_nsec() - start_time; + _LOGI(">>> finished in %ld.%09ld seconds", + (long) (time / NM_UTILS_NSEC_PER_SEC), + (long) (time % NM_UTILS_NSEC_PER_SEC)); } static void -test_create_many_links (gconstpointer user_data) +test_create_many_links(gconstpointer user_data) { - guint n_devices = GPOINTER_TO_UINT (user_data); + guint n_devices = GPOINTER_TO_UINT(user_data); - if (n_devices > 100 && nmtst_test_quick ()) { - g_print ("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", g_get_prgname () ?: "test-link-linux"); - g_test_skip ("Skip long running test"); - return; - } + if (n_devices > 100 && nmtst_test_quick()) { + g_print("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", + g_get_prgname() ?: "test-link-linux"); + g_test_skip("Skip long running test"); + return; + } - test_create_many_links_do (n_devices); + test_create_many_links_do(n_devices); } /*****************************************************************************/ static void -test_nl_bugs_veth (void) +test_nl_bugs_veth(void) { - const char *IFACE_VETH0 = "nm-test-veth0"; - const char *IFACE_VETH1 = "nm-test-veth1"; - int ifindex_veth0, ifindex_veth1; - int i; - const NMPlatformLink *pllink_veth0, *pllink_veth1; - gs_free_error GError *error = NULL; - NMTstpNamespaceHandle *ns_handle = NULL; - - /* create veth pair. */ - ifindex_veth0 = nmtstp_link_veth_add (NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex; - ifindex_veth1 = nmtstp_link_get_typed (NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex; - - /* assert that nm_platform_link_veth_get_properties() returns the expected peer ifindexes. */ - g_assert (nm_platform_link_veth_get_properties (NM_PLATFORM_GET, ifindex_veth0, &i)); - g_assert_cmpint (i, ==, ifindex_veth1); - - g_assert (nm_platform_link_veth_get_properties (NM_PLATFORM_GET, ifindex_veth1, &i)); - g_assert_cmpint (i, ==, ifindex_veth0); - - /* assert that NMPlatformLink.parent is the peer-ifindex. */ - pllink_veth0 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth0); - g_assert (pllink_veth0); - if (pllink_veth0->parent == 0) { - /* Kernels prior to 4.1 dated 21 June, 2015 don't support exposing the veth peer - * as IFA_LINK. skip the remainder of the test. */ - goto out; - } - g_assert_cmpint (pllink_veth0->parent, ==, ifindex_veth1); - - /* The following tests whether we have a workaround for kernel bug - * https://bugzilla.redhat.com/show_bug.cgi?id=1285827 in place. */ - pllink_veth1 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth1); - g_assert (pllink_veth1); - g_assert_cmpint (pllink_veth1->parent, ==, ifindex_veth0); - - /* move one veth peer to another namespace and check that the - * parent/IFLA_LINK of the remaining peer properly updates - * (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */ - ns_handle = nmtstp_namespace_create (CLONE_NEWNET, &error); - g_assert_no_error (error); - g_assert (ns_handle); - - nmtstp_run_command_check ("ip link set %s netns %ld", IFACE_VETH1, (long) nmtstp_namespace_handle_get_pid (ns_handle)); - NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); - nm_platform_process_events (NM_PLATFORM_GET); - - pllink_veth1 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth1); - pllink_veth0 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth0); - if ( !pllink_veth1 - && pllink_veth0 - && pllink_veth0->parent == NM_PLATFORM_LINK_OTHER_NETNS) { - break; - } - }); + const char * IFACE_VETH0 = "nm-test-veth0"; + const char * IFACE_VETH1 = "nm-test-veth1"; + int ifindex_veth0, ifindex_veth1; + int i; + const NMPlatformLink *pllink_veth0, *pllink_veth1; + gs_free_error GError * error = NULL; + NMTstpNamespaceHandle *ns_handle = NULL; + + /* create veth pair. */ + ifindex_veth0 = nmtstp_link_veth_add(NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex; + ifindex_veth1 = + nmtstp_link_get_typed(NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex; + + /* assert that nm_platform_link_veth_get_properties() returns the expected peer ifindexes. */ + g_assert(nm_platform_link_veth_get_properties(NM_PLATFORM_GET, ifindex_veth0, &i)); + g_assert_cmpint(i, ==, ifindex_veth1); + + g_assert(nm_platform_link_veth_get_properties(NM_PLATFORM_GET, ifindex_veth1, &i)); + g_assert_cmpint(i, ==, ifindex_veth0); + + /* assert that NMPlatformLink.parent is the peer-ifindex. */ + pllink_veth0 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth0); + g_assert(pllink_veth0); + if (pllink_veth0->parent == 0) { + /* Kernels prior to 4.1 dated 21 June, 2015 don't support exposing the veth peer + * as IFA_LINK. skip the remainder of the test. */ + goto out; + } + g_assert_cmpint(pllink_veth0->parent, ==, ifindex_veth1); + + /* The following tests whether we have a workaround for kernel bug + * https://bugzilla.redhat.com/show_bug.cgi?id=1285827 in place. */ + pllink_veth1 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth1); + g_assert(pllink_veth1); + g_assert_cmpint(pllink_veth1->parent, ==, ifindex_veth0); + + /* move one veth peer to another namespace and check that the + * parent/IFLA_LINK of the remaining peer properly updates + * (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */ + ns_handle = nmtstp_namespace_create(CLONE_NEWNET, &error); + g_assert_no_error(error); + g_assert(ns_handle); + + nmtstp_run_command_check("ip link set %s netns %ld", + IFACE_VETH1, + (long) nmtstp_namespace_handle_get_pid(ns_handle)); + NMTST_WAIT_ASSERT(100, { + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); + nm_platform_process_events(NM_PLATFORM_GET); + + pllink_veth1 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth1); + pllink_veth0 = nm_platform_link_get(NM_PLATFORM_GET, ifindex_veth0); + if (!pllink_veth1 && pllink_veth0 && pllink_veth0->parent == NM_PLATFORM_LINK_OTHER_NETNS) { + break; + } + }); out: - nmtstp_link_delete (NULL, -1, ifindex_veth0, IFACE_VETH0, TRUE); - g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth0, IFACE_VETH0)); - g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth1, IFACE_VETH1)); - nmtstp_namespace_handle_release (ns_handle); + nmtstp_link_delete(NULL, -1, ifindex_veth0, IFACE_VETH0, TRUE); + g_assert(!nmtstp_link_get(NM_PLATFORM_GET, ifindex_veth0, IFACE_VETH0)); + g_assert(!nmtstp_link_get(NM_PLATFORM_GET, ifindex_veth1, IFACE_VETH1)); + nmtstp_namespace_handle_release(ns_handle); } /*****************************************************************************/ static void -test_nl_bugs_spuroius_newlink (void) +test_nl_bugs_spuroius_newlink(void) { - const char *IFACE_BOND0 = "nm-test-bond0"; - const char *IFACE_DUMMY0 = "nm-test-dummy0"; - int ifindex_bond0, ifindex_dummy0; - const NMPlatformLink *pllink; - gboolean wait_for_settle; + const char * IFACE_BOND0 = "nm-test-bond0"; + const char * IFACE_DUMMY0 = "nm-test-dummy0"; + int ifindex_bond0, ifindex_dummy0; + const NMPlatformLink *pllink; + gboolean wait_for_settle; - /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ + /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ - nmtstp_run_command_check ("ip link add %s type dummy", IFACE_DUMMY0); - ifindex_dummy0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex; + nmtstp_run_command_check("ip link add %s type dummy", IFACE_DUMMY0); + ifindex_dummy0 = + nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100) + ->ifindex; - nmtstp_run_command_check ("ip link add %s type bond", IFACE_BOND0); - ifindex_bond0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex; + nmtstp_run_command_check("ip link add %s type bond", IFACE_BOND0); + ifindex_bond0 = + nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex; - nmtstp_link_set_updown (NULL, -1, ifindex_bond0, TRUE); + nmtstp_link_set_updown(NULL, -1, ifindex_bond0, TRUE); - nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BOND0); - NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); + nmtstp_run_command_check("ip link set %s master %s", IFACE_DUMMY0, IFACE_BOND0); + NMTST_WAIT_ASSERT(100, { + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0); - g_assert (pllink); - if (pllink->master == ifindex_bond0) - break; - }); + pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0); + g_assert(pllink); + if (pllink->master == ifindex_bond0) + break; + }); - nmtstp_run_command_check ("ip link del %s", IFACE_BOND0); + nmtstp_run_command_check("ip link del %s", IFACE_BOND0); - wait_for_settle = TRUE; - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); + wait_for_settle = TRUE; + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); again: - nm_platform_process_events (NM_PLATFORM_GET); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_bond0); - g_assert (!pllink); - - if (wait_for_settle) { - wait_for_settle = FALSE; - NMTST_WAIT (300, { nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); }); - goto again; - } - - g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_bond0, IFACE_BOND0)); - nmtstp_link_delete (NULL, -1, ifindex_dummy0, IFACE_DUMMY0, TRUE); + nm_platform_process_events(NM_PLATFORM_GET); + pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_bond0); + g_assert(!pllink); + + if (wait_for_settle) { + wait_for_settle = FALSE; + NMTST_WAIT(300, { nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); }); + goto again; + } + + g_assert(!nmtstp_link_get(NM_PLATFORM_GET, ifindex_bond0, IFACE_BOND0)); + nmtstp_link_delete(NULL, -1, ifindex_dummy0, IFACE_DUMMY0, TRUE); } /*****************************************************************************/ static void -test_nl_bugs_spuroius_dellink (void) +test_nl_bugs_spuroius_dellink(void) { - const char *IFACE_BRIDGE0 = "nm-test-bridge0"; - const char *IFACE_DUMMY0 = "nm-test-dummy0"; - int ifindex_bridge0, ifindex_dummy0; - const NMPlatformLink *pllink; - gboolean wait_for_settle; + const char * IFACE_BRIDGE0 = "nm-test-bridge0"; + const char * IFACE_DUMMY0 = "nm-test-dummy0"; + int ifindex_bridge0, ifindex_dummy0; + const NMPlatformLink *pllink; + gboolean wait_for_settle; - /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ + /* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */ - nmtstp_run_command_check ("ip link add %s type dummy", IFACE_DUMMY0); - ifindex_dummy0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex; + nmtstp_run_command_check("ip link add %s type dummy", IFACE_DUMMY0); + ifindex_dummy0 = + nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100) + ->ifindex; - nmtstp_run_command_check ("ip link add %s type bridge", IFACE_BRIDGE0); - ifindex_bridge0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100)->ifindex; + nmtstp_run_command_check("ip link add %s type bridge", IFACE_BRIDGE0); + ifindex_bridge0 = + nmtstp_assert_wait_for_link(NM_PLATFORM_GET, IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100) + ->ifindex; - nmtstp_link_set_updown (NULL, -1, ifindex_bridge0, TRUE); + nmtstp_link_set_updown(NULL, -1, ifindex_bridge0, TRUE); - nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BRIDGE0); - NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); + nmtstp_run_command_check("ip link set %s master %s", IFACE_DUMMY0, IFACE_BRIDGE0); + NMTST_WAIT_ASSERT(100, { + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0); - g_assert (pllink); - if (pllink->master == ifindex_bridge0) - break; - }); + pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0); + g_assert(pllink); + if (pllink->master == ifindex_bridge0) + break; + }); - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events(NM_PLATFORM_GET); - nmtstp_run_command_check ("ip link set %s nomaster", IFACE_DUMMY0); + nmtstp_run_command_check("ip link set %s nomaster", IFACE_DUMMY0); - wait_for_settle = TRUE; - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); + wait_for_settle = TRUE; + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); again: - nm_platform_process_events (NM_PLATFORM_GET); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_bridge0); - g_assert (pllink); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0); - g_assert (pllink); - g_assert_cmpint (pllink->parent, ==, 0); - - if (wait_for_settle) { - wait_for_settle = FALSE; - NMTST_WAIT (300, { nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); }); - goto again; - } - - nmtstp_link_delete (NULL, -1, ifindex_bridge0, IFACE_BRIDGE0, TRUE); - nmtstp_link_delete (NULL, -1, ifindex_dummy0, IFACE_DUMMY0, TRUE); + nm_platform_process_events(NM_PLATFORM_GET); + pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_bridge0); + g_assert(pllink); + pllink = nm_platform_link_get(NM_PLATFORM_GET, ifindex_dummy0); + g_assert(pllink); + g_assert_cmpint(pllink->parent, ==, 0); + + if (wait_for_settle) { + wait_for_settle = FALSE; + NMTST_WAIT(300, { nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); }); + goto again; + } + + nmtstp_link_delete(NULL, -1, ifindex_bridge0, IFACE_BRIDGE0, TRUE); + nmtstp_link_delete(NULL, -1, ifindex_dummy0, IFACE_DUMMY0, TRUE); } /*****************************************************************************/ static void -_test_netns_setup (gpointer fixture, gconstpointer test_data) +_test_netns_setup(gpointer fixture, gconstpointer test_data) { - /* the singleton platform instance has netns support disabled. - * Destroy the instance before the test and re-create it afterwards. */ - g_object_unref (NM_PLATFORM_GET); + /* the singleton platform instance has netns support disabled. + * Destroy the instance before the test and re-create it afterwards. */ + g_object_unref(NM_PLATFORM_GET); } static void -_test_netns_teardown (gpointer fixture, gconstpointer test_data) +_test_netns_teardown(gpointer fixture, gconstpointer test_data) { - nmtstp_setup_platform (); + nmtstp_setup_platform(); } static NMPlatform * -_test_netns_create_platform (void) +_test_netns_create_platform(void) { - NMPNetns *netns; - NMPlatform *platform; + NMPNetns * netns; + NMPlatform *platform; - netns = nmp_netns_new (); - g_assert (NMP_IS_NETNS (netns)); + netns = nmp_netns_new(); + g_assert(NMP_IS_NETNS(netns)); - platform = nm_linux_platform_new (TRUE, TRUE); - g_assert (NM_IS_LINUX_PLATFORM (platform)); + platform = nm_linux_platform_new(TRUE, TRUE); + g_assert(NM_IS_LINUX_PLATFORM(platform)); - nmp_netns_pop (netns); - g_object_unref (netns); + nmp_netns_pop(netns); + g_object_unref(netns); - return platform; + return platform; } static gboolean -_test_netns_check_skip (void) +_test_netns_check_skip(void) { - static int support = -1; - static int support_errsv = 0; - NMPNetns *netns; - gs_unref_object NMPNetns *netns2 = NULL; - - netns = nmp_netns_get_current (); - if (!netns) { - g_test_skip ("No netns support"); - return TRUE; - } - - g_assert (nmp_netns_get_fd_net (netns) > 0); - - if (support == -1) { - support = (setns (nmp_netns_get_fd_net (netns), CLONE_NEWNET) == 0); - if (!support) - support_errsv = errno; - } - if (!support) { - _LOGD ("setns() failed with \"%s\". This indicates missing support (valgrind?)", nm_strerror_native (support_errsv)); - g_test_skip ("No netns support (setns failed)"); - return TRUE; - } - - netns2 = nmp_netns_new (); - if (!netns2) { - /* skip tests for https://bugzilla.gnome.org/show_bug.cgi?id=790214 */ - g_assert_cmpint (errno, ==, EINVAL); - g_test_skip ("No netns support to create another netns"); - return TRUE; - } - nmp_netns_pop (netns2); - - return FALSE; + static int support = -1; + static int support_errsv = 0; + NMPNetns * netns; + gs_unref_object NMPNetns *netns2 = NULL; + + netns = nmp_netns_get_current(); + if (!netns) { + g_test_skip("No netns support"); + return TRUE; + } + + g_assert(nmp_netns_get_fd_net(netns) > 0); + + if (support == -1) { + support = (setns(nmp_netns_get_fd_net(netns), CLONE_NEWNET) == 0); + if (!support) + support_errsv = errno; + } + if (!support) { + _LOGD("setns() failed with \"%s\". This indicates missing support (valgrind?)", + nm_strerror_native(support_errsv)); + g_test_skip("No netns support (setns failed)"); + return TRUE; + } + + netns2 = nmp_netns_new(); + if (!netns2) { + /* skip tests for https://bugzilla.gnome.org/show_bug.cgi?id=790214 */ + g_assert_cmpint(errno, ==, EINVAL); + g_test_skip("No netns support to create another netns"); + return TRUE; + } + nmp_netns_pop(netns2); + + return FALSE; } static gboolean -_check_sysctl_skip (void) +_check_sysctl_skip(void) { - if (access ("/proc/sys/net/ipv4/ip_forward", W_OK) == -1) { - g_test_skip ("Can not write sysctls"); - return TRUE; - } + if (access("/proc/sys/net/ipv4/ip_forward", W_OK) == -1) { + g_test_skip("Can not write sysctls"); + return TRUE; + } - return FALSE; + return FALSE; } /*****************************************************************************/ -#define _sysctl_assert_eq(plat, path, value) \ - G_STMT_START { \ - gs_free char *_val = NULL; \ - \ - _val = nm_platform_sysctl_get (plat, NMP_SYSCTL_PATHID_ABSOLUTE (path)); \ - g_assert_cmpstr (_val, ==, value); \ - } G_STMT_END +#define _sysctl_assert_eq(plat, path, value) \ + G_STMT_START \ + { \ + gs_free char *_val = NULL; \ + \ + _val = nm_platform_sysctl_get(plat, NMP_SYSCTL_PATHID_ABSOLUTE(path)); \ + g_assert_cmpstr(_val, ==, value); \ + } \ + G_STMT_END static void -test_netns_general (gpointer fixture, gconstpointer test_data) +test_netns_general(gpointer fixture, gconstpointer test_data) { - gs_unref_object NMPlatform *platform_1 = NULL; - gs_unref_object NMPlatform *platform_2 = NULL; - NMPNetns *netns_tmp; - char sbuf[100]; - int i, j, k; - gboolean ethtool_support; - NMPUtilsEthtoolDriverInfo driver_info; - - if (_test_netns_check_skip ()) - return; - - if (_check_sysctl_skip ()) - return; - - platform_1 = nm_linux_platform_new (TRUE, TRUE); - platform_2 = _test_netns_create_platform (); - - /* add some dummy devices. The "other-*" devices are there to bump the ifindex */ - for (k = 0; k < 2; k++) { - NMPlatform *p = (k == 0 ? platform_1 : platform_2); - const char *id = (k == 0 ? "a" : "b"); - - for (i = 0, j = nmtst_get_rand_uint32 () % 5; i < j; i++) - _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "other-a-%s-%02d", id, i)); - - _ADD_DUMMY (p, "dummy1_"); - - for (i = 0, j = nmtst_get_rand_uint32 () % 5; i < j; i++) - _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "other-b-%s-%02d", id, i)); - - _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "dummy2%s", id)); - - for (i = 0, j = nmtst_get_rand_uint32 () % 5; i < j; i++) - _ADD_DUMMY (p, nm_sprintf_buf (sbuf, "other-c-%s-%02d", id, i)); - } - - _sysctl_assert_eq (platform_1,"/sys/devices/virtual/net/dummy1_/ifindex", - nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex)); - _sysctl_assert_eq (platform_1, "/sys/devices/virtual/net/dummy2a/ifindex", - nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex)); - _sysctl_assert_eq (platform_1, "/sys/devices/virtual/net/dummy2b/ifindex", - NULL); - - _sysctl_assert_eq (platform_2, "/sys/devices/virtual/net/dummy1_/ifindex", - nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex)); - _sysctl_assert_eq (platform_2, "/sys/devices/virtual/net/dummy2a/ifindex", - NULL); - _sysctl_assert_eq (platform_2, "/sys/devices/virtual/net/dummy2b/ifindex", - nm_sprintf_buf (sbuf, "%d", nmtstp_link_get_typed (platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex)); - - for (i = 0; i < 10; i++) { - NMPlatform *pl; - const char *path; - - j = nmtst_get_rand_uint32 () % 2; - - if (nmtst_get_rand_uint32 () % 2) { - pl = platform_1; - if (nmtst_get_rand_uint32 () % 2) - path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6"; - else - path = "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6"; - } else { - pl = platform_2; - if (nmtst_get_rand_uint32 () % 2) - path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6"; - else - path = "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6"; - } - g_assert (nm_platform_sysctl_set (pl, NMP_SYSCTL_PATHID_ABSOLUTE (path), nm_sprintf_buf (sbuf, "%d", j))); - _sysctl_assert_eq (pl, path, nm_sprintf_buf (sbuf, "%d", j)); - } - - _sysctl_assert_eq (platform_1, "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6", NULL); - _sysctl_assert_eq (platform_2, "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6", NULL); - - /* Kernels prior to 3.19 dated 8 February, 2015 don't support ethtool -i for dummy devices. - * Work around that and skip asserts that are known to fail. */ - ethtool_support = nmtstp_run_command ("ethtool -i dummy1_ > /dev/null") == 0; - if (ethtool_support) { - g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); - g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); - g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy1_ > /dev/null"), ==, 0); - g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a > /dev/null"), ==, 0); - g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b 2> /dev/null"), !=, 0); - } - - g_assert (nm_platform_netns_push (platform_2, &netns_tmp)); - - if (ethtool_support) { - g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); - g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); - g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy1_ > /dev/null"), ==, 0); - g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a 2> /dev/null"), !=, 0); - g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b > /dev/null"), ==, 0); - } - - nmp_netns_pop (netns_tmp); + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + NMPNetns * netns_tmp; + char sbuf[100]; + int i, j, k; + gboolean ethtool_support; + NMPUtilsEthtoolDriverInfo driver_info; + + if (_test_netns_check_skip()) + return; + + if (_check_sysctl_skip()) + return; + + platform_1 = nm_linux_platform_new(TRUE, TRUE); + platform_2 = _test_netns_create_platform(); + + /* add some dummy devices. The "other-*" devices are there to bump the ifindex */ + for (k = 0; k < 2; k++) { + NMPlatform *p = (k == 0 ? platform_1 : platform_2); + const char *id = (k == 0 ? "a" : "b"); + + for (i = 0, j = nmtst_get_rand_uint32() % 5; i < j; i++) + _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "other-a-%s-%02d", id, i)); + + _ADD_DUMMY(p, "dummy1_"); + + for (i = 0, j = nmtst_get_rand_uint32() % 5; i < j; i++) + _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "other-b-%s-%02d", id, i)); + + _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "dummy2%s", id)); + + for (i = 0, j = nmtst_get_rand_uint32() % 5; i < j; i++) + _ADD_DUMMY(p, nm_sprintf_buf(sbuf, "other-c-%s-%02d", id, i)); + } + + _sysctl_assert_eq( + platform_1, + "/sys/devices/virtual/net/dummy1_/ifindex", + nm_sprintf_buf( + sbuf, + "%d", + nmtstp_link_get_typed(platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex)); + _sysctl_assert_eq( + platform_1, + "/sys/devices/virtual/net/dummy2a/ifindex", + nm_sprintf_buf( + sbuf, + "%d", + nmtstp_link_get_typed(platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex)); + _sysctl_assert_eq(platform_1, "/sys/devices/virtual/net/dummy2b/ifindex", NULL); + + _sysctl_assert_eq( + platform_2, + "/sys/devices/virtual/net/dummy1_/ifindex", + nm_sprintf_buf( + sbuf, + "%d", + nmtstp_link_get_typed(platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex)); + _sysctl_assert_eq(platform_2, "/sys/devices/virtual/net/dummy2a/ifindex", NULL); + _sysctl_assert_eq( + platform_2, + "/sys/devices/virtual/net/dummy2b/ifindex", + nm_sprintf_buf( + sbuf, + "%d", + nmtstp_link_get_typed(platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex)); + + for (i = 0; i < 10; i++) { + NMPlatform *pl; + const char *path; + + j = nmtst_get_rand_uint32() % 2; + + if (nmtst_get_rand_uint32() % 2) { + pl = platform_1; + if (nmtst_get_rand_uint32() % 2) + path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6"; + else + path = "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6"; + } else { + pl = platform_2; + if (nmtst_get_rand_uint32() % 2) + path = "/proc/sys/net/ipv6/conf/dummy1_/disable_ipv6"; + else + path = "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6"; + } + g_assert(nm_platform_sysctl_set(pl, + NMP_SYSCTL_PATHID_ABSOLUTE(path), + nm_sprintf_buf(sbuf, "%d", j))); + _sysctl_assert_eq(pl, path, nm_sprintf_buf(sbuf, "%d", j)); + } + + _sysctl_assert_eq(platform_1, "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6", NULL); + _sysctl_assert_eq(platform_2, "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6", NULL); + + /* Kernels prior to 3.19 dated 8 February, 2015 don't support ethtool -i for dummy devices. + * Work around that and skip asserts that are known to fail. */ + ethtool_support = nmtstp_run_command("ethtool -i dummy1_ > /dev/null") == 0; + if (ethtool_support) { + g_assert(nmp_utils_ethtool_get_driver_info( + nmtstp_link_get_typed(platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, + &driver_info)); + g_assert(nmp_utils_ethtool_get_driver_info( + nmtstp_link_get_typed(platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex, + &driver_info)); + g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0); + g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2a > /dev/null"), ==, 0); + g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2b 2> /dev/null"), !=, 0); + } + + g_assert(nm_platform_netns_push(platform_2, &netns_tmp)); + + if (ethtool_support) { + g_assert(nmp_utils_ethtool_get_driver_info( + nmtstp_link_get_typed(platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, + &driver_info)); + g_assert(nmp_utils_ethtool_get_driver_info( + nmtstp_link_get_typed(platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex, + &driver_info)); + g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0); + g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2a 2> /dev/null"), !=, 0); + g_assert_cmpint(nmtstp_run_command("ethtool -i dummy2b > /dev/null"), ==, 0); + } + + nmp_netns_pop(netns_tmp); } /*****************************************************************************/ static void -test_netns_set_netns (gpointer fixture, gconstpointer test_data) +test_netns_set_netns(gpointer fixture, gconstpointer test_data) { - NMPlatform *platforms[3]; - gs_unref_object NMPlatform *platform_0 = NULL; - gs_unref_object NMPlatform *platform_1 = NULL; - gs_unref_object NMPlatform *platform_2 = NULL; - nm_auto_pop_netns NMPNetns *netns_pop = NULL; + NMPlatform * platforms[3]; + gs_unref_object NMPlatform *platform_0 = NULL; + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; - if (_test_netns_check_skip ()) - return; + if (_test_netns_check_skip()) + return; - platforms[0] = platform_0 = nm_linux_platform_new (TRUE, TRUE); - platforms[1] = platform_1 = _test_netns_create_platform (); - platforms[2] = platform_2 = _test_netns_create_platform (); + platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE); + platforms[1] = platform_1 = _test_netns_create_platform(); + platforms[2] = platform_2 = _test_netns_create_platform(); - nmtstp_netns_select_random (platforms, G_N_ELEMENTS (platforms), &netns_pop); + nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop); #define LINK_MOVE_NAME "link-move" - g_assert (!nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); - g_assert (!nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); - _ADD_DUMMY (platform_1, LINK_MOVE_NAME); - g_assert ( nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); - g_assert (!nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); - g_assert (nm_platform_link_set_netns (platform_1, - nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)->ifindex, - nmp_netns_get_fd_net (nm_platform_netns_get (platform_2)))); - g_assert (!nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); - g_assert (!nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); - nmtstp_assert_wait_for_link (platform_2, LINK_MOVE_NAME, NM_LINK_TYPE_DUMMY, 100); - g_assert (!nm_platform_link_get_by_ifname (platform_1, LINK_MOVE_NAME)); - g_assert ( nm_platform_link_get_by_ifname (platform_2, LINK_MOVE_NAME)); + g_assert(!nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME)); + g_assert(!nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME)); + _ADD_DUMMY(platform_1, LINK_MOVE_NAME); + g_assert(nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME)); + g_assert(!nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME)); + g_assert(nm_platform_link_set_netns( + platform_1, + nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME)->ifindex, + nmp_netns_get_fd_net(nm_platform_netns_get(platform_2)))); + g_assert(!nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME)); + g_assert(!nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME)); + nmtstp_assert_wait_for_link(platform_2, LINK_MOVE_NAME, NM_LINK_TYPE_DUMMY, 100); + g_assert(!nm_platform_link_get_by_ifname(platform_1, LINK_MOVE_NAME)); + g_assert(nm_platform_link_get_by_ifname(platform_2, LINK_MOVE_NAME)); } /*****************************************************************************/ static char * -_get_current_namespace_id (int ns_type) +_get_current_namespace_id(int ns_type) { - const char *p; - GError *error = NULL; - char *id; - - switch (ns_type) { - case CLONE_NEWNET: - p = "/proc/self/ns/net"; - break; - case CLONE_NEWNS: - p = "/proc/self/ns/mnt"; - break; - default: - g_assert_not_reached (); - } - - id = g_file_read_link (p, &error); - g_assert_no_error (error); - g_assert (id); - return id; + const char *p; + GError * error = NULL; + char * id; + + switch (ns_type) { + case CLONE_NEWNET: + p = "/proc/self/ns/net"; + break; + case CLONE_NEWNS: + p = "/proc/self/ns/mnt"; + break; + default: + g_assert_not_reached(); + } + + id = g_file_read_link(p, &error); + g_assert_no_error(error); + g_assert(id); + return id; } static char * -_get_sysctl_value (const char *path) +_get_sysctl_value(const char *path) { - char *data = NULL; - gs_free_error GError *error = NULL; - - if (!g_file_get_contents (path, &data, NULL, &error)) { - nmtst_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT, NULL); - g_assert (!data); - } else { - g_assert_no_error (error); - g_assert (data); - g_strstrip (data); - } - return data; + char * data = NULL; + gs_free_error GError *error = NULL; + + if (!g_file_get_contents(path, &data, NULL, &error)) { + nmtst_assert_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT, NULL); + g_assert(!data); + } else { + g_assert_no_error(error); + g_assert(data); + g_strstrip(data); + } + return data; } static void -test_netns_push (gpointer fixture, gconstpointer test_data) +test_netns_push(gpointer fixture, gconstpointer test_data) { - gs_unref_object NMPlatform *platform_0 = NULL; - gs_unref_object NMPlatform *platform_1 = NULL; - gs_unref_object NMPlatform *platform_2 = NULL; - nm_auto_pop_netns NMPNetns *netns_pop = NULL; - gs_unref_ptrarray GPtrArray *device_names = g_ptr_array_new_with_free_func (g_free); - int i, j; - const int ns_types_list[] = { CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWNET | CLONE_NEWNS }; - const int ns_types_test[] = { CLONE_NEWNET, CLONE_NEWNS }; - typedef struct { - NMPlatform *platform; - const char *device_name; - const char *sysctl_path; - const char *sysctl_value; - const char *ns_net; - const char *ns_mnt; - } PlatformData; - PlatformData pl[3] = { }; - PlatformData *pl_base; - struct { - PlatformData *pl; - int ns_types; - } stack[6] = { }; - int nstack; - - if (_test_netns_check_skip ()) - return; - - if (_check_sysctl_skip ()) - return; - - pl[0].platform = platform_0 = nm_linux_platform_new (TRUE, TRUE); - pl[1].platform = platform_1 = _test_netns_create_platform (); - pl[2].platform = platform_2 = _test_netns_create_platform (); - - pl_base = &pl[0]; - i = nmtst_get_rand_uint32 () % (G_N_ELEMENTS (pl) + 1); - if (i < G_N_ELEMENTS (pl)) { - pl_base = &pl[i]; - g_assert (nm_platform_netns_push (pl[i].platform, &netns_pop)); - } - - for (i = 0; i < G_N_ELEMENTS (pl); i++) { - nm_auto_pop_netns NMPNetns *netns_free = NULL; - char *tmp; - - g_assert (nm_platform_netns_push (pl[i].platform, &netns_free)); - - tmp = g_strdup_printf ("nmtst-dev-%d", i); - g_ptr_array_add (device_names, tmp); - pl[i].device_name = tmp; - - tmp = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/disable_ipv6", pl[i].device_name); - g_ptr_array_add (device_names, tmp); - pl[i].sysctl_path = tmp; - - pl[i].sysctl_value = nmtst_get_rand_uint32 () % 2 ? "1" : "0"; - - _ADD_DUMMY (pl[i].platform, pl[i].device_name); - - g_assert (nm_platform_sysctl_set (pl[i].platform, NMP_SYSCTL_PATHID_ABSOLUTE (pl[i].sysctl_path), pl[i].sysctl_value)); - - tmp = _get_current_namespace_id (CLONE_NEWNET); - g_ptr_array_add (device_names, tmp); - pl[i].ns_net = tmp; - - tmp = _get_current_namespace_id (CLONE_NEWNS); - g_ptr_array_add (device_names, tmp); - pl[i].ns_mnt = tmp; - } - - nstack = nmtst_get_rand_uint32 () % (G_N_ELEMENTS (stack) + 1); - for (i = 0; i < nstack; i++) { - stack[i].pl = &pl[nmtst_get_rand_uint32 () % G_N_ELEMENTS (pl)]; - stack[i].ns_types = ns_types_list[nmtst_get_rand_uint32 () % G_N_ELEMENTS (ns_types_list)]; - - nmp_netns_push_type (nm_platform_netns_get (stack[i].pl->platform), stack[i].ns_types); - } - - /* pop some again. */ - for (i = nmtst_get_rand_uint32 () % (nstack + 1); i > 0; i--) { - g_assert (nstack > 0); - nstack--; - nmp_netns_pop (nm_platform_netns_get (stack[nstack].pl->platform)); - } - - for (i = 0; i < G_N_ELEMENTS (ns_types_test); i++) { - int ns_type = ns_types_test[i]; - PlatformData *p; - gs_free char *current_namespace_id = NULL; - - p = pl_base; - for (j = nstack; j >= 1; ) { - j--; - if (NM_FLAGS_ANY (stack[j].ns_types, ns_type)) { - p = stack[j].pl; - break; - } - } - - current_namespace_id = _get_current_namespace_id (ns_type); - - if (ns_type == CLONE_NEWNET) { - g_assert_cmpstr (current_namespace_id, ==, p->ns_net); - for (j = 0; j < G_N_ELEMENTS (pl); j++) { - gs_free char *data = NULL; - - if (p == &pl[j]) - g_assert_cmpint (nmtstp_run_command ("ip link show %s 1>/dev/null", pl[j].device_name), ==, 0); - else - g_assert_cmpint (nmtstp_run_command ("ip link show %s 2>/dev/null", pl[j].device_name), !=, 0); - - data = _get_sysctl_value (pl[j].sysctl_path); - if (p == &pl[j]) - g_assert_cmpstr (data, ==, pl[j].sysctl_value); - else - g_assert (!data); - } - } else if (ns_type == CLONE_NEWNS) { - g_assert_cmpstr (current_namespace_id, ==, p->ns_mnt); - for (j = 0; j < G_N_ELEMENTS (pl); j++) { - char path[600]; - gs_free char *data = NULL; - - nm_sprintf_buf (path, "/sys/devices/virtual/net/%s/ifindex", pl[j].device_name); - - data = _get_sysctl_value (path); - if (p == &pl[j]) - g_assert_cmpstr (data, ==, nm_sprintf_buf (path, "%d", nmtstp_link_get_typed (p->platform, 0, p->device_name, NM_LINK_TYPE_DUMMY)->ifindex)); - else - g_assert (!data); - } - } else - g_assert_not_reached (); - } - - for (i = nstack; i >= 1; ) { - i--; - nmp_netns_pop (nm_platform_netns_get (stack[i].pl->platform)); - } + gs_unref_object NMPlatform *platform_0 = NULL; + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; + gs_unref_ptrarray GPtrArray *device_names = g_ptr_array_new_with_free_func(g_free); + int i, j; + const int ns_types_list[] = {CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWNET | CLONE_NEWNS}; + const int ns_types_test[] = {CLONE_NEWNET, CLONE_NEWNS}; + typedef struct { + NMPlatform *platform; + const char *device_name; + const char *sysctl_path; + const char *sysctl_value; + const char *ns_net; + const char *ns_mnt; + } PlatformData; + PlatformData pl[3] = {}; + PlatformData *pl_base; + struct { + PlatformData *pl; + int ns_types; + } stack[6] = {}; + int nstack; + + if (_test_netns_check_skip()) + return; + + if (_check_sysctl_skip()) + return; + + pl[0].platform = platform_0 = nm_linux_platform_new(TRUE, TRUE); + pl[1].platform = platform_1 = _test_netns_create_platform(); + pl[2].platform = platform_2 = _test_netns_create_platform(); + + pl_base = &pl[0]; + i = nmtst_get_rand_uint32() % (G_N_ELEMENTS(pl) + 1); + if (i < G_N_ELEMENTS(pl)) { + pl_base = &pl[i]; + g_assert(nm_platform_netns_push(pl[i].platform, &netns_pop)); + } + + for (i = 0; i < G_N_ELEMENTS(pl); i++) { + nm_auto_pop_netns NMPNetns *netns_free = NULL; + char * tmp; + + g_assert(nm_platform_netns_push(pl[i].platform, &netns_free)); + + tmp = g_strdup_printf("nmtst-dev-%d", i); + g_ptr_array_add(device_names, tmp); + pl[i].device_name = tmp; + + tmp = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", pl[i].device_name); + g_ptr_array_add(device_names, tmp); + pl[i].sysctl_path = tmp; + + pl[i].sysctl_value = nmtst_get_rand_uint32() % 2 ? "1" : "0"; + + _ADD_DUMMY(pl[i].platform, pl[i].device_name); + + g_assert(nm_platform_sysctl_set(pl[i].platform, + NMP_SYSCTL_PATHID_ABSOLUTE(pl[i].sysctl_path), + pl[i].sysctl_value)); + + tmp = _get_current_namespace_id(CLONE_NEWNET); + g_ptr_array_add(device_names, tmp); + pl[i].ns_net = tmp; + + tmp = _get_current_namespace_id(CLONE_NEWNS); + g_ptr_array_add(device_names, tmp); + pl[i].ns_mnt = tmp; + } + + nstack = nmtst_get_rand_uint32() % (G_N_ELEMENTS(stack) + 1); + for (i = 0; i < nstack; i++) { + stack[i].pl = &pl[nmtst_get_rand_uint32() % G_N_ELEMENTS(pl)]; + stack[i].ns_types = ns_types_list[nmtst_get_rand_uint32() % G_N_ELEMENTS(ns_types_list)]; + + nmp_netns_push_type(nm_platform_netns_get(stack[i].pl->platform), stack[i].ns_types); + } + + /* pop some again. */ + for (i = nmtst_get_rand_uint32() % (nstack + 1); i > 0; i--) { + g_assert(nstack > 0); + nstack--; + nmp_netns_pop(nm_platform_netns_get(stack[nstack].pl->platform)); + } + + for (i = 0; i < G_N_ELEMENTS(ns_types_test); i++) { + int ns_type = ns_types_test[i]; + PlatformData *p; + gs_free char *current_namespace_id = NULL; + + p = pl_base; + for (j = nstack; j >= 1;) { + j--; + if (NM_FLAGS_ANY(stack[j].ns_types, ns_type)) { + p = stack[j].pl; + break; + } + } + + current_namespace_id = _get_current_namespace_id(ns_type); + + if (ns_type == CLONE_NEWNET) { + g_assert_cmpstr(current_namespace_id, ==, p->ns_net); + for (j = 0; j < G_N_ELEMENTS(pl); j++) { + gs_free char *data = NULL; + + if (p == &pl[j]) + g_assert_cmpint( + nmtstp_run_command("ip link show %s 1>/dev/null", pl[j].device_name), + ==, + 0); + else + g_assert_cmpint( + nmtstp_run_command("ip link show %s 2>/dev/null", pl[j].device_name), + !=, + 0); + + data = _get_sysctl_value(pl[j].sysctl_path); + if (p == &pl[j]) + g_assert_cmpstr(data, ==, pl[j].sysctl_value); + else + g_assert(!data); + } + } else if (ns_type == CLONE_NEWNS) { + g_assert_cmpstr(current_namespace_id, ==, p->ns_mnt); + for (j = 0; j < G_N_ELEMENTS(pl); j++) { + char path[600]; + gs_free char *data = NULL; + + nm_sprintf_buf(path, "/sys/devices/virtual/net/%s/ifindex", pl[j].device_name); + + data = _get_sysctl_value(path); + if (p == &pl[j]) + g_assert_cmpstr(data, + ==, + nm_sprintf_buf(path, + "%d", + nmtstp_link_get_typed(p->platform, + 0, + p->device_name, + NM_LINK_TYPE_DUMMY) + ->ifindex)); + else + g_assert(!data); + } + } else + g_assert_not_reached(); + } + + for (i = nstack; i >= 1;) { + i--; + nmp_netns_pop(nm_platform_netns_get(stack[i].pl->platform)); + } } /*****************************************************************************/ static void -test_netns_bind_to_path (gpointer fixture, gconstpointer test_data) +test_netns_bind_to_path(gpointer fixture, gconstpointer test_data) { #define P_VAR_RUN "/run" #define P_VAR_RUN_NETNS "/run/netns" -#define P_VAR_RUN_NETNS_BINDNAME "/run/netns/"P_NETNS_BINDNAME +#define P_VAR_RUN_NETNS_BINDNAME "/run/netns/" P_NETNS_BINDNAME #define P_NETNS_BINDNAME "nmtst-iproute2-netns" - gs_unref_object NMPlatform *platform_0 = NULL; - gs_unref_object NMPlatform *platform_1 = NULL; - gs_unref_object NMPlatform *platform_2 = NULL; - nm_auto_pop_netns NMPNetns *netns_pop = NULL; - NMPlatform *platforms[3]; - NMPNetns *netns; - int i; + gs_unref_object NMPlatform *platform_0 = NULL; + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop = NULL; + NMPlatform * platforms[3]; + NMPNetns * netns; + int i; - if (_test_netns_check_skip ()) - return; + if (_test_netns_check_skip()) + return; - platforms[0] = platform_0 = nm_linux_platform_new (TRUE, TRUE); - platforms[1] = platform_1 = _test_netns_create_platform (); - platforms[2] = platform_2 = _test_netns_create_platform (); + platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE); + platforms[1] = platform_1 = _test_netns_create_platform(); + platforms[2] = platform_2 = _test_netns_create_platform(); - nmtstp_netns_select_random (platforms, G_N_ELEMENTS (platforms), &netns_pop); + nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop); - g_assert_cmpint (mount ("tmpfs", P_VAR_RUN, "tmpfs", MS_NOATIME | MS_NODEV | MS_NOSUID, "mode=0755,size=32K"), ==, 0); - g_assert_cmpint (mkdir (P_VAR_RUN_NETNS, 755), ==, 0); + g_assert_cmpint( + mount("tmpfs", P_VAR_RUN, "tmpfs", MS_NOATIME | MS_NODEV | MS_NOSUID, "mode=0755,size=32K"), + ==, + 0); + g_assert_cmpint(mkdir(P_VAR_RUN_NETNS, 755), ==, 0); - i = (nmtst_get_rand_uint32 () % 2) + 1; - netns = nm_platform_netns_get (platforms[i]); + i = (nmtst_get_rand_uint32() % 2) + 1; + netns = nm_platform_netns_get(platforms[i]); - _ADD_DUMMY (platforms[i], "dummy2b"); + _ADD_DUMMY(platforms[i], "dummy2b"); - g_assert (!g_file_test (P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); - g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" true 2>/dev/null"), !=, 0); + g_assert(!g_file_test(P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); + g_assert_cmpint(nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true 2>/dev/null"), + !=, + 0); - g_assert (nmp_netns_bind_to_path (netns, P_VAR_RUN_NETNS_BINDNAME, NULL)); + g_assert(nmp_netns_bind_to_path(netns, P_VAR_RUN_NETNS_BINDNAME, NULL)); - g_assert (g_file_test (P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); - g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" true"), ==, 0); - g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" ip link show dummy2b 1>/dev/null"), ==, 0); + g_assert(g_file_test(P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); + g_assert_cmpint(nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true"), ==, 0); + g_assert_cmpint( + nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " ip link show dummy2b 1>/dev/null"), + ==, + 0); - g_assert (nmp_netns_bind_to_path_destroy (netns, P_VAR_RUN_NETNS_BINDNAME)); + g_assert(nmp_netns_bind_to_path_destroy(netns, P_VAR_RUN_NETNS_BINDNAME)); - g_assert (!g_file_test (P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); - g_assert_cmpint (nmtstp_run_command ("ip netns exec "P_NETNS_BINDNAME" true 2>/dev/null"), !=, 0); + g_assert(!g_file_test(P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); + g_assert_cmpint(nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true 2>/dev/null"), + !=, + 0); - g_assert_cmpint (umount (P_VAR_RUN), ==, 0); + g_assert_cmpint(umount(P_VAR_RUN), ==, 0); } /*****************************************************************************/ static void -test_sysctl_rename (void) +test_sysctl_rename(void) { - NMPlatform *const PL = NM_PLATFORM_GET; - const char *const IFNAME[3] = { - "nm-dummy-0", - "nm-dummy-1", - "nm-dummy-2", - }; - int ifindex[G_N_ELEMENTS (IFNAME)] = { 0 }; - nm_auto_close int dirfd = -1; - int i; - char ifname_buf[IFNAMSIZ]; - char *s; - const NMPlatformLink *pllink; - - ifindex[0] = nmtstp_link_dummy_add (PL, -1, IFNAME[0])->ifindex; - ifindex[1] = nmtstp_link_dummy_add (PL, -1, IFNAME[1])->ifindex; - - s = (nmtst_get_rand_uint32 () % 2) ? NULL : ifname_buf; - - if (nmtst_get_rand_uint32 () % 2) { - /* bring the platform cache out of sync */ - nmtstp_run_command_check ("ip link set %s name %s", IFNAME[0], IFNAME[2]); - nm_platform_process_events (PL); - nmtstp_run_command_check ("ip link set %s name %s", IFNAME[2], IFNAME[0]); - - pllink = nm_platform_link_get_by_ifname (PL, IFNAME[2]); - g_assert (pllink && pllink->ifindex == ifindex[0]); - pllink = nm_platform_link_get_by_ifname (PL, IFNAME[0]); - g_assert (!pllink); - } - - /* open dirfd for IFNAME[0] */ - i = nmtst_get_rand_uint32 () % (2 + G_N_ELEMENTS (IFNAME)); - if (i == 0) { - dirfd = nm_platform_sysctl_open_netdir (PL, - ifindex[0], - s); - } else { - const char *ifname_guess; - - /* provide a wrong or no guess. */ - ifname_guess = i == 1 ? NULL : IFNAME[i - 2]; - dirfd = nmp_utils_sysctl_open_netdir (ifindex[0], - ifname_guess, - s); - } - g_assert (dirfd >= 0); - if (s) - g_assert_cmpstr (s, ==, IFNAME[0]); - - /* possibly rename the interfaces. */ - switch (nmtst_get_rand_uint32 () % 4) { - case 0: - break; - case 1: - nmtstp_run_command_check ("ip link set %s name %s", IFNAME[0], IFNAME[2]); - break; - case 2: - nmtstp_run_command_check ("ip link set %s name %s", IFNAME[0], IFNAME[2]); - nmtstp_run_command_check ("ip link set %s name %s", IFNAME[1], IFNAME[0]); - break; - } - - /* possibly, resync platform cache (should make no difference). */ - if (nmtst_get_rand_uint32 () % 2) - nm_platform_process_events (PL); - - /* check that we still read the same file. */ - switch (nmtst_get_rand_uint32 () % 2) { - case 0: { - gs_free char *c = NULL; - - if (!nm_utils_file_get_contents (dirfd, - "ifindex", - 1*1024*1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &c, - NULL, - NULL, - NULL)) - g_assert_not_reached(); - g_assert_cmpint (ifindex[0], ==, (int) _nm_utils_ascii_str_to_int64 (c, 10, 0, G_MAXINT, -1)); - break; - } - case 1: { - g_assert_cmpint (ifindex[0], ==, (gint32) nm_platform_sysctl_get_int32 (PL, NMP_SYSCTL_PATHID_NETDIR (dirfd, s ?: "<unknown>", "ifindex"), -1)); - break; - } - } - - nm_platform_process_events (PL); - nmtstp_link_delete (PL, -1, ifindex[0], NULL, TRUE); - nmtstp_link_delete (PL, -1, ifindex[1], NULL, TRUE); + NMPlatform *const PL = NM_PLATFORM_GET; + const char *const IFNAME[3] = { + "nm-dummy-0", + "nm-dummy-1", + "nm-dummy-2", + }; + int ifindex[G_N_ELEMENTS(IFNAME)] = {0}; + nm_auto_close int dirfd = -1; + int i; + char ifname_buf[IFNAMSIZ]; + char * s; + const NMPlatformLink *pllink; + + ifindex[0] = nmtstp_link_dummy_add(PL, -1, IFNAME[0])->ifindex; + ifindex[1] = nmtstp_link_dummy_add(PL, -1, IFNAME[1])->ifindex; + + s = (nmtst_get_rand_uint32() % 2) ? NULL : ifname_buf; + + if (nmtst_get_rand_uint32() % 2) { + /* bring the platform cache out of sync */ + nmtstp_run_command_check("ip link set %s name %s", IFNAME[0], IFNAME[2]); + nm_platform_process_events(PL); + nmtstp_run_command_check("ip link set %s name %s", IFNAME[2], IFNAME[0]); + + pllink = nm_platform_link_get_by_ifname(PL, IFNAME[2]); + g_assert(pllink && pllink->ifindex == ifindex[0]); + pllink = nm_platform_link_get_by_ifname(PL, IFNAME[0]); + g_assert(!pllink); + } + + /* open dirfd for IFNAME[0] */ + i = nmtst_get_rand_uint32() % (2 + G_N_ELEMENTS(IFNAME)); + if (i == 0) { + dirfd = nm_platform_sysctl_open_netdir(PL, ifindex[0], s); + } else { + const char *ifname_guess; + + /* provide a wrong or no guess. */ + ifname_guess = i == 1 ? NULL : IFNAME[i - 2]; + dirfd = nmp_utils_sysctl_open_netdir(ifindex[0], ifname_guess, s); + } + g_assert(dirfd >= 0); + if (s) + g_assert_cmpstr(s, ==, IFNAME[0]); + + /* possibly rename the interfaces. */ + switch (nmtst_get_rand_uint32() % 4) { + case 0: + break; + case 1: + nmtstp_run_command_check("ip link set %s name %s", IFNAME[0], IFNAME[2]); + break; + case 2: + nmtstp_run_command_check("ip link set %s name %s", IFNAME[0], IFNAME[2]); + nmtstp_run_command_check("ip link set %s name %s", IFNAME[1], IFNAME[0]); + break; + } + + /* possibly, resync platform cache (should make no difference). */ + if (nmtst_get_rand_uint32() % 2) + nm_platform_process_events(PL); + + /* check that we still read the same file. */ + switch (nmtst_get_rand_uint32() % 2) { + case 0: + { + gs_free char *c = NULL; + + if (!nm_utils_file_get_contents(dirfd, + "ifindex", + 1 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &c, + NULL, + NULL, + NULL)) + g_assert_not_reached(); + g_assert_cmpint(ifindex[0], ==, (int) _nm_utils_ascii_str_to_int64(c, 10, 0, G_MAXINT, -1)); + break; + } + case 1: + { + g_assert_cmpint(ifindex[0], + ==, + (gint32) nm_platform_sysctl_get_int32( + PL, + NMP_SYSCTL_PATHID_NETDIR(dirfd, s ?: "<unknown>", "ifindex"), + -1)); + break; + } + } + + nm_platform_process_events(PL); + nmtstp_link_delete(PL, -1, ifindex[0], NULL, TRUE); + nmtstp_link_delete(PL, -1, ifindex[1], NULL, TRUE); } /*****************************************************************************/ static void -test_sysctl_netns_switch (void) +test_sysctl_netns_switch(void) { - const char *const IFNAME = "nm-dummy-0"; - int ifindex, ifindex_tmp; - nm_auto_close int dirfd = -1; - char ifname_buf[IFNAMSIZ]; - char *s; - gs_unref_object NMPlatform *platform_0 = NULL; - gs_unref_object NMPlatform *platform_1 = NULL; - gs_unref_object NMPlatform *platform_2 = NULL; - nm_auto_pop_netns NMPNetns *netns_pop_1 = NULL; - nm_auto_pop_netns NMPNetns *netns_pop_2 = NULL; - nm_auto_pop_netns NMPNetns *netns_pop_3 = NULL; - NMPlatform *PL; - NMPlatform *platforms[3]; - - if (_test_netns_check_skip ()) - return; - - platforms[0] = platform_0 = nm_linux_platform_new (TRUE, TRUE); - platforms[1] = platform_1 = _test_netns_create_platform (); - platforms[2] = platform_2 = _test_netns_create_platform (); - PL = platforms[nmtst_get_rand_uint32 () % 3]; - - nmtstp_netns_select_random (platforms, G_N_ELEMENTS (platforms), &netns_pop_1); - - ifindex = nmtstp_link_dummy_add (PL, FALSE, IFNAME)->ifindex; - - nmtstp_netns_select_random (platforms, G_N_ELEMENTS (platforms), &netns_pop_2); - - s = (nmtst_get_rand_uint32 () % 2) ? NULL : ifname_buf; - dirfd = nm_platform_sysctl_open_netdir (PL, - ifindex, - s); - g_assert (dirfd >= 0); - if (s) - g_assert_cmpstr (s, ==, IFNAME); - - nmtstp_netns_select_random (platforms, G_N_ELEMENTS (platforms), &netns_pop_3); - - /* even if we switch to other namespaces, we can still lookup the path correctly, - * either using dirfd or via the platform instance (which switches namespace as needed). */ - { - gs_free char *c = NULL; - - if (!nm_utils_file_get_contents (dirfd, - "ifindex", - 0, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &c, - NULL, - NULL, - NULL)) - g_assert_not_reached(); - g_assert_cmpint (ifindex, ==, (int) _nm_utils_ascii_str_to_int64 (c, 10, 0, G_MAXINT, -1)); - } - g_assert_cmpint (ifindex, ==, (gint32) nm_platform_sysctl_get_int32 (PL, NMP_SYSCTL_PATHID_NETDIR (dirfd, s ?: "<unknown>", "ifindex"), -1)); - g_assert_cmpint (ifindex, ==, (gint32) nm_platform_sysctl_get_int32 (PL, NMP_SYSCTL_PATHID_ABSOLUTE (nm_sprintf_bufa (100, "/sys/class/net/%s/ifindex", IFNAME)), -1)); - - /* also test that nm_platform_sysctl_get() sets errno to ENOENT for non-existing paths. */ - { - gint64 i64; - int errsv; - char *v; - - errno = ESRCH; - v = nm_platform_sysctl_get (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/not-existing/ifindex")); - errsv = errno; - g_assert (!v); - g_assert_cmpint (errsv, ==, ENOENT); - - errno = ESRCH; - i64 = nm_platform_sysctl_get_int_checked (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/not-existing/ifindex"), 10, 1, G_MAXINT, -1); - errsv = errno; - g_assert_cmpint (i64, ==, -1); - g_assert_cmpint (errsv, ==, ENOENT); - - errno = ESRCH; - v = nm_platform_sysctl_get (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/lo/not-existing")); - errsv = errno; - g_assert (!v); - g_assert_cmpint (errsv, ==, ENOENT); - - errno = ESRCH; - i64 = nm_platform_sysctl_get_int_checked (PL, NMP_SYSCTL_PATHID_ABSOLUTE ("/sys/devices/virtual/net/lo/not-existing"), 10, 1, G_MAXINT, -1); - errsv = errno; - g_assert_cmpint (i64, ==, -1); - g_assert_cmpint (errsv, ==, ENOENT); - } - - /* accessing the path directly, only succeeds iff the current namespace happens to be the namespace - * in which we created the link. */ - { - gs_free char *c = NULL; - - if (!nm_utils_file_get_contents (-1, - nm_sprintf_bufa (100, "/sys/class/net/%s/ifindex", IFNAME), - 0, - NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, - &c, - NULL, - NULL, - NULL)) - ifindex_tmp = -1; - else - ifindex_tmp = _nm_utils_ascii_str_to_int64 (c, 10, 0, G_MAXINT, -2); - } - if (nmp_netns_get_current () == nm_platform_netns_get (PL)) - g_assert_cmpint (ifindex_tmp, ==, ifindex); - else - g_assert_cmpint (ifindex_tmp, ==, -1); - - nmtstp_link_delete (PL, FALSE, ifindex, NULL, TRUE); + const char *const IFNAME = "nm-dummy-0"; + int ifindex, ifindex_tmp; + nm_auto_close int dirfd = -1; + char ifname_buf[IFNAMSIZ]; + char * s; + gs_unref_object NMPlatform *platform_0 = NULL; + gs_unref_object NMPlatform *platform_1 = NULL; + gs_unref_object NMPlatform *platform_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop_1 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop_2 = NULL; + nm_auto_pop_netns NMPNetns *netns_pop_3 = NULL; + NMPlatform * PL; + NMPlatform * platforms[3]; + + if (_test_netns_check_skip()) + return; + + platforms[0] = platform_0 = nm_linux_platform_new(TRUE, TRUE); + platforms[1] = platform_1 = _test_netns_create_platform(); + platforms[2] = platform_2 = _test_netns_create_platform(); + PL = platforms[nmtst_get_rand_uint32() % 3]; + + nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop_1); + + ifindex = nmtstp_link_dummy_add(PL, FALSE, IFNAME)->ifindex; + + nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop_2); + + s = (nmtst_get_rand_uint32() % 2) ? NULL : ifname_buf; + dirfd = nm_platform_sysctl_open_netdir(PL, ifindex, s); + g_assert(dirfd >= 0); + if (s) + g_assert_cmpstr(s, ==, IFNAME); + + nmtstp_netns_select_random(platforms, G_N_ELEMENTS(platforms), &netns_pop_3); + + /* even if we switch to other namespaces, we can still lookup the path correctly, + * either using dirfd or via the platform instance (which switches namespace as needed). */ + { + gs_free char *c = NULL; + + if (!nm_utils_file_get_contents(dirfd, + "ifindex", + 0, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &c, + NULL, + NULL, + NULL)) + g_assert_not_reached(); + g_assert_cmpint(ifindex, ==, (int) _nm_utils_ascii_str_to_int64(c, 10, 0, G_MAXINT, -1)); + } + g_assert_cmpint(ifindex, + ==, + (gint32) nm_platform_sysctl_get_int32( + PL, + NMP_SYSCTL_PATHID_NETDIR(dirfd, s ?: "<unknown>", "ifindex"), + -1)); + g_assert_cmpint( + ifindex, + ==, + (gint32) nm_platform_sysctl_get_int32( + PL, + NMP_SYSCTL_PATHID_ABSOLUTE(nm_sprintf_bufa(100, "/sys/class/net/%s/ifindex", IFNAME)), + -1)); + + /* also test that nm_platform_sysctl_get() sets errno to ENOENT for non-existing paths. */ + { + gint64 i64; + int errsv; + char * v; + + errno = ESRCH; + v = nm_platform_sysctl_get( + PL, + NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/not-existing/ifindex")); + errsv = errno; + g_assert(!v); + g_assert_cmpint(errsv, ==, ENOENT); + + errno = ESRCH; + i64 = nm_platform_sysctl_get_int_checked( + PL, + NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/not-existing/ifindex"), + 10, + 1, + G_MAXINT, + -1); + errsv = errno; + g_assert_cmpint(i64, ==, -1); + g_assert_cmpint(errsv, ==, ENOENT); + + errno = ESRCH; + v = nm_platform_sysctl_get( + PL, + NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/lo/not-existing")); + errsv = errno; + g_assert(!v); + g_assert_cmpint(errsv, ==, ENOENT); + + errno = ESRCH; + i64 = nm_platform_sysctl_get_int_checked( + PL, + NMP_SYSCTL_PATHID_ABSOLUTE("/sys/devices/virtual/net/lo/not-existing"), + 10, + 1, + G_MAXINT, + -1); + errsv = errno; + g_assert_cmpint(i64, ==, -1); + g_assert_cmpint(errsv, ==, ENOENT); + } + + /* accessing the path directly, only succeeds iff the current namespace happens to be the namespace + * in which we created the link. */ + { + gs_free char *c = NULL; + + if (!nm_utils_file_get_contents(-1, + nm_sprintf_bufa(100, "/sys/class/net/%s/ifindex", IFNAME), + 0, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, + &c, + NULL, + NULL, + NULL)) + ifindex_tmp = -1; + else + ifindex_tmp = _nm_utils_ascii_str_to_int64(c, 10, 0, G_MAXINT, -2); + } + if (nmp_netns_get_current() == nm_platform_netns_get(PL)) + g_assert_cmpint(ifindex_tmp, ==, ifindex); + else + g_assert_cmpint(ifindex_tmp, ==, -1); + + nmtstp_link_delete(PL, FALSE, ifindex, NULL, TRUE); } typedef struct { - GMainLoop *loop; - const char *path; - gboolean expected_success; - gint32 expected_value; + GMainLoop * loop; + const char *path; + gboolean expected_success; + gint32 expected_value; } SetAsyncData; static void -sysctl_set_async_cb (GError *error, gpointer user_data) +sysctl_set_async_cb(GError *error, gpointer user_data) { - SetAsyncData *data = user_data; - - if (data->expected_success) { - g_assert_no_error (error); - g_assert_cmpint (nm_platform_sysctl_get_int32 (NM_PLATFORM_GET, - NMP_SYSCTL_PATHID_ABSOLUTE (data->path), - -1), - ==, - data->expected_value); - } else - g_assert (error); - - g_main_loop_quit (data->loop); + SetAsyncData *data = user_data; + + if (data->expected_success) { + g_assert_no_error(error); + g_assert_cmpint(nm_platform_sysctl_get_int32(NM_PLATFORM_GET, + NMP_SYSCTL_PATHID_ABSOLUTE(data->path), + -1), + ==, + data->expected_value); + } else + g_assert(error); + + g_main_loop_quit(data->loop); } static void -test_sysctl_set_async (void) +test_sysctl_set_async(void) { - NMPlatform *const PL = NM_PLATFORM_GET; - const char *const IFNAME = "nm-dummy-0"; - const char *const PATH = "/proc/sys/net/ipv4/conf/nm-dummy-0/rp_filter"; - GMainLoop *loop; - gs_unref_object GCancellable *cancellable = NULL; - gboolean proc_writable; - SetAsyncData data; - int ifindex; - - ifindex = nmtstp_link_dummy_add (PL, -1, IFNAME)->ifindex; - loop = g_main_loop_new (NULL, FALSE); - cancellable = g_cancellable_new (); - proc_writable = access (PATH, W_OK) == 0; - - data = (SetAsyncData) { - .loop = loop, - .path = PATH, - .expected_success = proc_writable, - .expected_value = 2, - }; - - nm_platform_sysctl_set_async (PL, - NMP_SYSCTL_PATHID_ABSOLUTE (PATH), - (const char *[]) { "2", NULL}, - sysctl_set_async_cb, - &data, - cancellable); - - if (!nmtst_main_loop_run (loop, 1000)) - g_assert_not_reached (); - - data = (SetAsyncData) { - .loop = loop, - .path = PATH, - .expected_success = proc_writable, - .expected_value = 1, - }; - - nm_platform_sysctl_set_async (PL, - NMP_SYSCTL_PATHID_ABSOLUTE (PATH), - (const char *[]) { "2", "0", "1", "0", "1", NULL}, - sysctl_set_async_cb, - &data, - cancellable); - - if (!nmtst_main_loop_run (loop, 2000)) - g_assert_not_reached (); - - nmtstp_link_delete (NULL, -1, ifindex, IFNAME, TRUE); - g_main_loop_unref (loop); + NMPlatform *const PL = NM_PLATFORM_GET; + const char *const IFNAME = "nm-dummy-0"; + const char *const PATH = "/proc/sys/net/ipv4/conf/nm-dummy-0/rp_filter"; + GMainLoop * loop; + gs_unref_object GCancellable *cancellable = NULL; + gboolean proc_writable; + SetAsyncData data; + int ifindex; + + ifindex = nmtstp_link_dummy_add(PL, -1, IFNAME)->ifindex; + loop = g_main_loop_new(NULL, FALSE); + cancellable = g_cancellable_new(); + proc_writable = access(PATH, W_OK) == 0; + + data = (SetAsyncData){ + .loop = loop, + .path = PATH, + .expected_success = proc_writable, + .expected_value = 2, + }; + + nm_platform_sysctl_set_async(PL, + NMP_SYSCTL_PATHID_ABSOLUTE(PATH), + (const char *[]){"2", NULL}, + sysctl_set_async_cb, + &data, + cancellable); + + if (!nmtst_main_loop_run(loop, 1000)) + g_assert_not_reached(); + + data = (SetAsyncData){ + .loop = loop, + .path = PATH, + .expected_success = proc_writable, + .expected_value = 1, + }; + + nm_platform_sysctl_set_async(PL, + NMP_SYSCTL_PATHID_ABSOLUTE(PATH), + (const char *[]){"2", "0", "1", "0", "1", NULL}, + sysctl_set_async_cb, + &data, + cancellable); + + if (!nmtst_main_loop_run(loop, 2000)) + g_assert_not_reached(); + + nmtstp_link_delete(NULL, -1, ifindex, IFNAME, TRUE); + g_main_loop_unref(loop); } static void -test_sysctl_set_async_fail (void) +test_sysctl_set_async_fail(void) { - NMPlatform *const PL = NM_PLATFORM_GET; - const char *const IFNAME = "nm-dummy-0"; - const char *const PATH = "/proc/sys/net/ipv4/conf/nm-dummy-0/does-not-exist"; - GMainLoop *loop; - gs_unref_object GCancellable *cancellable = NULL; - SetAsyncData data; - int ifindex; - - ifindex = nmtstp_link_dummy_add (PL, -1, IFNAME)->ifindex; - loop = g_main_loop_new (NULL, FALSE); - cancellable = g_cancellable_new (); - - data = (SetAsyncData) { - .loop = loop, - .path = PATH, - .expected_success = FALSE, - }; - - nm_platform_sysctl_set_async (PL, - NMP_SYSCTL_PATHID_ABSOLUTE (PATH), - (const char *[]) { "2", NULL}, - sysctl_set_async_cb, - &data, - cancellable); - - if (!nmtst_main_loop_run (loop, 1000)) - g_assert_not_reached (); - - nmtstp_link_delete (NULL, -1, ifindex, IFNAME, TRUE); - g_main_loop_unref (loop); + NMPlatform *const PL = NM_PLATFORM_GET; + const char *const IFNAME = "nm-dummy-0"; + const char *const PATH = "/proc/sys/net/ipv4/conf/nm-dummy-0/does-not-exist"; + GMainLoop * loop; + gs_unref_object GCancellable *cancellable = NULL; + SetAsyncData data; + int ifindex; + + ifindex = nmtstp_link_dummy_add(PL, -1, IFNAME)->ifindex; + loop = g_main_loop_new(NULL, FALSE); + cancellable = g_cancellable_new(); + + data = (SetAsyncData){ + .loop = loop, + .path = PATH, + .expected_success = FALSE, + }; + + nm_platform_sysctl_set_async(PL, + NMP_SYSCTL_PATHID_ABSOLUTE(PATH), + (const char *[]){"2", NULL}, + sysctl_set_async_cb, + &data, + cancellable); + + if (!nmtst_main_loop_run(loop, 1000)) + g_assert_not_reached(); + + nmtstp_link_delete(NULL, -1, ifindex, IFNAME, TRUE); + g_main_loop_unref(loop); } /*****************************************************************************/ static gpointer -_test_netns_mt_thread (gpointer data) +_test_netns_mt_thread(gpointer data) { - NMPNetns *netns1 = data; - gs_unref_object NMPNetns *netns2 = NULL; - NMPNetns *netns_bottom; - NMPNetns *initial; - - netns_bottom = nmp_netns_get_initial (); - g_assert (netns_bottom); - - /* I don't know why, but we need to create a new netns here at least once. - * Otherwise, setns(, CLONE_NEWNS) below fails with EINVAL (???). - * - * Something is not right here, but what? */ - netns2 = nmp_netns_new (); - nmp_netns_pop (netns2); - g_clear_object (&netns2); - - nmp_netns_push (netns1); - nmp_netns_push_type (netns_bottom, CLONE_NEWNET); - nmp_netns_push_type (netns_bottom, CLONE_NEWNS); - nmp_netns_push_type (netns1, CLONE_NEWNS); - nmp_netns_pop (netns1); - nmp_netns_pop (netns_bottom); - nmp_netns_pop (netns_bottom); - nmp_netns_pop (netns1); - - initial = nmp_netns_get_initial (); - g_assert (NMP_IS_NETNS (initial)); - return g_object_ref (initial); + NMPNetns * netns1 = data; + gs_unref_object NMPNetns *netns2 = NULL; + NMPNetns * netns_bottom; + NMPNetns * initial; + + netns_bottom = nmp_netns_get_initial(); + g_assert(netns_bottom); + + /* I don't know why, but we need to create a new netns here at least once. + * Otherwise, setns(, CLONE_NEWNS) below fails with EINVAL (???). + * + * Something is not right here, but what? */ + netns2 = nmp_netns_new(); + nmp_netns_pop(netns2); + g_clear_object(&netns2); + + nmp_netns_push(netns1); + nmp_netns_push_type(netns_bottom, CLONE_NEWNET); + nmp_netns_push_type(netns_bottom, CLONE_NEWNS); + nmp_netns_push_type(netns1, CLONE_NEWNS); + nmp_netns_pop(netns1); + nmp_netns_pop(netns_bottom); + nmp_netns_pop(netns_bottom); + nmp_netns_pop(netns1); + + initial = nmp_netns_get_initial(); + g_assert(NMP_IS_NETNS(initial)); + return g_object_ref(initial); } static void -test_netns_mt (void) +test_netns_mt(void) { - gs_unref_object NMPNetns *netns1 = NULL; - NMPNetns *initial_from_other_thread; - GThread *th; - - if (_test_netns_check_skip ()) - return; - - netns1 = nmp_netns_new (); - g_assert (NMP_NETNS (netns1)); - nmp_netns_pop (netns1); - - th = g_thread_new ("nm-test-netns-mt", _test_netns_mt_thread, netns1); - initial_from_other_thread = g_thread_join (th); - g_assert (NMP_IS_NETNS (initial_from_other_thread)); - - if (nmtst_get_rand_bool ()) { - nmp_netns_push (initial_from_other_thread); - nmp_netns_pop (initial_from_other_thread); - } - - g_object_add_weak_pointer (G_OBJECT (initial_from_other_thread), (gpointer *) &initial_from_other_thread); - g_object_unref (initial_from_other_thread); - g_assert (initial_from_other_thread == NULL); + gs_unref_object NMPNetns *netns1 = NULL; + NMPNetns * initial_from_other_thread; + GThread * th; + + if (_test_netns_check_skip()) + return; + + netns1 = nmp_netns_new(); + g_assert(NMP_NETNS(netns1)); + nmp_netns_pop(netns1); + + th = g_thread_new("nm-test-netns-mt", _test_netns_mt_thread, netns1); + initial_from_other_thread = g_thread_join(th); + g_assert(NMP_IS_NETNS(initial_from_other_thread)); + + if (nmtst_get_rand_bool()) { + nmp_netns_push(initial_from_other_thread); + nmp_netns_pop(initial_from_other_thread); + } + + g_object_add_weak_pointer(G_OBJECT(initial_from_other_thread), + (gpointer *) &initial_from_other_thread); + g_object_unref(initial_from_other_thread); + g_assert(initial_from_other_thread == NULL); } /*****************************************************************************/ static void -ethtool_features_dump (const NMEthtoolFeatureStates *features) +ethtool_features_dump(const NMEthtoolFeatureStates *features) { - guint i, j; - - g_assert (features); - - _LOGT (">>> %u features (%u ss-features)", features->n_states, features->n_ss_features); - - for (i = 0; i < features->n_states; i++) { - const NMEthtoolFeatureState *s = &features->states_list[i]; - - _LOGT (">>> feature-list[%3u]: %3d = %-32s (%3u) | %s %s %s %s", - i, - (int) s->info->ethtool_id, - s->info->kernel_names[s->idx_kernel_name], - s->idx_ss_features, - s->active ? "ACT" : "act", - s->available ? "AVA" : "ava", - s->never_changed ? "NCH" : "nch", - s->requested ? "REQ" : "req"); - } - for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) { - _LOGT (">>> feature-idx [%3u]: %-32s = %u features", - i + (guint) _NM_ETHTOOL_ID_FEATURE_FIRST, - nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, - (guint) NM_PTRARRAY_LEN (features->states_indexed[i])); - for (j = 0; features->states_indexed[i] && features->states_indexed[i][j]; j++) { - const NMEthtoolFeatureState *s = features->states_indexed[i][j]; - - _LOGT (">>> %3u: %-32s | %s %s %s %s", - j, - s->info->kernel_names[s->idx_kernel_name], - s->active ? "ACT" : "act", - s->available ? "AVA" : "ava", - s->never_changed ? "NCH" : "nch", - s->requested ? "REQ" : "req"); - } - } + guint i, j; + + g_assert(features); + + _LOGT(">>> %u features (%u ss-features)", features->n_states, features->n_ss_features); + + for (i = 0; i < features->n_states; i++) { + const NMEthtoolFeatureState *s = &features->states_list[i]; + + _LOGT(">>> feature-list[%3u]: %3d = %-32s (%3u) | %s %s %s %s", + i, + (int) s->info->ethtool_id, + s->info->kernel_names[s->idx_kernel_name], + s->idx_ss_features, + s->active ? "ACT" : "act", + s->available ? "AVA" : "ava", + s->never_changed ? "NCH" : "nch", + s->requested ? "REQ" : "req"); + } + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) { + _LOGT(">>> feature-idx [%3u]: %-32s = %u features", + i + (guint) _NM_ETHTOOL_ID_FEATURE_FIRST, + nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, + (guint) NM_PTRARRAY_LEN(features->states_indexed[i])); + for (j = 0; features->states_indexed[i] && features->states_indexed[i][j]; j++) { + const NMEthtoolFeatureState *s = features->states_indexed[i][j]; + + _LOGT(">>> %3u: %-32s | %s %s %s %s", + j, + s->info->kernel_names[s->idx_kernel_name], + s->active ? "ACT" : "act", + s->available ? "AVA" : "ava", + s->never_changed ? "NCH" : "nch", + s->requested ? "REQ" : "req"); + } + } } static void -test_ethtool_features_get (void) +test_ethtool_features_get(void) { - gs_unref_ptrarray GPtrArray *gfree_keeper = g_ptr_array_new_with_free_func (g_free); - const int IFINDEX = 1; - guint i; - guint i_run; - - for (i_run = 0; i_run < 5; i_run++) { - NMEthtoolFeatureStates *features; - NMTernary *requested; - gboolean do_set = TRUE; - - requested = g_new (NMTernary, _NM_ETHTOOL_ID_FEATURE_NUM); - for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) - requested[i] = NM_TERNARY_DEFAULT; - g_ptr_array_add (gfree_keeper, requested); - - if (i_run == 0) { - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX (NM_ETHTOOL_ID_FEATURE_RX)] = NM_TERNARY_FALSE; - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX (NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE; - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX (NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] = NM_TERNARY_FALSE; - } else if (i_run == 1) - do_set = FALSE; - else if (i_run == 2) { - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX (NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE; - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX (NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] = NM_TERNARY_TRUE; - } else if (i_run == 3) - do_set = FALSE; - - _LOGT (">>> ethtool-features-get RUN %u (do-set=%s", i_run, do_set ? "set" : "reset"); - - features = nmp_utils_ethtool_get_features (IFINDEX); - g_ptr_array_add (gfree_keeper, features); - - ethtool_features_dump (features); - - if (_LOGT_ENABLED ()) - _system ("ethtool -k lo"); - - if (!do_set) { - requested = gfree_keeper->pdata[i_run * 2 - 2]; - features = gfree_keeper->pdata[i_run * 2 - 1]; - } - - nmp_utils_ethtool_set_features (IFINDEX, features, requested, do_set); - } + gs_unref_ptrarray GPtrArray *gfree_keeper = g_ptr_array_new_with_free_func(g_free); + const int IFINDEX = 1; + guint i; + guint i_run; + + for (i_run = 0; i_run < 5; i_run++) { + NMEthtoolFeatureStates *features; + NMTernary * requested; + gboolean do_set = TRUE; + + requested = g_new(NMTernary, _NM_ETHTOOL_ID_FEATURE_NUM); + for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) + requested[i] = NM_TERNARY_DEFAULT; + g_ptr_array_add(gfree_keeper, requested); + + if (i_run == 0) { + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_RX)] = NM_TERNARY_FALSE; + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE; + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] = + NM_TERNARY_FALSE; + } else if (i_run == 1) + do_set = FALSE; + else if (i_run == 2) { + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE; + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] = + NM_TERNARY_TRUE; + } else if (i_run == 3) + do_set = FALSE; + + _LOGT(">>> ethtool-features-get RUN %u (do-set=%s", i_run, do_set ? "set" : "reset"); + + features = nmp_utils_ethtool_get_features(IFINDEX); + g_ptr_array_add(gfree_keeper, features); + + ethtool_features_dump(features); + + if (_LOGT_ENABLED()) + _system("ethtool -k lo"); + + if (!do_set) { + requested = gfree_keeper->pdata[i_run * 2 - 2]; + features = gfree_keeper->pdata[i_run * 2 - 1]; + } + + nmp_utils_ethtool_set_features(IFINDEX, features, requested, do_set); + } } /*****************************************************************************/ @@ -3325,73 +3719,98 @@ test_ethtool_features_get (void) NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; void -_nmtstp_init_tests (int *argc, char ***argv) +_nmtstp_init_tests(int *argc, char ***argv) { - nmtst_init_with_logging (argc, argv, NULL, "ALL"); + nmtst_init_with_logging(argc, argv, NULL, "ALL"); } void -_nmtstp_setup_tests (void) +_nmtstp_setup_tests(void) { - nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); - nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, SLAVE_NAME, FALSE); - nmtstp_link_delete (NM_PLATFORM_GET, -1, -1, PARENT_NAME, FALSE); - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, SLAVE_NAME)); - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, PARENT_NAME)); - - g_test_add_func ("/link/bogus", test_bogus); - g_test_add_func ("/link/loopback", test_loopback); - g_test_add_func ("/link/internal", test_internal); - g_test_add_func ("/link/software/bridge", test_bridge); - g_test_add_func ("/link/software/bond", test_bond); - g_test_add_func ("/link/software/team", test_team); - g_test_add_func ("/link/software/vlan", test_vlan); - g_test_add_func ("/link/software/bridge/addr", test_bridge_addr); - - if (nmtstp_is_root_test ()) { - g_test_add_func ("/link/external", test_external); - - test_software_detect_add ("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0); - test_software_detect_add ("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0); - test_software_detect_add ("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0); - test_software_detect_add ("/link/software/detect/ip6tnl/1", NM_LINK_TYPE_IP6TNL, 1); - test_software_detect_add ("/link/software/detect/ip6gre", NM_LINK_TYPE_IP6GRE, 0); - test_software_detect_add ("/link/software/detect/ip6gretap", NM_LINK_TYPE_IP6GRETAP, 0); - test_software_detect_add ("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0); - test_software_detect_add ("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0); - test_software_detect_add ("/link/software/detect/macvtap", NM_LINK_TYPE_MACVTAP, 0); - test_software_detect_add ("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0); - test_software_detect_add ("/link/software/detect/tun", NM_LINK_TYPE_TUN, 0); - test_software_detect_add ("/link/software/detect/vlan", NM_LINK_TYPE_VLAN, 0); - test_software_detect_add ("/link/software/detect/vrf", NM_LINK_TYPE_VRF, 0); - test_software_detect_add ("/link/software/detect/vxlan/0", NM_LINK_TYPE_VXLAN, 0); - test_software_detect_add ("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1); - test_software_detect_add ("/link/software/detect/wireguard/0", NM_LINK_TYPE_WIREGUARD, 0); - test_software_detect_add ("/link/software/detect/wireguard/1", NM_LINK_TYPE_WIREGUARD, 1); - test_software_detect_add ("/link/software/detect/wireguard/2", NM_LINK_TYPE_WIREGUARD, 2); - - g_test_add_func ("/link/software/vlan/set-xgress", test_vlan_set_xgress); - - g_test_add_data_func ("/link/create-many-links/20", GUINT_TO_POINTER (20), test_create_many_links); - g_test_add_data_func ("/link/create-many-links/1000", GUINT_TO_POINTER (1000), test_create_many_links); - - g_test_add_func ("/link/nl-bugs/veth", test_nl_bugs_veth); - g_test_add_func ("/link/nl-bugs/spurious-newlink", test_nl_bugs_spuroius_newlink); - g_test_add_func ("/link/nl-bugs/spurious-dellink", test_nl_bugs_spuroius_dellink); - - g_test_add_vtable ("/general/netns/general", 0, NULL, _test_netns_setup, test_netns_general, _test_netns_teardown); - g_test_add_vtable ("/general/netns/set-netns", 0, NULL, _test_netns_setup, test_netns_set_netns, _test_netns_teardown); - g_test_add_vtable ("/general/netns/push", 0, NULL, _test_netns_setup, test_netns_push, _test_netns_teardown); - g_test_add_vtable ("/general/netns/bind-to-path", 0, NULL, _test_netns_setup, test_netns_bind_to_path, _test_netns_teardown); - - g_test_add_func ("/general/netns/mt", test_netns_mt); - - g_test_add_func ("/general/sysctl/rename", test_sysctl_rename); - g_test_add_func ("/general/sysctl/netns-switch", test_sysctl_netns_switch); - g_test_add_func ("/general/sysctl/set-async", test_sysctl_set_async); - g_test_add_func ("/general/sysctl/set-async-fail", test_sysctl_set_async_fail); - - g_test_add_func ("/link/ethtool/features/get", test_ethtool_features_get); - } + nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, DEVICE_NAME, FALSE); + nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, SLAVE_NAME, FALSE); + nmtstp_link_delete(NM_PLATFORM_GET, -1, -1, PARENT_NAME, FALSE); + g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, DEVICE_NAME)); + g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, SLAVE_NAME)); + g_assert(!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, PARENT_NAME)); + + g_test_add_func("/link/bogus", test_bogus); + g_test_add_func("/link/loopback", test_loopback); + g_test_add_func("/link/internal", test_internal); + g_test_add_func("/link/software/bridge", test_bridge); + g_test_add_func("/link/software/bond", test_bond); + g_test_add_func("/link/software/team", test_team); + g_test_add_func("/link/software/vlan", test_vlan); + g_test_add_func("/link/software/bridge/addr", test_bridge_addr); + + if (nmtstp_is_root_test()) { + g_test_add_func("/link/external", test_external); + + test_software_detect_add("/link/software/detect/bridge", NM_LINK_TYPE_BRIDGE, 0); + test_software_detect_add("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0); + test_software_detect_add("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0); + test_software_detect_add("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0); + test_software_detect_add("/link/software/detect/ip6tnl/1", NM_LINK_TYPE_IP6TNL, 1); + test_software_detect_add("/link/software/detect/ip6gre", NM_LINK_TYPE_IP6GRE, 0); + test_software_detect_add("/link/software/detect/ip6gretap", NM_LINK_TYPE_IP6GRETAP, 0); + test_software_detect_add("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0); + test_software_detect_add("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0); + test_software_detect_add("/link/software/detect/macvtap", NM_LINK_TYPE_MACVTAP, 0); + test_software_detect_add("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0); + test_software_detect_add("/link/software/detect/tun", NM_LINK_TYPE_TUN, 0); + test_software_detect_add("/link/software/detect/vlan", NM_LINK_TYPE_VLAN, 0); + test_software_detect_add("/link/software/detect/vrf", NM_LINK_TYPE_VRF, 0); + test_software_detect_add("/link/software/detect/vxlan/0", NM_LINK_TYPE_VXLAN, 0); + test_software_detect_add("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1); + test_software_detect_add("/link/software/detect/wireguard/0", NM_LINK_TYPE_WIREGUARD, 0); + test_software_detect_add("/link/software/detect/wireguard/1", NM_LINK_TYPE_WIREGUARD, 1); + test_software_detect_add("/link/software/detect/wireguard/2", NM_LINK_TYPE_WIREGUARD, 2); + + g_test_add_func("/link/software/vlan/set-xgress", test_vlan_set_xgress); + + g_test_add_data_func("/link/create-many-links/20", + GUINT_TO_POINTER(20), + test_create_many_links); + g_test_add_data_func("/link/create-many-links/1000", + GUINT_TO_POINTER(1000), + test_create_many_links); + + g_test_add_func("/link/nl-bugs/veth", test_nl_bugs_veth); + g_test_add_func("/link/nl-bugs/spurious-newlink", test_nl_bugs_spuroius_newlink); + g_test_add_func("/link/nl-bugs/spurious-dellink", test_nl_bugs_spuroius_dellink); + + g_test_add_vtable("/general/netns/general", + 0, + NULL, + _test_netns_setup, + test_netns_general, + _test_netns_teardown); + g_test_add_vtable("/general/netns/set-netns", + 0, + NULL, + _test_netns_setup, + test_netns_set_netns, + _test_netns_teardown); + g_test_add_vtable("/general/netns/push", + 0, + NULL, + _test_netns_setup, + test_netns_push, + _test_netns_teardown); + g_test_add_vtable("/general/netns/bind-to-path", + 0, + NULL, + _test_netns_setup, + test_netns_bind_to_path, + _test_netns_teardown); + + g_test_add_func("/general/netns/mt", test_netns_mt); + + g_test_add_func("/general/sysctl/rename", test_sysctl_rename); + g_test_add_func("/general/sysctl/netns-switch", test_sysctl_netns_switch); + g_test_add_func("/general/sysctl/set-async", test_sysctl_set_async); + g_test_add_func("/general/sysctl/set-async-fail", test_sysctl_set_async_fail); + + g_test_add_func("/link/ethtool/features/get", test_ethtool_features_get); + } } diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c index 8ecfac8a..e61e6b09 100644 --- a/src/platform/tests/test-nmp-object.c +++ b/src/platform/tests/test-nmp-object.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 - 2017 Red Hat, Inc. */ @@ -14,571 +14,604 @@ #include "nm-test-utils-core.h" struct { - GList *udev_devices; + GList *udev_devices; } global; /*****************************************************************************/ static void -test_obj_base (void) +test_obj_base(void) { - static const union { - GObject g; - NMPObject k; - } x = { }; - static const union { - GTypeClass k; - NMPClass c; - } l = { }; - static const GObject *g = &x.g; - static const GTypeClass *k = &l.k; - static const NMPObject *o = &x.k; - static const NMPClass *c = &l.c; - - NMObjBaseInst *obj; - gs_unref_object GCancellable *obj_cancellable = g_cancellable_new (); - nm_auto_nmpobj NMPObject *obj_link = nmp_object_new_link (10); - - g_assert (&g->g_type_instance == (void *) &o->_class); - g_assert (&g->g_type_instance.g_class == (void *) &o->_class); - - g_assert (sizeof (o->parent.parent) == sizeof (GTypeInstance)); - - g_assert (&c->parent == (void *) c); - g_assert (&c->parent.parent.g_type_class == (void *) c); - g_assert (&c->parent.parent.g_type == (void *) c); - g_assert (&c->parent.parent.g_type == &k->g_type); - - g_assert (sizeof (c->parent.parent) == sizeof (GTypeClass)); - - g_assert (&o->parent == (void *) o); - g_assert (&o->parent.klass == (void *) &o->_class); - - obj = (NMObjBaseInst *) obj_cancellable; - g_assert (!NMP_CLASS_IS_VALID ((NMPClass *) obj->klass)); - g_assert (G_TYPE_CHECK_INSTANCE_TYPE (obj, G_TYPE_CANCELLABLE)); - - obj = (NMObjBaseInst *) obj_link; - g_assert (NMP_CLASS_IS_VALID ((NMPClass *) obj->klass)); - g_assert (!G_TYPE_CHECK_INSTANCE_TYPE (obj, G_TYPE_CANCELLABLE)); - + static const union { + GObject g; + NMPObject k; + } x = {}; + static const union { + GTypeClass k; + NMPClass c; + } l = {}; + static const GObject * g = &x.g; + static const GTypeClass *k = &l.k; + static const NMPObject * o = &x.k; + static const NMPClass * c = &l.c; + + NMObjBaseInst * obj; + gs_unref_object GCancellable *obj_cancellable = g_cancellable_new(); + nm_auto_nmpobj NMPObject *obj_link = nmp_object_new_link(10); + + g_assert(&g->g_type_instance == (void *) &o->_class); + g_assert(&g->g_type_instance.g_class == (void *) &o->_class); + + g_assert(sizeof(o->parent.parent) == sizeof(GTypeInstance)); + + g_assert(&c->parent == (void *) c); + g_assert(&c->parent.parent.g_type_class == (void *) c); + g_assert(&c->parent.parent.g_type == (void *) c); + g_assert(&c->parent.parent.g_type == &k->g_type); + + g_assert(sizeof(c->parent.parent) == sizeof(GTypeClass)); + + g_assert(&o->parent == (void *) o); + g_assert(&o->parent.klass == (void *) &o->_class); + + obj = (NMObjBaseInst *) obj_cancellable; + g_assert(!NMP_CLASS_IS_VALID((NMPClass *) obj->klass)); + g_assert(G_TYPE_CHECK_INSTANCE_TYPE(obj, G_TYPE_CANCELLABLE)); + + obj = (NMObjBaseInst *) obj_link; + g_assert(NMP_CLASS_IS_VALID((NMPClass *) obj->klass)); + g_assert(!G_TYPE_CHECK_INSTANCE_TYPE(obj, G_TYPE_CANCELLABLE)); } /*****************************************************************************/ static gboolean -_nmp_object_id_equal (const NMPObject *a, const NMPObject *b) +_nmp_object_id_equal(const NMPObject *a, const NMPObject *b) { - gboolean a_b = nmp_object_id_equal (a, b); + gboolean a_b = nmp_object_id_equal(a, b); - g_assert (NM_IN_SET (a_b, FALSE, TRUE) && a_b == nmp_object_id_equal (b, a)); - return a_b; + g_assert(NM_IN_SET(a_b, FALSE, TRUE) && a_b == nmp_object_id_equal(b, a)); + return a_b; } #define nmp_object_id_equal _nmp_object_id_equal static gboolean -_nmp_object_equal (const NMPObject *a, const NMPObject *b) +_nmp_object_equal(const NMPObject *a, const NMPObject *b) { - gboolean a_b = nmp_object_equal (a, b); + gboolean a_b = nmp_object_equal(a, b); - g_assert (NM_IN_SET (a_b, FALSE, TRUE) && a_b == nmp_object_equal (b, a)); - return a_b; + g_assert(NM_IN_SET(a_b, FALSE, TRUE) && a_b == nmp_object_equal(b, a)); + return a_b; } #define nmp_object_equal _nmp_object_equal /*****************************************************************************/ static void -_assert_cache_multi_lookup_contains (const NMPCache *cache, const NMDedupMultiHeadEntry *head_entry, const NMPObject *obj, gboolean visible_only, gboolean contains) +_assert_cache_multi_lookup_contains(const NMPCache * cache, + const NMDedupMultiHeadEntry *head_entry, + const NMPObject * obj, + gboolean visible_only, + gboolean contains) { - NMDedupMultiIter iter; - gboolean found; - guint i, len; - const NMPObject *o; - - g_assert (NMP_OBJECT_IS_VALID (obj)); - - g_assert (nmp_cache_lookup_obj (cache, obj) == obj); - g_assert (!head_entry || (head_entry->len > 0 && c_list_length (&head_entry->lst_entries_head) == head_entry->len)); - - len = head_entry ? head_entry->len : 0; - - found = FALSE; - i = 0; - nmp_cache_iter_for_each (&iter, - head_entry, - &o) { - g_assert (NMP_OBJECT_IS_VALID (o)); - if (obj == o) { - if ( !visible_only - || nmp_object_is_visible (o)) { - g_assert (!found); - found = TRUE; - } - } - i++; - } - - g_assert (len == i); - g_assert (!!contains == found); + NMDedupMultiIter iter; + gboolean found; + guint i, len; + const NMPObject *o; + + g_assert(NMP_OBJECT_IS_VALID(obj)); + + g_assert(nmp_cache_lookup_obj(cache, obj) == obj); + g_assert(!head_entry + || (head_entry->len > 0 + && c_list_length(&head_entry->lst_entries_head) == head_entry->len)); + + len = head_entry ? head_entry->len : 0; + + found = FALSE; + i = 0; + nmp_cache_iter_for_each (&iter, head_entry, &o) { + g_assert(NMP_OBJECT_IS_VALID(o)); + if (obj == o) { + if (!visible_only || nmp_object_is_visible(o)) { + g_assert(!found); + found = TRUE; + } + } + i++; + } + + g_assert(len == i); + g_assert(!!contains == found); } static void -_assert_cache_multi_lookup_contains_link (const NMPCache *cache, - gboolean visible_only, - const NMPObject *obj, - gboolean contains) +_assert_cache_multi_lookup_contains_link(const NMPCache * cache, + gboolean visible_only, + const NMPObject *obj, + gboolean contains) { - const NMDedupMultiHeadEntry *head_entry; - NMPLookup lookup; + const NMDedupMultiHeadEntry *head_entry; + NMPLookup lookup; - g_assert (cache); + g_assert(cache); - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK); - head_entry = nmp_cache_lookup (cache, &lookup); - _assert_cache_multi_lookup_contains (cache, head_entry, obj, visible_only, contains); + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK); + head_entry = nmp_cache_lookup(cache, &lookup); + _assert_cache_multi_lookup_contains(cache, head_entry, obj, visible_only, contains); } /*****************************************************************************/ static void -ops_post_check (NMPCache *cache, - NMPCacheOpsType ops_type, - const NMPObject *obj_old, - const NMPObject *obj_new, - const NMPObject *obj_new_expected, - NMPCacheOpsType expected_ops_type) +ops_post_check(NMPCache * cache, + NMPCacheOpsType ops_type, + const NMPObject *obj_old, + const NMPObject *obj_new, + const NMPObject *obj_new_expected, + NMPCacheOpsType expected_ops_type) { - g_assert (cache); - - g_assert_cmpint (expected_ops_type, ==, ops_type); - - switch (ops_type) { - case NMP_CACHE_OPS_ADDED: - g_assert (!obj_old); - g_assert (NMP_OBJECT_IS_VALID (obj_new)); - g_assert (nmp_object_is_alive (obj_new)); - g_assert (nmp_object_id_equal (obj_new_expected, obj_new)); - g_assert (nmp_object_equal (obj_new_expected, obj_new)); - break; - case NMP_CACHE_OPS_UPDATED: - g_assert (obj_old != obj_new); - g_assert (NMP_OBJECT_IS_VALID (obj_old)); - g_assert (NMP_OBJECT_IS_VALID (obj_new)); - g_assert (nmp_object_is_alive (obj_old)); - g_assert (nmp_object_is_alive (obj_new)); - g_assert (nmp_object_id_equal (obj_new_expected, obj_new)); - g_assert (nmp_object_id_equal (obj_new_expected, obj_old)); - g_assert (nmp_object_id_equal (obj_old, obj_new)); - g_assert (nmp_object_equal (obj_new_expected, obj_new)); - g_assert (!nmp_object_equal (obj_new_expected, obj_old)); - g_assert (!nmp_object_equal (obj_old, obj_new)); - break; - case NMP_CACHE_OPS_REMOVED: - g_assert (!obj_new); - g_assert (NMP_OBJECT_IS_VALID (obj_old)); - g_assert (nmp_object_is_alive (obj_old)); - if (obj_new_expected) - g_assert (nmp_object_id_equal (obj_new_expected, obj_old)); - break; - case NMP_CACHE_OPS_UNCHANGED: - g_assert (obj_old == obj_new); - if (obj_old) { - g_assert (NMP_OBJECT_IS_VALID (obj_old)); - g_assert (nmp_object_is_alive (obj_old)); - g_assert (nmp_object_equal (obj_old, obj_new)); - g_assert (nmp_object_id_equal (obj_new_expected, obj_new)); - } else - g_assert (!obj_new_expected); - break; - default: - g_assert_not_reached (); - } + g_assert(cache); + + g_assert_cmpint(expected_ops_type, ==, ops_type); + + switch (ops_type) { + case NMP_CACHE_OPS_ADDED: + g_assert(!obj_old); + g_assert(NMP_OBJECT_IS_VALID(obj_new)); + g_assert(nmp_object_is_alive(obj_new)); + g_assert(nmp_object_id_equal(obj_new_expected, obj_new)); + g_assert(nmp_object_equal(obj_new_expected, obj_new)); + break; + case NMP_CACHE_OPS_UPDATED: + g_assert(obj_old != obj_new); + g_assert(NMP_OBJECT_IS_VALID(obj_old)); + g_assert(NMP_OBJECT_IS_VALID(obj_new)); + g_assert(nmp_object_is_alive(obj_old)); + g_assert(nmp_object_is_alive(obj_new)); + g_assert(nmp_object_id_equal(obj_new_expected, obj_new)); + g_assert(nmp_object_id_equal(obj_new_expected, obj_old)); + g_assert(nmp_object_id_equal(obj_old, obj_new)); + g_assert(nmp_object_equal(obj_new_expected, obj_new)); + g_assert(!nmp_object_equal(obj_new_expected, obj_old)); + g_assert(!nmp_object_equal(obj_old, obj_new)); + break; + case NMP_CACHE_OPS_REMOVED: + g_assert(!obj_new); + g_assert(NMP_OBJECT_IS_VALID(obj_old)); + g_assert(nmp_object_is_alive(obj_old)); + if (obj_new_expected) + g_assert(nmp_object_id_equal(obj_new_expected, obj_old)); + break; + case NMP_CACHE_OPS_UNCHANGED: + g_assert(obj_old == obj_new); + if (obj_old) { + g_assert(NMP_OBJECT_IS_VALID(obj_old)); + g_assert(nmp_object_is_alive(obj_old)); + g_assert(nmp_object_equal(obj_old, obj_new)); + g_assert(nmp_object_id_equal(obj_new_expected, obj_new)); + } else + g_assert(!obj_new_expected); + break; + default: + g_assert_not_reached(); + } } static void -_nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, const NMPObject **out_obj_old, const NMPObject **out_obj_new, NMPCacheOpsType expected_ops_type) +_nmp_cache_update_netlink(NMPCache * cache, + NMPObject * obj, + const NMPObject **out_obj_old, + const NMPObject **out_obj_new, + NMPCacheOpsType expected_ops_type) { - NMPCacheOpsType ops_type; - const NMPObject *obj_prev; - const NMPObject *obj_old; - const NMPObject *obj_new; - nm_auto_nmpobj NMPObject *obj_new_expected = NULL; - - g_assert (cache); - g_assert (NMP_OBJECT_IS_VALID (obj)); - - obj_prev = nmp_cache_lookup_link (cache, NMP_OBJECT_CAST_LINK (obj)->ifindex); - obj_new_expected = nmp_object_clone (obj, FALSE); - if (obj_prev && obj_prev->_link.udev.device) - obj_new_expected->_link.udev.device = udev_device_ref (obj_prev->_link.udev.device); - _nmp_object_fixup_link_udev_fields (&obj_new_expected, NULL, nmp_cache_use_udev_get (cache)); - - ops_type = nmp_cache_update_netlink (cache, obj, FALSE, &obj_old, &obj_new); - ops_post_check (cache, ops_type, obj_old, obj_new, - nmp_object_is_alive (obj_new_expected) ? obj_new_expected : NULL, - expected_ops_type); - - if (out_obj_new) - *out_obj_new = obj_new; - else - nmp_object_unref (obj_new); - if (out_obj_old) - *out_obj_old = obj_old; - else - nmp_object_unref (obj_old); + NMPCacheOpsType ops_type; + const NMPObject *obj_prev; + const NMPObject *obj_old; + const NMPObject *obj_new; + nm_auto_nmpobj NMPObject *obj_new_expected = NULL; + + g_assert(cache); + g_assert(NMP_OBJECT_IS_VALID(obj)); + + obj_prev = nmp_cache_lookup_link(cache, NMP_OBJECT_CAST_LINK(obj)->ifindex); + obj_new_expected = nmp_object_clone(obj, FALSE); + if (obj_prev && obj_prev->_link.udev.device) + obj_new_expected->_link.udev.device = udev_device_ref(obj_prev->_link.udev.device); + _nmp_object_fixup_link_udev_fields(&obj_new_expected, NULL, nmp_cache_use_udev_get(cache)); + + ops_type = nmp_cache_update_netlink(cache, obj, FALSE, &obj_old, &obj_new); + ops_post_check(cache, + ops_type, + obj_old, + obj_new, + nmp_object_is_alive(obj_new_expected) ? obj_new_expected : NULL, + expected_ops_type); + + if (out_obj_new) + *out_obj_new = obj_new; + else + nmp_object_unref(obj_new); + if (out_obj_old) + *out_obj_old = obj_old; + else + nmp_object_unref(obj_old); } static const NMPlatformLink pl_link_2 = { - .ifindex = 2, - .name = "eth0", - .type = NM_LINK_TYPE_ETHERNET, + .ifindex = 2, + .name = "eth0", + .type = NM_LINK_TYPE_ETHERNET, }; static const NMPlatformLink pl_link_3 = { - .ifindex = 3, - .name = "wlan0", - .type = NM_LINK_TYPE_WIFI, + .ifindex = 3, + .name = "wlan0", + .type = NM_LINK_TYPE_WIFI, }; static void -test_cache_link (void) +test_cache_link(void) { - NMPCache *cache; - NMPObject *objm1; - const NMPObject *obj_old, *obj_new; - NMPObject objs1; - struct udev_device *udev_device_2 = g_list_nth_data (global.udev_devices, 0); - struct udev_device *udev_device_3 = g_list_nth_data (global.udev_devices, 0); - NMPCacheOpsType ops_type; - nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL; - gboolean use_udev = nmtst_get_rand_uint32 () % 2; - - multi_idx = nm_dedup_multi_index_new (); - - cache = nmp_cache_new (multi_idx, use_udev); - - /* if we have a link, and don't set is_in_netlink, adding it has no effect. */ - objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - g_assert (NMP_OBJECT_UP_CAST (&objm1->object) == objm1); - g_assert (!nmp_object_is_alive (objm1)); - _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED); - ASSERT_nmp_cache_is_consistent (cache); - g_assert (!obj_old); - g_assert (!obj_new); - g_assert (!nmp_cache_lookup_obj (cache, objm1)); - g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex))); - nmp_object_unref (objm1); - - /* Only when setting @is_in_netlink the link is added. */ - objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - objm1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (objm1)); - _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_ADDED); - ASSERT_nmp_cache_is_consistent (cache); - g_assert (!obj_old); - g_assert (obj_new); - g_assert (objm1 == obj_new); - g_assert (nmp_object_equal (objm1, obj_new)); - g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); - g_assert (nmp_object_is_visible (obj_new)); - _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); - _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); - nmp_object_unref (objm1); - nmp_object_unref (obj_new); - - /* updating the same link with identical value, has no effect. */ - objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - objm1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (objm1)); - _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED); - ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj_old); - g_assert (obj_new); - g_assert (obj_new != objm1); - g_assert (nmp_object_equal (objm1, obj_new)); - g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); - nmp_object_unref (objm1); - nmp_object_unref (obj_new); - nmp_object_unref (obj_new); - - /* remove the link from netlink */ - objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - g_assert (!nmp_object_is_alive (objm1)); - _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_REMOVED); - ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj_old); - g_assert (!obj_new); - g_assert (!nmp_cache_lookup_obj (cache, objm1)); - g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex))); - nmp_object_unref (objm1); - nmp_object_unref (obj_old); - nmp_object_unref (obj_new); - - if (udev_device_2) { - /* now add the link only with aspect UDEV. */ - ops_type = nmp_cache_update_link_udev (cache, pl_link_2.ifindex, udev_device_2, &obj_old, &obj_new); - ASSERT_nmp_cache_is_consistent (cache); - g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED); - g_assert (!obj_old); - g_assert (obj_new); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); - g_assert (!nmp_object_is_visible (obj_new)); - _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE); - _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); - nmp_object_unref (obj_new); - } - - /* add it in netlink too. */ - objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - objm1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (objm1)); - _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED); - ASSERT_nmp_cache_is_consistent (cache); - if (udev_device_2) { - g_assert (obj_old); - g_assert (!nmp_object_is_visible (obj_old)); - } else - g_assert (!obj_old); - g_assert (nmp_object_equal (objm1, obj_new)); - g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); - g_assert (nmp_object_is_visible (obj_new)); - _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); - _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); - nmp_object_unref (objm1); - nmp_object_unref (obj_old); - nmp_object_unref (obj_new); - - /* remove again from netlink. */ - objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - objm1->_link.netlink.is_in_netlink = FALSE; - g_assert (!nmp_object_is_alive (objm1)); - _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED); - ASSERT_nmp_cache_is_consistent (cache); - if (udev_device_2) - g_assert (obj_new == objm1); - else - g_assert (!obj_new); - g_assert (obj_old); - g_assert (nmp_object_is_alive (obj_old)); - if (udev_device_2) { - g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); - g_assert (!nmp_object_is_visible (obj_new)); - _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE); - _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); - } else { - g_assert (nmp_cache_lookup_obj (cache, objm1) == NULL); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == NULL); - g_assert (!nmp_object_is_alive (obj_new)); - g_assert (!nmp_object_is_visible (obj_new)); - } - nmp_object_unref (objm1); - nmp_object_unref (obj_old); - nmp_object_unref (obj_new); - - /* now another link only with aspect UDEV. */ - if (udev_device_3) { - /* now add the link only with aspect UDEV. */ - ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, udev_device_3, &obj_old, &obj_new); - g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED); - ASSERT_nmp_cache_is_consistent (cache); - g_assert (NMP_OBJECT_IS_VALID (obj_new)); - g_assert (!obj_old); - g_assert (!nmp_object_is_visible (obj_new)); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new); - _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE); - _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); - g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, FALSE); - g_assert_cmpint (obj_new->link.initialized, ==, FALSE); - nmp_object_unref (obj_new); - - /* add it in netlink too. */ - objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3); - objm1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (objm1)); - _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UPDATED); - ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj_old); - g_assert (obj_new == objm1); - g_assert (nmp_object_equal (objm1, obj_new)); - g_assert (!obj_old || !nmp_object_is_visible (obj_old)); - g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new); - g_assert (nmp_object_is_visible (obj_new)); - _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); - _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); - g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, TRUE); - g_assert_cmpint (obj_new->link.initialized, ==, TRUE); - nmp_object_unref (objm1); - nmp_object_unref (obj_old); - nmp_object_unref (obj_new); - - /* remove UDEV. */ - ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, NULL, &obj_old, &obj_new); - g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_UPDATED); - ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj_old && nmp_object_is_visible (obj_old)); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new); - g_assert (nmp_object_is_visible (obj_new)); - _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); - _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); - g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, TRUE); - g_assert_cmpint (obj_new->link.initialized, ==, !nmp_cache_use_udev_get (cache)); - nmp_object_unref (obj_new); - nmp_object_unref (obj_old); - } - - nmp_cache_free (cache); + NMPCache * cache; + NMPObject * objm1; + const NMPObject * obj_old, *obj_new; + NMPObject objs1; + struct udev_device * udev_device_2 = g_list_nth_data(global.udev_devices, 0); + struct udev_device * udev_device_3 = g_list_nth_data(global.udev_devices, 0); + NMPCacheOpsType ops_type; + nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL; + gboolean use_udev = nmtst_get_rand_uint32() % 2; + + multi_idx = nm_dedup_multi_index_new(); + + cache = nmp_cache_new(multi_idx, use_udev); + + /* if we have a link, and don't set is_in_netlink, adding it has no effect. */ + objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + g_assert(NMP_OBJECT_UP_CAST(&objm1->object) == objm1); + g_assert(!nmp_object_is_alive(objm1)); + _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert(!obj_old); + g_assert(!obj_new); + g_assert(!nmp_cache_lookup_obj(cache, objm1)); + g_assert(!nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))); + nmp_object_unref(objm1); + + /* Only when setting @is_in_netlink the link is added. */ + objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert(nmp_object_is_alive(objm1)); + _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_ADDED); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert(!obj_old); + g_assert(obj_new); + g_assert(objm1 == obj_new); + g_assert(nmp_object_equal(objm1, obj_new)); + g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new); + g_assert(nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)) + == obj_new); + g_assert(nmp_object_is_visible(obj_new)); + _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE); + nmp_object_unref(objm1); + nmp_object_unref(obj_new); + + /* updating the same link with identical value, has no effect. */ + objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert(nmp_object_is_alive(objm1)); + _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert(obj_old); + g_assert(obj_new); + g_assert(obj_new != objm1); + g_assert(nmp_object_equal(objm1, obj_new)); + g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new); + g_assert(nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)) + == obj_new); + nmp_object_unref(objm1); + nmp_object_unref(obj_new); + nmp_object_unref(obj_new); + + /* remove the link from netlink */ + objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + g_assert(!nmp_object_is_alive(objm1)); + _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_REMOVED); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert(obj_old); + g_assert(!obj_new); + g_assert(!nmp_cache_lookup_obj(cache, objm1)); + g_assert(!nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex))); + nmp_object_unref(objm1); + nmp_object_unref(obj_old); + nmp_object_unref(obj_new); + + if (udev_device_2) { + /* now add the link only with aspect UDEV. */ + ops_type = + nmp_cache_update_link_udev(cache, pl_link_2.ifindex, udev_device_2, &obj_old, &obj_new); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert_cmpint(ops_type, ==, NMP_CACHE_OPS_ADDED); + g_assert(!obj_old); + g_assert(obj_new); + g_assert( + nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)) + == obj_new); + g_assert(!nmp_object_is_visible(obj_new)); + _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, FALSE); + _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE); + nmp_object_unref(obj_new); + } + + /* add it in netlink too. */ + objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert(nmp_object_is_alive(objm1)); + _nmp_cache_update_netlink(cache, + objm1, + &obj_old, + &obj_new, + udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED); + nmtst_assert_nmp_cache_is_consistent(cache); + if (udev_device_2) { + g_assert(obj_old); + g_assert(!nmp_object_is_visible(obj_old)); + } else + g_assert(!obj_old); + g_assert(nmp_object_equal(objm1, obj_new)); + g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new); + g_assert(nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)) + == obj_new); + g_assert(nmp_object_is_visible(obj_new)); + _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE); + nmp_object_unref(objm1); + nmp_object_unref(obj_old); + nmp_object_unref(obj_new); + + /* remove again from netlink. */ + objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = FALSE; + g_assert(!nmp_object_is_alive(objm1)); + _nmp_cache_update_netlink(cache, + objm1, + &obj_old, + &obj_new, + udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED); + nmtst_assert_nmp_cache_is_consistent(cache); + if (udev_device_2) + g_assert(obj_new == objm1); + else + g_assert(!obj_new); + g_assert(obj_old); + g_assert(nmp_object_is_alive(obj_old)); + if (udev_device_2) { + g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new); + g_assert( + nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)) + == obj_new); + g_assert(!nmp_object_is_visible(obj_new)); + _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, FALSE); + _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE); + } else { + g_assert(nmp_cache_lookup_obj(cache, objm1) == NULL); + g_assert( + nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_2.ifindex)) + == NULL); + g_assert(!nmp_object_is_alive(obj_new)); + g_assert(!nmp_object_is_visible(obj_new)); + } + nmp_object_unref(objm1); + nmp_object_unref(obj_old); + nmp_object_unref(obj_new); + + /* now another link only with aspect UDEV. */ + if (udev_device_3) { + /* now add the link only with aspect UDEV. */ + ops_type = + nmp_cache_update_link_udev(cache, pl_link_3.ifindex, udev_device_3, &obj_old, &obj_new); + g_assert_cmpint(ops_type, ==, NMP_CACHE_OPS_ADDED); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert(NMP_OBJECT_IS_VALID(obj_new)); + g_assert(!obj_old); + g_assert(!nmp_object_is_visible(obj_new)); + g_assert( + nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_3.ifindex)) + == obj_new); + _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, FALSE); + _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE); + g_assert_cmpint(obj_new->_link.netlink.is_in_netlink, ==, FALSE); + g_assert_cmpint(obj_new->link.initialized, ==, FALSE); + nmp_object_unref(obj_new); + + /* add it in netlink too. */ + objm1 = nmp_object_new(NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert(nmp_object_is_alive(objm1)); + _nmp_cache_update_netlink(cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UPDATED); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert(obj_old); + g_assert(obj_new == objm1); + g_assert(nmp_object_equal(objm1, obj_new)); + g_assert(!obj_old || !nmp_object_is_visible(obj_old)); + g_assert(nmp_cache_lookup_obj(cache, objm1) == obj_new); + g_assert( + nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_3.ifindex)) + == obj_new); + g_assert(nmp_object_is_visible(obj_new)); + _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE); + g_assert_cmpint(obj_new->_link.netlink.is_in_netlink, ==, TRUE); + g_assert_cmpint(obj_new->link.initialized, ==, TRUE); + nmp_object_unref(objm1); + nmp_object_unref(obj_old); + nmp_object_unref(obj_new); + + /* remove UDEV. */ + ops_type = nmp_cache_update_link_udev(cache, pl_link_3.ifindex, NULL, &obj_old, &obj_new); + g_assert_cmpint(ops_type, ==, NMP_CACHE_OPS_UPDATED); + nmtst_assert_nmp_cache_is_consistent(cache); + g_assert(obj_old && nmp_object_is_visible(obj_old)); + g_assert( + nmp_cache_lookup_obj(cache, nmp_object_stackinit_id_link(&objs1, pl_link_3.ifindex)) + == obj_new); + g_assert(nmp_object_is_visible(obj_new)); + _assert_cache_multi_lookup_contains_link(cache, TRUE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link(cache, FALSE, obj_new, TRUE); + g_assert_cmpint(obj_new->_link.netlink.is_in_netlink, ==, TRUE); + g_assert_cmpint(obj_new->link.initialized, ==, !nmp_cache_use_udev_get(cache)); + nmp_object_unref(obj_new); + nmp_object_unref(obj_old); + } + + nmp_cache_free(cache); } -const char noqueue[] = "noqueue"; +const char noqueue[] = "noqueue"; const char fq_codel[] = "fq_codel"; -const char ingress[] = "ingress"; +const char ingress[] = "ingress"; static const NMPlatformQdisc pl_qdisc_1a = { - .ifindex = 1, - .kind = noqueue, - .addr_family = AF_UNSPEC, - .handle = 0, - .parent = TC_H_ROOT, - .info = 0, + .ifindex = 1, + .kind = noqueue, + .addr_family = AF_UNSPEC, + .handle = 0, + .parent = TC_H_ROOT, + .info = 0, }; static const NMPlatformQdisc pl_qdisc_1b = { - .ifindex = 1, - .kind = fq_codel, - .addr_family = AF_UNSPEC, - .handle = 0, - .parent = TC_H_ROOT, - .info = 0, + .ifindex = 1, + .kind = fq_codel, + .addr_family = AF_UNSPEC, + .handle = 0, + .parent = TC_H_ROOT, + .info = 0, }; static const NMPlatformQdisc pl_qdisc_1c = { - .ifindex = 1, - .kind = ingress, - .addr_family = AF_UNSPEC, - .handle = TC_H_MAKE(TC_H_INGRESS, 0), - .parent = TC_H_INGRESS, - .info = 0, + .ifindex = 1, + .kind = ingress, + .addr_family = AF_UNSPEC, + .handle = TC_H_MAKE(TC_H_INGRESS, 0), + .parent = TC_H_INGRESS, + .info = 0, }; static const NMPlatformQdisc pl_qdisc_2 = { - .ifindex = 2, - .kind = fq_codel, - .addr_family = AF_UNSPEC, - .handle = 0, - .parent = TC_H_ROOT, - .info = 0, + .ifindex = 2, + .kind = fq_codel, + .addr_family = AF_UNSPEC, + .handle = 0, + .parent = TC_H_ROOT, + .info = 0, }; static void -test_cache_qdisc (void) +test_cache_qdisc(void) { - NMPCache *cache; - nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL; - NMPLookup lookup; - const NMDedupMultiHeadEntry *head_entry; - nm_auto_nmpobj NMPObject *obj1a = nmp_object_new (NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1a); - nm_auto_nmpobj NMPObject *obj1b = nmp_object_new (NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1b); - nm_auto_nmpobj NMPObject *obj1c = nmp_object_new (NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1c); - nm_auto_nmpobj NMPObject *obj2 = nmp_object_new (NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_2); - - multi_idx = nm_dedup_multi_index_new (); - cache = nmp_cache_new (multi_idx, nmtst_get_rand_uint32 () % 2); - - g_assert (nmp_cache_lookup_obj (cache, obj1a) == NULL); - - g_assert (nmp_cache_update_netlink (cache, obj1a, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED); - g_assert (nmp_cache_lookup_obj (cache, obj1a) == obj1a); - g_assert (nmp_cache_lookup_obj (cache, obj1b) == obj1a); - g_assert (nmp_cache_lookup_obj (cache, obj2) == NULL); - - g_assert (nmp_cache_update_netlink (cache, obj1b, FALSE, NULL, NULL) == NMP_CACHE_OPS_UPDATED); - g_assert (nmp_cache_lookup_obj (cache, obj1a) == obj1b); - g_assert (nmp_cache_lookup_obj (cache, obj1b) == obj1b); - g_assert (nmp_cache_lookup_obj (cache, obj2) == NULL); - - g_assert (nmp_cache_update_netlink (cache, obj1c, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED); - g_assert (nmp_cache_lookup_obj (cache, obj1a) == obj1b); - g_assert (nmp_cache_lookup_obj (cache, obj1b) == obj1b); - g_assert (nmp_cache_lookup_obj (cache, obj1c) == obj1c); - g_assert (nmp_cache_lookup_obj (cache, obj2) == NULL); - - g_assert (nmp_cache_update_netlink (cache, obj2, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED); - g_assert (nmp_cache_lookup_obj (cache, obj1a) == obj1b); - g_assert (nmp_cache_lookup_obj (cache, obj1b) == obj1b); - g_assert (nmp_cache_lookup_obj (cache, obj2) == obj2); - - head_entry = nmp_cache_lookup (cache, - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_QDISC, - 1)); - g_assert (head_entry->len == 2); - - nmp_cache_free (cache); + NMPCache * cache; + nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL; + NMPLookup lookup; + const NMDedupMultiHeadEntry * head_entry; + nm_auto_nmpobj NMPObject *obj1a = + nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1a); + nm_auto_nmpobj NMPObject *obj1b = + nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1b); + nm_auto_nmpobj NMPObject *obj1c = + nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_1c); + nm_auto_nmpobj NMPObject *obj2 = + nmp_object_new(NMP_OBJECT_TYPE_QDISC, (NMPlatformObject *) &pl_qdisc_2); + + multi_idx = nm_dedup_multi_index_new(); + cache = nmp_cache_new(multi_idx, nmtst_get_rand_uint32() % 2); + + g_assert(nmp_cache_lookup_obj(cache, obj1a) == NULL); + + g_assert(nmp_cache_update_netlink(cache, obj1a, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED); + g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1a); + g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1a); + g_assert(nmp_cache_lookup_obj(cache, obj2) == NULL); + + g_assert(nmp_cache_update_netlink(cache, obj1b, FALSE, NULL, NULL) == NMP_CACHE_OPS_UPDATED); + g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1b); + g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1b); + g_assert(nmp_cache_lookup_obj(cache, obj2) == NULL); + + g_assert(nmp_cache_update_netlink(cache, obj1c, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED); + g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1b); + g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1b); + g_assert(nmp_cache_lookup_obj(cache, obj1c) == obj1c); + g_assert(nmp_cache_lookup_obj(cache, obj2) == NULL); + + g_assert(nmp_cache_update_netlink(cache, obj2, FALSE, NULL, NULL) == NMP_CACHE_OPS_ADDED); + g_assert(nmp_cache_lookup_obj(cache, obj1a) == obj1b); + g_assert(nmp_cache_lookup_obj(cache, obj1b) == obj1b); + g_assert(nmp_cache_lookup_obj(cache, obj2) == obj2); + + head_entry = nmp_cache_lookup(cache, nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_QDISC, 1)); + g_assert(head_entry->len == 2); + + nmp_cache_free(cache); } /*****************************************************************************/ -NMTST_DEFINE (); +NMTST_DEFINE(); int -main (int argc, char **argv) +main(int argc, char **argv) { - int result; - NMUdevClient *udev_client; + int result; + NMUdevClient *udev_client; - nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT"); + nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT"); - udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, - NULL, NULL); - { - struct udev_enumerate *enumerator; - struct udev_list_entry *devices, *l; + udev_client = nm_udev_client_new((const char *[]){"net", NULL}, NULL, NULL); + { + struct udev_enumerate * enumerator; + struct udev_list_entry *devices, *l; - enumerator = nm_udev_client_enumerate_new (udev_client); + enumerator = nm_udev_client_enumerate_new(udev_client); - /* Demand that the device is initialized (udev rules ran, - * device has a stable name now) in case udev is running - * (not in a container). */ - if (access ("/sys", W_OK) == 0) - udev_enumerate_add_match_is_initialized (enumerator); + /* Demand that the device is initialized (udev rules ran, + * device has a stable name now) in case udev is running + * (not in a container). */ + if (access("/sys", W_OK) == 0) + udev_enumerate_add_match_is_initialized(enumerator); - udev_enumerate_scan_devices (enumerator); + udev_enumerate_scan_devices(enumerator); - devices = udev_enumerate_get_list_entry (enumerator); - for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) { - struct udev_device *udevice; + devices = udev_enumerate_get_list_entry(enumerator); + for (l = devices; l != NULL; l = udev_list_entry_get_next(l)) { + struct udev_device *udevice; - udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator), - udev_list_entry_get_name (l)); - if (udevice == NULL) - continue; + udevice = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), + udev_list_entry_get_name(l)); + if (udevice == NULL) + continue; - global.udev_devices = g_list_prepend (global.udev_devices, udevice); - } - global.udev_devices = g_list_reverse (global.udev_devices); + global.udev_devices = g_list_prepend(global.udev_devices, udevice); + } + global.udev_devices = g_list_reverse(global.udev_devices); - udev_enumerate_unref (enumerator); - } + udev_enumerate_unref(enumerator); + } - g_test_add_func ("/nmp-object/obj-base", test_obj_base); - g_test_add_func ("/nmp-object/cache_link", test_cache_link); - g_test_add_func ("/nmp-object/cache_qdisc", test_cache_qdisc); + g_test_add_func("/nmp-object/obj-base", test_obj_base); + g_test_add_func("/nmp-object/cache_link", test_cache_link); + g_test_add_func("/nmp-object/cache_qdisc", test_cache_qdisc); - result = g_test_run (); + result = g_test_run(); - while (global.udev_devices) { - udev_device_unref (global.udev_devices->data); - global.udev_devices = g_list_delete_link (global.udev_devices, global.udev_devices); - } + while (global.udev_devices) { + udev_device_unref(global.udev_devices->data); + global.udev_devices = g_list_delete_link(global.udev_devices, global.udev_devices); + } - nm_udev_client_unref (udev_client); + nm_udev_client_unref(udev_client); - return result; + return result; } - diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c index 255210f2..f98f84c9 100644 --- a/src/platform/tests/test-platform-general.c +++ b/src/platform/tests/test-platform-general.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ @@ -14,64 +14,730 @@ /*****************************************************************************/ +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr) + == G_STRUCT_OFFSET(NMPlatformIP4Address, address)); +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr) + == G_STRUCT_OFFSET(NMPlatformIP6Address, address)); + +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr) + == G_STRUCT_OFFSET(NMPlatformIP4Route, network)); +G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr) + == G_STRUCT_OFFSET(NMPlatformIP6Route, network)); + +/*****************************************************************************/ + static void -test_init_linux_platform (void) +test_init_linux_platform(void) { - gs_unref_object NMPlatform *platform = NULL; + gs_unref_object NMPlatform *platform = NULL; - platform = nm_linux_platform_new (TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); + platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); } /*****************************************************************************/ static void -test_link_get_all (void) +test_link_get_all(void) { - gs_unref_object NMPlatform *platform = NULL; - gs_unref_ptrarray GPtrArray *links = NULL; + gs_unref_object NMPlatform *platform = NULL; + gs_unref_ptrarray GPtrArray *links = NULL; - platform = nm_linux_platform_new (TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); + platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); - links = nm_platform_link_get_all (platform, TRUE); + links = nm_platform_link_get_all(platform, TRUE); } /*****************************************************************************/ static void -test_nm_platform_link_flags2str (void) +test_nm_platform_link_flags2str(void) { - int i; - - for (i = 0; i < 100; i++) { - char buf[NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN + 100]; - const char *s; - const guint flags = ((i == 0) ? ~0u : nmtst_get_rand_uint ()); - gsize l; - - s = nm_platform_link_flags2str (flags, buf, sizeof (buf)); - g_assert (s); - - l = strlen (s); - if (l > NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN) - g_error ("nm_platform_link_flags2str(%x) produced a longer output than %zu chars: \"%s\"", flags, NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN, s); - if ( flags == ~0u - && l != NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN) - g_error ("nm_platform_link_flags2str(%x) is expected to produce %zu chars, but produced %zu: \"%s\"", flags, NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN, l, s); - } + int i; + + for (i = 0; i < 100; i++) { + char buf[NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN + 100]; + const char *s; + const guint flags = ((i == 0) ? ~0u : nmtst_get_rand_uint()); + gsize l; + + s = nm_platform_link_flags2str(flags, buf, sizeof(buf)); + g_assert(s); + + l = strlen(s); + if (l > NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN) + g_error( + "nm_platform_link_flags2str(%x) produced a longer output than %zu chars: \"%s\"", + flags, + NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN, + s); + if (flags == ~0u && l != NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN) + g_error("nm_platform_link_flags2str(%x) is expected to produce %zu chars, but produced " + "%zu: \"%s\"", + flags, + NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN, + l, + s); + } +} + +/*****************************************************************************/ + +static int +_address_pretty_sort_cmp(gconstpointer a, gconstpointer b, gpointer test_data) +{ + const int TEST_DATA_I = GPOINTER_TO_INT(test_data); + const int addr_family = (TEST_DATA_I == 0 ? AF_INET : AF_INET6); + const int IPV6_PREFER_TEMP = (TEST_DATA_I == 2); + const NMPlatformIPXAddress *a_a = a; + const NMPlatformIPXAddress *a_b = b; + + if (addr_family == AF_INET) + return nm_platform_ip4_address_pretty_sort_cmp(&a_a->a4, &a_b->a4); + + return nm_platform_ip6_address_pretty_sort_cmp(&a_a->a6, &a_b->a6, IPV6_PREFER_TEMP); +} + +static void +test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) +{ + static const char *const EXPECTED_BUFFER[3] = { + [0] = ("5b1aea34648cabfec7c3523f76cf1ce34ca17a9a32f3f0f218424e48836dd1cb504e03d53e1124c5" + "0065aeb2e6fbf952902383028e3b47f280f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a" + "8982c42f0000003437c5156e072b2f2f0037c9cfe07c34ddb3980deb14ab7b5af84a034703000000" + "883b0f3fd6ed84d6c959e553b887edcd01c2f5d200000043b809d259e499db7d00f1853bdcb0e4bc" + "0e2b00b667b7b16d8d1e69c803000000b973972c17a47631c169f11ff9119c400368b6630000007a" + "034f43340d01683c0045097aea4a849f060ddf57b24a5be9636360d603000000ad7c499dd538d345" + "74c038404923e75d0209e2fc0000004acc807cdce682f80f00315c45ef817264c89a736ed55ed637" + "b96c200203000000faf1809becd2506315a6da29b2e94d3a031fe0e900000083a36035fb6297dfa7" + "00686b5efd0d53bb6215de4bb6f6f3d031a79028030000008bb836c0a25ea71f5daaed4d99eb2ebe" + "033c432f000000bf4ccf30d3aaaf02a4005d7308b67f91bf9d82c856ba942455e8d07c8403000000" + "f2abb982b001ec16901f55f960c55c22022099a80000002b4d4647f53b1921af0088e3759a08e7a5" + "6663861eea1bf42c12ea3b9503000000fb95e8332fdfff658483a2d039a7bf1402d3481e00000060" + "e89f7abdb682380a00eae374835b4a49a2b980b6aba92da6409969aa03000000e00473755d31e5b2" + "de252167c1c91b3a02ba0c700000007740318db913a353ed006efc068829c0e66ad0143a0554efb4" + "40e55b8b03000000c0cfb2b4386bec092fa5757ecde9348b00c12ebd000000ab667224dae775e5cc" + "0041aca2ff0f576767d3648102b61886d149f07403000000153ece68ade15cec25a59273e7519f34" + "c4458d70000000f3819aa46fbe1439340033ae6dec0fb124f264af67eed7c9a8ecc8fb1103000000" + "fcebbaeb0c56535923f14874042a8aff021f8e5ec3cc13cc36bbe3c9bb0ec36f00e007bb64a2827b" + "7cdd38d0314c178e5a06c40b03000000ab90135fa636af4464d210a256be75e0029c44770000004b" + "2e69220d6c0fc09c25d6534c809829af4a9df58dbfef186d416f3a1e030000002c932e655203d82a" + "3c84c4eb274ed18603780281000000f2235376239daeaacb3cae864b437baaae91921681c2162b9b" + "69e66142030000004fda8a3e0b841cf76391dd68269b53ec0244a831000000b78c54dda9ac3bb1b1" + "d43e6505621b9a7f0422ae3fc8979ee0416f95e70300000057d6249b652ba98c7dc7f17f666969e4" + "023baf7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695111d891d03000000" + "cd897619f51f44e644d7cf1d06b2b1150082549e62c12fba5b1cdec48d10bbb13b8313d8cd2a24d3" + "4fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5d8a4c5cf3351ee1c03c2056c00000051" + "bbce426cfa4b861cc78592be7b14e7ba9c15acb881ae55f0e5fe7d360300000066a3ae3939762df3" + "3a2d55060c78d55100b110fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b" + "86ed271803000000a5edc511c1507a141e0f515638c7ba31027609450000003357ae79989870ccec" + "3def0ad92749e016663fe6ee0228c1da82d1595603000000348352d715cf9d411ea012e5307294b6" + "0146dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26bb20413203000000" + "862573c2303dd1d65c7b2cffeca6d1adaccae11f0000000f855ebf3b772eb2b1c896c9a7304f6645" + "0a5f6abd850b06e3b10123e6030000001dff045298cfee0636674cdefb57b9ae54cfe8f400000038" + "1ba2c4396de60f032bc7f34de2959871c0d4c0d4eb720c4ab550c5db03000000f32f4af595d785d5" + "c1b5aad487c192f08bd7a09b00000043288cd9bf66ec305a225a0c71b2ce78bb16104c8eaf18c565" + "b16c7376030000005219061ab4c5c79489b2cc6a883c146972decb8b000000f5e6d66df46ea13910" + "7754dee62c36d2fc70ccc567df7a49b8585287dc03000000cfb18b2b2cb749e2e03e544d0eb4f73e" + "75039fcf251b32fc79685b05ddd3aa9ba511d2e40edb4d758fb554158ae5c7c0beb42b3403000000" + "895d5f24037d233302ad3b82d639272e0246eadfbd2146bf8cfdb205f90e54b58a6ee136a779f37c" + "30d2c5053c40ecaec38b6b8e03000000bea73223e59bf0193432e9fa7a899f2d8ec7e4b89bf5a5d0" + "6776e66a9d80ab132e1ac921eb76adbb229df32e561fa80a0fc4676703000000a23eb66e720da9e0" + "7ac998b5690807d50217369ee1af4ca5a6a95581af5fd7ceacdca10f47d7b351a36b178aabc78a4a" + "1a0dd8c003000000e2815a1a37a52bddd1c2f1018b587eed03bb58f0e9201f17bd99fcf72909ac9e" + "7a55299e9bb4fd53bc7417940fcffe3f81cafd6302000000d6732578acd14320aefd4503189f7630" + "038e501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eb62f22ca02000000" + "891715df7fc6a902edae579e2e10c7f7022ba0340436242cbeb0248cee3fbc160032d4f28aa28c08" + "f80dd50c6712dfb4abba4a32020000008ffe423d01883918039249f398f9b37ea091465100000064" + "3722d9b707c0d8a400b7c8307f06b4b29088f20d9ac676d5e4bafc4e02000000fde69eec3af2e6d0" + "bd68ab722af14548b29572e504265f6c72923e22594f3f790008ed2e2ebb0771db46a54cadb245ea" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd6011fa56dfdcfc1155f236c8b9c79a620" + "00660bbf024b03ff0a8e27c405e64244e36f90d402000000fd41fe47684b370b6ec6584d64496089" + "570968ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a119c64ed0402000000" + "a660ac824b7fae389861419c50da49bf02092583000000259f9f0251becc987907879cca68fec7bb" + "bb5f8edf248b4995d184e82002000000a19cdf6dd1c173f6078a806d329c9b0000bfc972000000f5" + "b2cd3dbddc74e26de958e48d2ab8b0313e7f8933e315130f641e447502000000b9b68c08a5e4351e" + "a349e1ccf662e058b879a45100000045fcb6a035339d504c9726d80d9c2d89df765b4d9a130257dc" + "d1e1b34902000000bcd7be07d78e6222e45aaf61814f703b40125e6b000000cbaaa37b861e6d46da" + "fe7d6ec4ac1ea051010911915ddb05f2c43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0" + "032d2ec50000000103781b0f294a2b7300421398f4de67e9cee64b38b56e03e01539ce4101000000" + "18238487a417f3da01d99dae5f19009601582cab0000005b2363d13edc5aa115005eb914d8fbe9a4" + "fdb3d117d76b0de5bd82e9ea010000003d1b91caae8cb60b49ba9be338d856a40267c3d400000064" + "9da90bd2fff2f2560046870bd7d5f14870c6d18d6242b356b9ef1b2101000000f90adac616a31dc2" + "e46a234558817151008fc9c900000073e64b0bd761fdf274005dca8ce1bd1871ae17bb4515856092" + "b4d9e89b010000006855676c277cf1bd017c9148da5892bb0351c3a70000009f3391ce7d3fd48469" + "005f0c233dbdd2a97835df1f1782dee86c1de913010000003ee1d76fc1ea76e98c9dfc78997ab53e" + "00c21963f5b4cb2454830c68e44ea74b002b83f9b3bee14d861a4c9eeecc89f65408c1b701000000" + "d9e1825fa638e1af284a024b7f9e85ff00e050a2000000276e08cb887464b93400c3127c750fabdd" + "69121aec129cdc690d58fbcc01000000d0d44ff1e51c35157666c05348e6f50700a8e89800000012" + "b900b2061d0c334b009f2dd1cdf64b0f9a60e0e289f08db3fde6b0250100000039dd8f88152a5845" + "4d9ca9d20f45dfa702e78604000000fbcd7db68b9ae586da00b4070c50320427c4dd3d031e33f22c" + "210aeb09010000007000b96d06992b6a58acd3995b9663d20248f333ef467092818aa77d6732b678" + "00844ef5a943825fcd743f59bd14c89b955e1a13010000007acbce3e3bcdf3824f1b134847ff26ba" + "009a774900000017ec852d59f3d17232edd86ad6c3103a68843a9aef34983882d3d3878501000000" + "5e0dfe491d1ba96742c7b5e02b2271220188b02a06d0dc5504b0595daf37deb499996bfb667f072d" + "ec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2ccd47724a3c460ba80383f4c500000063" + "eafb1ac4c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8ca0100000027335a25a364d101" + "5ffac03089f4553902b01784000000d7b83579b8da27345a72437f9b6245de39ec9e71ee4b951507" + "f121014a01000000efc67bce716c856e3973dc42a1003be94f89d8ee0000009b5d5bbe6c10085f3d" + "6176f78a19bb8df1804c122fce5078c156e8f3fe010000000ea8042602a1f8e6f5657f3f9e3eb807" + "cbad7645000000b8df6f628a70456d79f25d5895fb57fa60d9279fb2b8fcbac65ad47b8a01000000" + "da40d88d40a6d75bc404156225b7eedefc2b44574b15e2ae496ad01bf007eacb0a28aec868282510" + "b60291ea6480e356925b568a0000000087bb24e5264fd3ebe9cf9f6df9615189018ee815000000a7" + "5c9555876b6a3f13002b6cb8360feaac1d5c302df59dd32a7a859db500000000362956cd46646a0e" + "222160e5f769bb290366ed370000005b6a813387e99bb834009da86c64fefab2548759d313a5b92d" + "8e47935e0000000034f0386a253c21d94064f6b021281e230094ae20000000d71fd050bf8d85055b" + "00e3756ccdb3455c60ca7b11c66af76e594f24a100000000e143fd52599364e13468f80fd514573f" + "b572671c0000006932d1d5f5d0ce2cf6007a70ba5193a162bc92ec1b11d9172c857ae81200000000" + "3e29535402e9b690c628d048eacce745ea213cb1000000b632ef3be6070dafa200187470e9da5570" + "9427c226d324d9a08487fd0d00000000b7a350f9fc1519defa7db4532545666937c22a3b000000dc" + "c405cbee5016c25200d8901d7a0165fe20744edb6ba04f14a4c73cf500000000a4bab14874afdf54" + "e6aae816430607ca0675e09818e9bbec5918c59068baf76a008940f6fc3bbdc7f6090f756aae660b" + "6e4c699300000000d9c1e67743efb54e54270e46042e911803894e38000000376feecb80ac245409" + "c0becc271d9c2f67179bff0644399ae7e3c9472e00000000c5cfd9f2343b21362c19a0921dce2f83" + "00defa45000000270b9977e166bee737fe73670c439a644c323b59b4cd20eb7dabea74f700000000" + "f6989d2d6a909e986ff7add5df2c93e05459507b0000000f466554d2ae4d52a8c67b2e48b47003c8" + "1785d3ffdbd9a617df6b3542000000004c5cf8107ba282f4f983821918f93e742d08f0550000006f" + "2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b5159747cf200000000ab2dadc5a39411fd" + "4ff1116d478987316a553fc2000000cfc6ebe434a7ae8ff040483e310819e3b10db116431ec6f769" + "438a72e1000000002495a609675344f7e2e3a5ebaec3c85f0a1742f70abe95c50345132a61eda239" + "d9d083c3bf085387046ef8a36f0e9e696b382ab0000000009a6ce5d906837dbca6a5ee19d6f63fe9" + "03dd01f7246f13b2050424a2b3a45ef7a029c896b4132bd895072cfeffe9d6815997069500000000" + "0d3c723b91adb0da7c4aa7e7eb5a15bc03015fb98b841fd84cc43c510385b9a4c2aac1d67a909b29" + "7c703915312e9c3cae02dfa000000000dd603bd35e7fa0f02f2f3313d8469d09a92409c0b7f0318a" + "575a4f8e061db3dd7fde25654a4059d565dbc8a91e3b4457b077ddad3108be69f9b97d05c917ad6b" + "10e693bb6e26f2ba90c8e909a9fe20e5c7a4c656482a9b0d00625009a40aeb62a42b6a62548e3c38" + "cd3c72f203000000ca82ac5180101be4f85cef468ea086ea01aafdc3a9fe1ec787bc45db7c52a52d" + "00bd39a44e8e8bc17c01ac63eca0c1cf5ff7f03a03000000c9a89192c1c8be55281a59d1fd338f35" + "0075f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d53b02239e03000000" + "24438387def0f4c6544e4b275d9b714600f810d2a9fec17647176b7c07d856e3b883efebc09dd9d6" + "1966b7ae7412041d57393c6f03000000182c0287822a272bec4501a1e27acfee018588ffa9fe6cae" + "426de59560fad65d67c624f285d7174177a47579dda0b6eaa9a84c820300000070b1646d8026e9f1" + "704f1b16286ba2da017ef082a9feed33ef60a8b540b26f66761d1f13badfad0fe8fa8f3c1aad2a82" + "fa40546c03000000df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea9fe3e7d75a2f42b50c6a363" + "40132378b95c59313bacba64dbe996206e6904f50200000047150b9b14010469823acb72bb89182f" + "00112196a9feb9153b36bc60be5b534e006527f67485ab35aca0c7ee419733853cf09e8b02000000" + "e79c10acfce165e332a62384ec04e5ba009185ada9fe0070a36dd51323b2c54200154d12f86c260a" + "9edfa7a74c1c83c1050f63f802000000443cacf59c6379a44b7892f487afa98c0221c19ca9fe942f" + "460bcea75481f25e007d0de9a7afe283bd2f22ead05ff72006c83bc0020000004bdade862c224f6f" + "36506ebd455e679c00369bb8a9fecec3f8c8fa6867a982be8a934f852cc3d4d82bc0ec7303f99f8f" + "def85b7502000000a0bef8675b29a197b7b3cceaf5f1bb120335256aa9fe6e5d58099ffc4a503a71" + "2350acbd48411f0dc15d2f0f49dad345d966279502000000e06302aba042aaa218dc091e9aa1477f" + "6fdc9830a9fec95829a8838314dff34d24c332219a1b163a732d803e0e2f4f916d06412601000000" + "98c39e7cc282208fefc57ff447036b9501adcb22a9fe793f797a3c7dadd1c86e009d0c90bc512e13" + "7dcef5e4a27985bd5cfd5ce601000000152f2b70eaef7443e0f79ab6902dde5301b3ec71a9fe9f25" + "4ac95883195580410062ed564153e17478f8c3344d89c0bbfaa100fd01000000be184524a6bdc878" + "9cf851782d895bcc03a98489a9fe8c1287e6f7bb020ffdb00012098610e52bb2a16a4008aefd545b" + "0d80684e01000000ba8110fb9733cc24904f288262e6ea77032fa5f8a9feeefa701d120523bd98f2" + "00098b43cd68be6e3f81268193fd637e9037d7a701000000c47cf0f551e96770a754ac19ef820fe0" + "0031f2d3a9fe049150b8d10ab700cc3a7cf51be0403b654ba2f56808092069af5f5b481b01000000" + "68cb3bc873b04d937a6ed8f7bc51e54066fed098a9fe048a92d3adc69a84eb47622400207799416a" + "f1f0a086fbd7e2f7dea0077a00000000c386e9c6e6a2cbfa10ee58bdc75183600085d627a9feb1cb" + "e491cbbbf9443fd6007eb3c5bf64b671d6f18dbf463f9b83f512dc1c00000000fbab244735d67c61" + "283031667b2d74a102e0b1b1a9fe2aa590a2312e17f1a35900459582f4ef43c780908872746e39ef" + "a9a89f8700000000fcdf6d9be94030b34774d1d7dddedd9802f0f627a9fe965a87041331b2834bcf" + "00b4e3ce848518c4e3f6cbf25e5e1b992231bb0200000000173c333cd03bc905b7b899afeb760e3f" + "024a2efca9fe96b89b1bc8f415bd4e77be46bae5a1b3cae76665a268abfe8a41a84e27c100000000" + "cb29efdf672d2fa57fc85ebbe276c5660364192da9fee7af5eb888e9eb37bb046686943b101e1f55" + "3215abf8fbdf17c3677e5a3a00000000608df061d45d864d09f4ecf17625f82d03c74828a9fe1e37" + "1051852c972ea7954079884af257b044fd13a6826a4c619f3d136cac000000009402a4c216772167" + "3f2b02b3256ead1f03ea9bc1a9fefca162fb81e733cff620ca7feefe1933631e8e69f6d9d6962d2c"), + [1] = ("54270e46020000006a894e387625da376feecb80ac245409c0becc271d9c2f67179bff0644399ae7" + "9c64ed0432d599eaa660ac824b7fae389861419c7a899f2d010000009bf5a5d06776e66a9d80ab13" + "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" + "c4e1966800000000b3121cd5ef51e696c816290dbaee0e7726d082e1530ff5397c9125f59577d71c" + "4b258a005116d11354edff62ceaa458fc75a91c425a5927300000000c4458d70911714f1819aa46f" + "be143934c933ae6dec0fb124f264af67eed7c9a8c38b6b8ee2614344bea73223e59bf0193432e9fa" + "4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44" + "64d210a256be75e0509c4477d19ac64b2e69220d12ea3b9501000000fb95e8332fdfff658483a2d0" + "39a7bf148ed3481e0bccc460e89f7abdb682380a62eae374835b4a49a2b980b6aba92da6409969aa" + "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359" + "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9bb0ec36f0000000064a2827b7cdd38d0314c178e" + "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" + "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226" + "d324d9a086ed27184b443181a5edc511c1507a142fea9bc10300000062fb81e733cff620ca7feefe" + "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" + "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911" + "4bdade862c224f6f36506ebd455e679cef369bb8d514573f03000000f6932f6932d1d5f5d0ce2cf6" + "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" + "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d" + "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a41e0f515601000000f57609453df7803357ae7998" + "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" + "ae8cb60b0300000038d856a40c67c3d4afa9c8649da90bd2fff2f256000000000000000000000000" + "00000001955e1a13d1111b067acbce3e3bcdf38200154d12010000009edfa7a74c1c83c18e47935e" + "8354846e34f0386a00000000000000000000000000000001ac26c7d41fd050bf8d85055bcfe3756c" + "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000" + "00000000020ffdb0e612098610e52bb2a16a40086f0e9e6903000000ec2e2924348352d715cf9d41" + "1ea012e5307294b600000000000000000000000000000000ccd2f50c30706cae3fdcc2f0ee3d5e26" + "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000" + "0000000000459582f4ef43c780908872746e39efaefd545b020000007ced4f8b362956cd46646a0e" + "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" + "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000" + "0000000069d9942f460bcea75481f25e307d0de96e91b91501000000be5b534e0a6527f67485ab35" + "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" + "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000" + "00000000b49185ad9b7d0070a36dd51323b2c542e5fe7d360100000066a3ae3939762df33a2d5506" + "0c78d551cbb110fd000000000000000000000000000000002c171ed15abbbe1cd911db7b56e8f3fe" + "9a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7246f13b2050424a2000000000000000000000000" + "00000000ffe9d6812231bb02f922259b173c333cbae87d60000000005d31e5b2de252167c1c91b3a" + "36ba0c700ee78477000000000000000000000000000000006ad0143a0554efb46b382ab0404cdf02" + "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000" + "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8" + "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" + "7666c05303000000ffa8e89871fb9510b900b2061d0c334b819f2dd1000000000000000000000000" + "00000000095a3230fde69eec3af2e6d0bd68ab7210613fc90200000016a31dc2e46a234558817151" + "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" + "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000" + "00000000b314f695bd82e9ea8891ed0a3d1b91cab56e03e0010000002f70249eefc67bce716c856e" + "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1" + "eecc89f601000000d635edea8ffe423d01883918039249f398f9b37e000000000000000000000000" + "000000001fb7c8307f06b4b29088f20d9ac676d5f90e54b501000000a779f37c30d2c5053c40ecae" + "210aeb0934cb2a2400000000000000000000000000000000df48f333ef467092818aa77d6732b678" + "bcd7be0700000000e45aaf61814f703b40125e6baf4648cbaaa37b86000000000000000000000000" + "000000005ddb05f2a84e27c18a06e2c9cb29efdf50da49bf00000000d94beb259f9f0251becc9879" + "07879cca68fec7bb000000000000000000000000000000009402a4c2167721673f2b02b3256ead1f" + "a349e1cc00000000b879a45176740744fcb6a035339d504c9726d80d000000000000000000000000" + "000000009518862bc9a89192c1c8be55281a59d1ebfdcec30000000067a982be8a934f852cc3d4d8" + "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" + "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000" + "00000002e6fbf952902383028e3b47f2111d891d536c75bb01000000720da9e07ac998b5690807d5" + "2617369ee1af4ca500000000000000000000ffff47d7b351a36b178aabc78a4a0d80684ee5dbf45b" + "17a4763102000000f9119c40b468b66331bca67a034f43340d01683c00000000000000000000ffff" + "b24a5be9b10123e6e4f15ecd1dff045298cfee069c88b02a0300000004b0595daf37deb499996bfb" + "667f072dec1e5d9cdc8a11f4409bcfb3c167090e99d90a8543961b2ccd47724a3c460ba85183f4c5" + "a7afe28302000000d05ff720b16c73761a3fcb675219061ab4c5c79489b2cc6a883c146972decb8b" + "5adac8f5e6d66df46ea139107754dee62c36d2fcc7a4c65601000000cd625009a40aeb62a42b6a62" + "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" + "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599" + "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b21cdb3455c00000000c66af76e80f062ea1a7e0b7b" + "e218d067530e1b0487b8c3b99f2b8a1a8982c42f53700a3437c5156e072b2f2fb337c9cfe07c34dd" + "c896c9a7000000000a5f6abd850b06e3d9662795ce2cc1cee06302aba042aaa218dc091e9aa1477f" + "6fdc9830d7fbc95829a8838314dff34d24c332214d4647f5000000000f88e3759a08e7a56663861e" + "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" + "7625ca4a00000000e682f80f94315c45ef817264c89a736ed55ed637b077ddad3108be69f9b97d05" + "c917ad6b10e693bb6e26f2ba90c8e909e85e20e5b0916e5d030000004a503a712350acbd48411f0d" + "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" + "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e" + "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c" + "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620" + "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2" + "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" + "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9" + "4d88189c471a1ff2f0ce3ff66e782110125ae2eddaae7d6300000000c0982b283aa9986700b2a2b3" + "ed257b8b0489f48f053ec8cac72105b327335a25a364d1015ffac03089f45539e1b0178462156cd6" + "6855676c00000000017c9148da5892bb4951c3a7ed55689d3391ce7d3fd48469845f0c233dbdd2a9" + "7835df1f1782dee88487fd0db5971b46b7a350f998c39e7c00000000efc57ff447036b9551adcb22" + "fd50793f797a3c7dadd1c86e759d0c90bc512e137dcef5e4a27985bd8d1e69c83dc21056b973972c" + "bc51e540030000006c3d048a92d3adc69a84eb47622400207799416afef0a086fbd7e2f7dea0077a" + "e9c0c0d9c386e9c6e6a2cbfa10ee58bdc75183600422ae3f03000000c43bd794c697895e5bfe47c6" + "f53a54e01b0c1d89fecd94d0e02d2ec587fc330003781b0f294a2b73c4421398f4de67e9cee64b38" + "69121aec010000000fcc00ac2daa755e5292cd32dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51" + "bbce426cfa4b861cc78592be7b14e7ba9c15acb836674cde0200000054cfe8f42bf0e9381ba2c439" + "6de60f032bc7f34dfe959871c0d4c0d4eb720c4ae3c9472e5f2da5d9c5cfd9f2343b21362c19a092" + "b2cd3dbd01000000e958e48d2ab8b0313e7f8933e315130fa9a84c82feb83f6e70b1646d8026e9f1" + "704f1b16286ba2dabc7ef0820c91ed33ef60a8b5bcfe97e1000000007ad742d3d7320a4f880cf47f" + "5dd0cf69cb22840ffeb3fe7749509cb6752b2cee30b7e7736a0afc9879ea40e69710fc9f6e8e99cd" + "1dce2f83020000003a3efc240b9977e166bee737fe73670c439a644c000000000000000000000000" + "000000015e0dfe491d1ba96742c7b5e02b227122cf844ef501000000cd743f59bd14c89b5cfd5ce6" + "e82e7854152f2b700000000000000000000000000000000127e19f254ac9588319558041fc62ed56" + "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000" + "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f" + "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" + "0436242c03000000ee3fbc164632d4f28aa28c08f80dd50c6712dfb4000000000000000000000000" + "00000000078a806d329c9b008bbfc9723107f3f52af145480300000004265f6c72923e22594f3f79" + "e208ed2e2ebb07710000000000000000000000000000000039dd8f88152a58454d9ca9d20f45dfa7" + "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000" + "000000008ae21e371051852c972ea7954079884a9a1b163a030000000e2f4f911a0dd8c052ed6b13" + "e2815a1a37a52bdd00000000000000000000000000000000bd99fcf72909ac9e7a55299e9bb4fd53" + "9f3c2c8803000000f51f44e644d7cf1d06b2b115d882549e62c12fba000000000000000000000000" + "000000004fc812bd2f8a59d96d064126666befbbf257b044030000006a4c619f9037d7a754655354" + "c47cf0f551e967700000000000000000000000000000000050b8d10ab700cc3a7cf51be0403b654b" + "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000" + "00000000d538d34574c038404923e75d0e09e2fcfc1519de010000002545666937c22a3b6e9686dc" + "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" + "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000" + "00000000b883efebc09dd9d61966b7ae7412041dd7ac5f9901000000822a272bec4501a1e27acfee" + "7a8588ffd5a06cae0000000000000000000000000000000077a47579dda0b6ead1e1b34901eaedd5" + "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000" + "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096" + "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" + "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000" + "000000005b29a197b7b3cceaf5f1bb12c535256a74993ade03000000e62112898dab2dade2ab2fc9" + "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" + "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000" + "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050" + "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f" + "bc74179403000000438a72e12ae0436a2495a609675344f7e2e3a5eb000000000000000000000000" + "0000000061eda239d9d083c3bf085387046ef8a34153e174020000004d89c0bb5408c1b7d17fb084" + "d9e1825fa638e1af000000000000000000000000000000006e08cb887464b9344ec3127c750fabdd" + "6c0fc09c02000000809829af4a9df58dbfef186d416f3a1ef170d10f000000000000000000000000" + "0000000087780281d47a32f2235376239daeaacba9a89f8701000000fcdf6d9be94030b34774d1d7" + "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" + "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000" + "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc" + "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" + "b7f0318a01000000061db3dd7fde25654a4059d565dbc8a91e3b4457000000000000000000000000" + "00000000c1b5aad487c192f08bd7a09bdd21444359747cf200000000ab2dadc5a39411fd4ff1116d" + "478987316a553fc2000000000000000000000000000000000819e3b10db116431ec6f7691539ce41" + "b95c593100000000dbe9962069e66142e22753344fda8a3e0b841cf7000000000000000000000000" + "000000008c54dda9ac3bb1b1d43e6505621b9a7f672d2fa501000000e276c5661a64192db44ce7af" + "5eb888e9eb37bb0400000000000000000000000000000002641e447514ca565fb9b68c08a5e4351e" + "9f3c39f201000000de745cb25851429b3bbfb50168dfd04edf6b3542000000000000000000000000" + "0000000218f93e742d08f0550b55726f2292362e70ccc56700000000a4c73cf5ffa4ffc8a4bab148" + "74afdf54e6aae8160000000000000000000000000000000268baf76ab08940f6fc3bbdc7f6090f75" + "4f1b134803000000449a774929e86716ec852d59f3d17232edd86ad6000000000000000000000000" + "000000027dba1ee7e143fd52599364e13468f80f40b26f6603000000badfad0fe8fa8f3c1aad2a82" + "530b7447d9c2f401000000000000000000000000000000028147507e1cd59ea1ae6da48b1eba6d16" + "dedea2030100000002a1f8e6f5657f3f9e3eb807cbad76451055edb8000000000000000000000000" + "00000002d9279fb2b8fcbac6abea74f7a6df7979f6989d2d000000006ff7add5df2c93e05459507b" + "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"), + [2] = ("4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44" + "64d210a256be75e0509c4477d19ac64b2e69220d54270e46020000006a894e387625da376feecb80" + "ac245409c0becc271d9c2f67179bff0644399ae79c64ed0432d599eaa660ac824b7fae389861419c" + "12ea3b9501000000fb95e8332fdfff658483a2d039a7bf148ed3481e0bccc460e89f7abdb682380a" + "62eae374835b4a49a2b980b6aba92da6409969aa7a899f2d010000009bf5a5d06776e66a9d80ab13" + "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b" + "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359" + "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9c4e1966800000000b3121cd5ef51e696c816290d" + "baee0e7726d082e1530ff5397c9125f59577d71c4b258a005116d11354edff62ceaa458fc75a91c4" + "25a5927300000000c4458d70911714f1819aa46fbe143934c933ae6dec0fb124f264af67eed7c9a8" + "c38b6b8ee2614344bea73223e59bf0193432e9fa2fea9bc10300000062fb81e733cff620ca7feefe" + "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196" + "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911" + "4bdade862c224f6f36506ebd455e679cef369bb8bb0ec36f0000000064a2827b7cdd38d0314c178e" + "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13" + "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226" + "d324d9a086ed27184b443181a5edc511c1507a14d514573f03000000f6932f6932d1d5f5d0ce2cf6" + "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd" + "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d" + "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a4ae8cb60b0300000038d856a40c67c3d4afa9c864" + "9da90bd2fff2f25600000000000000000000000000000001955e1a13d1111b067acbce3e3bcdf382" + "00154d12010000009edfa7a74c1c83c18e47935e8354846e34f0386a000000000000000000000000" + "00000001ac26c7d41fd050bf8d85055bcfe3756c1e0f515601000000f57609453df7803357ae7998" + "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7" + "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000" + "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8" + "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec" + "6f0e9e6903000000ec2e2924348352d715cf9d411ea012e5307294b6000000000000000000000000" + "00000000ccd2f50c30706cae3fdcc2f0ee3d5e267666c05303000000ffa8e89871fb9510b900b206" + "1d0c334b819f2dd100000000000000000000000000000000095a3230fde69eec3af2e6d0bd68ab72" + "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000" + "0000000000459582f4ef43c780908872746e39ef10613fc90200000016a31dc2e46a234558817151" + "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2" + "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000" + "00000000b314f695bd82e9ea8891ed0a3d1b91ca6e91b91501000000be5b534e0a6527f67485ab35" + "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b" + "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000" + "00000000b49185ad9b7d0070a36dd51323b2c542b56e03e0010000002f70249eefc67bce716c856e" + "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1" + "e5fe7d360100000066a3ae3939762df33a2d55060c78d551cbb110fd000000000000000000000000" + "000000002c171ed15abbbe1cd911db7b56e8f3feeecc89f601000000d635edea8ffe423d01883918" + "039249f398f9b37e000000000000000000000000000000001fb7c8307f06b4b29088f20d9ac676d5" + "f90e54b501000000a779f37c30d2c5053c40ecae210aeb0934cb2a24000000000000000000000000" + "00000000df48f333ef467092818aa77d6732b678bcd7be0700000000e45aaf61814f703b40125e6b" + "af4648cbaaa37b86000000000000000000000000000000005ddb05f2a84e27c18a06e2c9cb29efdf" + "50da49bf00000000d94beb259f9f0251becc987907879cca68fec7bb000000000000000000000000" + "000000009402a4c2167721673f2b02b3256ead1fa349e1cc00000000b879a45176740744fcb6a035" + "339d504c9726d80d000000000000000000000000000000009518862bc9a89192c1c8be55281a59d1" + "bae87d60000000005d31e5b2de252167c1c91b3a36ba0c700ee78477000000000000000000000000" + "000000006ad0143a0554efb46b382ab0404cdf02ebfdcec30000000067a982be8a934f852cc3d4d8" + "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a" + "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000" + "00000000020ffdb0e612098610e52bb2a16a4008aefd545b020000007ced4f8b362956cd46646a0e" + "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d" + "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000" + "0000000069d9942f460bcea75481f25e307d0de99a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7" + "246f13b2050424a200000000000000000000000000000000ffe9d6812231bb02f922259b173c333c" + "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000" + "00000002e6fbf952902383028e3b47f2111d891d17a4763102000000f9119c40b468b66331bca67a" + "034f43340d01683c00000000000000000000ffffb24a5be9b10123e6e4f15ecd1dff045298cfee06" + "536c75bb01000000720da9e07ac998b5690807d52617369ee1af4ca500000000000000000000ffff" + "47d7b351a36b178aabc78a4a0d80684ee5dbf45bb0916e5d030000004a503a712350acbd48411f0d" + "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8" + "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e" + "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c" + "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378" + "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620" + "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2" + "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034" + "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9" + "4d88189c471a1ff2f0ce3ff66e782110125ae2edc7a4c65601000000cd625009a40aeb62a42b6a62" + "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb" + "daae7d6300000000c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8cac72105b327335a25" + "a364d1015ffac03089f45539e1b0178462156cd66855676c00000000017c9148da5892bb4951c3a7" + "ed55689d3391ce7d3fd48469845f0c233dbdd2a97835df1f1782dee88487fd0db5971b46b7a350f9" + "cdb3455c00000000c66af76e80f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a8982c42f" + "53700a3437c5156e072b2f2fb337c9cfe07c34ddc896c9a7000000000a5f6abd850b06e3d9662795" + "ce2cc1cee06302aba042aaa218dc091e9aa1477f6fdc9830d7fbc95829a8838314dff34d24c33221" + "98c39e7c00000000efc57ff447036b9551adcb22fd50793f797a3c7dadd1c86e759d0c90bc512e13" + "7dcef5e4a27985bd8d1e69c83dc21056b973972c7625ca4a00000000e682f80f94315c45ef817264" + "c89a736ed55ed637b077ddad3108be69f9b97d05c917ad6b10e693bb6e26f2ba90c8e909e85e20e5" + "9c88b02a0300000004b0595daf37deb499996bfb667f072dec1e5d9cdc8a11f4409bcfb3c167090e" + "99d90a8543961b2ccd47724a3c460ba85183f4c5a7afe28302000000d05ff720b16c73761a3fcb67" + "5219061ab4c5c79489b2cc6a883c146972decb8b5adac8f5e6d66df46ea139107754dee62c36d2fc" + "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599" + "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b214d4647f5000000000f88e3759a08e7a56663861e" + "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db" + "0422ae3f03000000c43bd794c697895e5bfe47c6f53a54e01b0c1d89fecd94d0e02d2ec587fc3300" + "03781b0f294a2b73c4421398f4de67e9cee64b38bc51e540030000006c3d048a92d3adc69a84eb47" + "622400207799416afef0a086fbd7e2f7dea0077ae9c0c0d9c386e9c6e6a2cbfa10ee58bdc7518360" + "36674cde0200000054cfe8f42bf0e9381ba2c4396de60f032bc7f34dfe959871c0d4c0d4eb720c4a" + "e3c9472e5f2da5d9c5cfd9f2343b21362c19a092b2cd3dbd01000000e958e48d2ab8b0313e7f8933" + "e315130fa9a84c82feb83f6e70b1646d8026e9f1704f1b16286ba2dabc7ef0820c91ed33ef60a8b5" + "bcfe97e1000000007ad742d3d7320a4f880cf47f5dd0cf69cb22840ffeb3fe7749509cb6752b2cee" + "30b7e7736a0afc9879ea40e69710fc9f6e8e99cd69121aec010000000fcc00ac2daa755e5292cd32" + "dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51bbce426cfa4b861cc78592be7b14e7ba9c15acb8" + "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000" + "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f" + "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e" + "cf844ef501000000cd743f59bd14c89b5cfd5ce6e82e7854152f2b70000000000000000000000000" + "0000000127e19f254ac9588319558041fc62ed561dce2f83020000003a3efc240b9977e166bee737" + "fe73670c439a644c000000000000000000000000000000015e0dfe491d1ba96742c7b5e02b227122" + "2af145480300000004265f6c72923e22594f3f79e208ed2e2ebb0771000000000000000000000000" + "0000000039dd8f88152a58454d9ca9d20f45dfa774993ade03000000e62112898dab2dade2ab2fc9" + "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8" + "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000" + "000000008ae21e371051852c972ea7954079884a9f3c2c8803000000f51f44e644d7cf1d06b2b115" + "d882549e62c12fba000000000000000000000000000000004fc812bd2f8a59d96d064126666befbb" + "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000" + "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050" + "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f" + "f257b044030000006a4c619f9037d7a754655354c47cf0f551e96770000000000000000000000000" + "0000000050b8d10ab700cc3a7cf51be0403b654bbc74179403000000438a72e12ae0436a2495a609" + "675344f7e2e3a5eb0000000000000000000000000000000061eda239d9d083c3bf085387046ef8a3" + "4153e174020000004d89c0bb5408c1b7d17fb084d9e1825fa638e1af000000000000000000000000" + "000000006e08cb887464b9344ec3127c750fabdd6c0fc09c02000000809829af4a9df58dbfef186d" + "416f3a1ef170d10f0000000000000000000000000000000087780281d47a32f2235376239daeaacb" + "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000" + "00000000d538d34574c038404923e75d0e09e2fca9a89f8701000000fcdf6d9be94030b34774d1d7" + "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767" + "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000" + "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc" + "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515" + "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000" + "00000000b883efebc09dd9d61966b7ae7412041db7f0318a01000000061db3dd7fde25654a4059d5" + "65dbc8a91e3b445700000000000000000000000000000000c1b5aad487c192f08bd7a09bdd214443" + "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000" + "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096" + "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f" + "59747cf200000000ab2dadc5a39411fd4ff1116d478987316a553fc2000000000000000000000000" + "000000000819e3b10db116431ec6f7691539ce41b95c593100000000dbe9962069e66142e2275334" + "4fda8a3e0b841cf7000000000000000000000000000000008c54dda9ac3bb1b1d43e6505621b9a7f" + "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000" + "000000005b29a197b7b3cceaf5f1bb12c535256a0436242c03000000ee3fbc164632d4f28aa28c08" + "f80dd50c6712dfb400000000000000000000000000000000078a806d329c9b008bbfc9723107f3f5" + "9a1b163a030000000e2f4f911a0dd8c052ed6b13e2815a1a37a52bdd000000000000000000000000" + "00000000bd99fcf72909ac9e7a55299e9bb4fd53fc1519de010000002545666937c22a3b6e9686dc" + "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e" + "d7ac5f9901000000822a272bec4501a1e27acfee7a8588ffd5a06cae000000000000000000000000" + "0000000077a47579dda0b6ead1e1b34901eaedd54f1b134803000000449a774929e86716ec852d59" + "f3d17232edd86ad6000000000000000000000000000000027dba1ee7e143fd52599364e13468f80f" + "40b26f6603000000badfad0fe8fa8f3c1aad2a82530b7447d9c2f401000000000000000000000000" + "000000028147507e1cd59ea1ae6da48b1eba6d16dedea2030100000002a1f8e6f5657f3f9e3eb807" + "cbad76451055edb800000000000000000000000000000002d9279fb2b8fcbac6abea74f7a6df7979" + "672d2fa501000000e276c5661a64192db44ce7af5eb888e9eb37bb04000000000000000000000000" + "00000002641e447514ca565fb9b68c08a5e4351e9f3c39f201000000de745cb25851429b3bbfb501" + "68dfd04edf6b35420000000000000000000000000000000218f93e742d08f0550b55726f2292362e" + "70ccc56700000000a4c73cf5ffa4ffc8a4bab14874afdf54e6aae816000000000000000000000000" + "0000000268baf76ab08940f6fc3bbdc7f6090f75f6989d2d000000006ff7add5df2c93e05459507b" + "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"), + }; + const int TEST_DATA_I = GPOINTER_TO_INT(test_data); + const int addr_family = (TEST_DATA_I == 0 ? AF_INET : AF_INET6); + const int IPV6_PREFER_TEMP = (TEST_DATA_I == 2); + const guint N_ADDRESSES = 100; + const gsize ELM_SIZE = + addr_family == AF_INET ? sizeof(NMPlatformIP4Address) : sizeof(NMPlatformIP6Address); + const gboolean DO_REGENERATE = FALSE; + const gboolean PRINT_RESULT = DO_REGENERATE; + const gboolean CHECK_RESULT = !DO_REGENERATE; + gs_free guint8 *addresses = NULL; + gs_free guint64 *rand_map = NULL; + gsize i, j; + + /* + * First we create a list of addresses filled with (stable) random bytes. + * We tweak some fields explicitly (stable randomly), so that we cover all + * relevant cases. + * + * Then we sort the list of addresses, and compare that the result is + * as our EXPECTED_BUFFER. + */ + + addresses = g_malloc(ELM_SIZE * N_ADDRESSES); + rand_map = g_malloc(sizeof(rand_map[0]) * N_ADDRESSES); + nmtst_stable_rand(258829693, addresses, ELM_SIZE * N_ADDRESSES); + nmtst_stable_rand(710086081, rand_map, sizeof(rand_map[0]) * N_ADDRESSES); + + for (i = 0; i < N_ADDRESSES; i++) { + NMPlatformIPXAddress *a = (gpointer)(&addresses[i * ELM_SIZE]); + guint64 r = rand_map[i]; + struct in6_addr * a6; + +#define CONSUME_BITS(r, nbits) \ + ({ \ + guint64 _r = (r); \ + const int _nbits = (nbits); \ + \ + r >>= (_nbits); \ + (_r & (((((guint64) 1u) << (_nbits)) - 1u))); \ + }) + + if (addr_family == AF_INET) { + if (CONSUME_BITS(r, 1)) { + /* randomly create a link-local address or not. */ + g_assert((NM_IPV4LL_NETWORK & ~NM_IPV4LL_NETMASK) == 0); + a->a4.address = (a->a4.address & ~NM_IPV4LL_NETMASK) | NM_IPV4LL_NETWORK; + } + } else { + a6 = &a->a6.address; + switch (CONSUME_BITS(r, 4)) { + case 0: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = htonl(0xffff); + g_assert(IN6_IS_ADDR_V4MAPPED(a6)); + break; + case 1: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = 0; + a6->s6_addr32[3] = htonl(2); + g_assert(IN6_IS_ADDR_V4COMPAT(a6)); + break; + case 2: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = 0; + a6->s6_addr32[3] = 0; + g_assert(IN6_IS_ADDR_UNSPECIFIED(a6)); + break; + case 3: + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = 0; + a6->s6_addr32[3] = htonl(1); + g_assert(IN6_IS_ADDR_LOOPBACK(a6)); + break; + case 4: + a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl(0xffc00000)) | htonl(0xfe800000); + g_assert(IN6_IS_ADDR_LINKLOCAL(a6)); + break; + case 6: + a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl(0xffc00000)) | htonl(0xfec00000); + g_assert(IN6_IS_ADDR_SITELOCAL(a6)); + break; + case 7: + case 8: + case 9: + case 10: + break; + default: + memset(a6, 0, sizeof(*a6)); + break; + } + } + + if (CONSUME_BITS(r, 5) != 0) { + /* randomly make addr-source the same (so that several addresses compare + * equal). */ + a->a4.addr_source = CONSUME_BITS(r, 2); + } + + if (addr_family == AF_INET) { + if (CONSUME_BITS(r, 1)) { + /* randomly make the label empty or not. */ + a->a4.label[0] = '\0'; + } + } + if (addr_family == AF_INET) { + if (CONSUME_BITS(r, 2) != 0) { + /* randomly make the label empty or not. */ + a->a4.plen = CONSUME_BITS(r, 2); + } + } + if (addr_family == AF_INET) { + if (CONSUME_BITS(r, 1)) { + a->a4.address = (a->a4.address & ~0xFFFFFFu) | (CONSUME_BITS(r, 2) << 24); + } + } + } + + g_qsort_with_data(addresses, + N_ADDRESSES, + ELM_SIZE, + _address_pretty_sort_cmp, + (gpointer) test_data); + + for (i = 0; i < N_ADDRESSES; i++) { + const NMPlatformIPXAddress *a = (gconstpointer)(&addresses[i * ELM_SIZE]); + + for (j = i + 1; j < N_ADDRESSES; j++) { + const NMPlatformIPXAddress *b = (gconstpointer)(&addresses[j * ELM_SIZE]); + int c1; + int c2; + + if (addr_family == AF_INET) { + c1 = nm_platform_ip4_address_pretty_sort_cmp(&a->a4, &b->a4); + c2 = nm_platform_ip4_address_pretty_sort_cmp(&b->a4, &a->a4); + } else { + c1 = nm_platform_ip6_address_pretty_sort_cmp(&a->a6, &b->a6, IPV6_PREFER_TEMP); + c2 = nm_platform_ip6_address_pretty_sort_cmp(&b->a6, &a->a6, IPV6_PREFER_TEMP); + } + + g_assert_cmpint(c1, >=, -1); + g_assert_cmpint(c1, <=, 1); + g_assert_cmpint(c1, ==, -c2); + } + } + + if (PRINT_RESULT) { + g_print("\n\n\t\t[%d] = (\n", TEST_DATA_I); + for (i = 0; i < ELM_SIZE * N_ADDRESSES;) { + g_print("\t\t\t\""); + for (j = 0; j < 40 && i < ELM_SIZE * N_ADDRESSES; j++, i++) + g_print("%02x", addresses[i]); + g_print("\"\n"); + } + g_print("\t\t),\n\n"); + return; + } + + if (CHECK_RESULT) { + gs_free guint8 *bin_arr = NULL; + gsize bin_len; + + bin_arr = nm_utils_hexstr2bin_alloc(EXPECTED_BUFFER[TEST_DATA_I], + FALSE, + FALSE, + NULL, + 0, + &bin_len); + g_assert_cmpmem(addresses, ELM_SIZE * N_ADDRESSES, bin_arr, bin_len); + } } /*****************************************************************************/ -NMTST_DEFINE (); +NMTST_DEFINE(); int -main (int argc, char **argv) +main(int argc, char **argv) { - nmtst_init_assert_logging (&argc, &argv, "WARN", "DEFAULT"); + nmtst_init_assert_logging(&argc, &argv, "WARN", "DEFAULT"); - g_test_add_func ("/general/init_linux_platform", test_init_linux_platform); - g_test_add_func ("/general/link_get_all", test_link_get_all); - g_test_add_func ("/general/nm_platform_link_flags2str", test_nm_platform_link_flags2str); + g_test_add_func("/general/init_linux_platform", test_init_linux_platform); + g_test_add_func("/general/link_get_all", test_link_get_all); + g_test_add_func("/general/nm_platform_link_flags2str", test_nm_platform_link_flags2str); + g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/4", + GINT_TO_POINTER(0), + test_platform_ip_address_pretty_sort_cmp); + g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/6/1", + GINT_TO_POINTER(1), + test_platform_ip_address_pretty_sort_cmp); + g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/6/2", + GINT_TO_POINTER(2), + test_platform_ip_address_pretty_sort_cmp); - return g_test_run (); + return g_test_run(); } diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 42b5baf0..1305e586 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 - 2017 Red Hat, Inc. */ @@ -18,1710 +18,1870 @@ #define EX NMTSTP_ENV1_EX static void -_wait_for_ipv4_addr_device_route (NMPlatform *platform, - gint64 timeout_msec, - int ifindex, - in_addr_t addr, - guint8 plen) +_wait_for_ipv4_addr_device_route(NMPlatform *platform, + gint64 timeout_msec, + int ifindex, + in_addr_t addr, + guint8 plen) { - /* Wait that the addresses gets a device-route. After adding a address, - * the device route is not added immediately. It takes a moment... */ - - addr = nm_utils_ip4_address_clear_host_address (addr, plen); - NMTST_WAIT_ASSERT (400, { - NMDedupMultiIter iter; - NMPLookup lookup; - const NMPObject *o; - - nmp_cache_iter_for_each (&iter, - nm_platform_lookup (platform, - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_IP4_ROUTE, - ifindex)), - &o) { - const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o); - - if ( r->plen == plen - && addr == nm_utils_ip4_address_clear_host_address (r->network, plen) - && r->metric == 0 - && r->scope_inv == nm_platform_route_scope_inv (RT_SCOPE_LINK) - && r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) - return; - } - nmtstp_assert_wait_for_signal (platform, - (nmtst_wait_end_us - g_get_monotonic_time ()) / 1000); - }); + /* Wait that the addresses gets a device-route. After adding a address, + * the device route is not added immediately. It takes a moment... */ + + addr = nm_utils_ip4_address_clear_host_address(addr, plen); + NMTST_WAIT_ASSERT(400, { + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPObject *o; + + nmp_cache_iter_for_each ( + &iter, + nm_platform_lookup(platform, + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex)), + &o) { + const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE(o); + + if (r->plen == plen && addr == nm_utils_ip4_address_clear_host_address(r->network, plen) + && r->metric == 0 && r->scope_inv == nm_platform_route_scope_inv(RT_SCOPE_LINK) + && r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) + return; + } + nmtstp_assert_wait_for_signal(platform, + (nmtst_wait_end_us - g_get_monotonic_time()) / 1000); + }); } static void -_wait_for_ipv6_addr_non_tentative (NMPlatform *platform, - gint64 timeout_msec, - int ifindex, - guint addr_n, - const struct in6_addr *addrs) +_wait_for_ipv6_addr_non_tentative(NMPlatform * platform, + gint64 timeout_msec, + int ifindex, + guint addr_n, + const struct in6_addr *addrs) { - guint i; - - /* Wait that the addresses become non-tentative. Dummy interfaces are NOARP - * and thus don't do DAD, but the kernel sets the address as tentative for a - * small amount of time, which prevents the immediate addition of the route - * with RTA_PREFSRC */ - - NMTST_WAIT_ASSERT (timeout_msec, { - gboolean should_wait = FALSE; - const NMPlatformIP6Address *plt_addr; - - for (i = 0; i < addr_n; i++) { - plt_addr = nm_platform_ip6_address_get (platform, ifindex, addrs[i]); - if ( !plt_addr - || NM_FLAGS_HAS (plt_addr->n_ifa_flags, IFA_F_TENTATIVE)) { - should_wait = TRUE; - break; - } - } - if (!should_wait) - return; - nmtstp_assert_wait_for_signal (platform, - (nmtst_wait_end_us - g_get_monotonic_time ()) / 1000); - }); + guint i; + + /* Wait that the addresses become non-tentative. Dummy interfaces are NOARP + * and thus don't do DAD, but the kernel sets the address as tentative for a + * small amount of time, which prevents the immediate addition of the route + * with RTA_PREFSRC */ + + NMTST_WAIT_ASSERT(timeout_msec, { + gboolean should_wait = FALSE; + const NMPlatformIP6Address *plt_addr; + + for (i = 0; i < addr_n; i++) { + plt_addr = nm_platform_ip6_address_get(platform, ifindex, &addrs[i]); + if (!plt_addr || NM_FLAGS_HAS(plt_addr->n_ifa_flags, IFA_F_TENTATIVE)) { + should_wait = TRUE; + break; + } + } + if (!should_wait) + return; + nmtstp_assert_wait_for_signal(platform, + (nmtst_wait_end_us - g_get_monotonic_time()) / 1000); + }); } static void -ip4_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMPlatformIP4Route *received, int change_type_i, SignalData *data) +ip4_route_callback(NMPlatform * platform, + int obj_type_i, + int ifindex, + const NMPlatformIP4Route *received, + int change_type_i, + SignalData * data) { - const NMPObjectType obj_type = obj_type_i; - const NMPlatformSignalChangeType change_type = change_type_i; - NMPObject o_id; - nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL); - - g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_IP4_ROUTE); - g_assert (received); - g_assert_cmpint (received->ifindex, ==, ifindex); - g_assert (data && data->name); - g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED); - - /* run code for initializing the ID only */ - nmp_object_stackinit_id (&o_id, NMP_OBJECT_UP_CAST (received)); - nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), TRUE); - nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), FALSE); - - if (data->ifindex && data->ifindex != received->ifindex) - return; - if (data->change_type != change_type) - return; - - if (data->loop) - g_main_loop_quit (data->loop); - - data->received_count++; - _LOGD ("Received signal '%s' %dth time.", data->name, data->received_count); + const NMPObjectType obj_type = obj_type_i; + const NMPlatformSignalChangeType change_type = change_type_i; + NMPObject o_id; + nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new(NMP_OBJECT_TYPE_IP4_ROUTE, NULL); + + g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_IP4_ROUTE); + g_assert(received); + g_assert_cmpint(received->ifindex, ==, ifindex); + g_assert(data && data->name); + g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED); + + /* run code for initializing the ID only */ + nmp_object_stackinit_id(&o_id, NMP_OBJECT_UP_CAST(received)); + nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), TRUE); + nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), FALSE); + + if (data->ifindex && data->ifindex != received->ifindex) + return; + if (data->change_type != change_type) + return; + + if (data->loop) + g_main_loop_quit(data->loop); + + data->received_count++; + _LOGD("Received signal '%s' %dth time.", data->name, data->received_count); } static void -ip6_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMPlatformIP6Route *received, int change_type_i, SignalData *data) +ip6_route_callback(NMPlatform * platform, + int obj_type_i, + int ifindex, + const NMPlatformIP6Route *received, + int change_type_i, + SignalData * data) { - const NMPObjectType obj_type = obj_type_i; - const NMPlatformSignalChangeType change_type = change_type_i; - NMPObject o_id; - nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, NULL); - - g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_IP6_ROUTE); - g_assert (received); - g_assert_cmpint (received->ifindex, ==, ifindex); - g_assert (data && data->name); - g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED); - - /* run code for initializing the ID only */ - nmp_object_stackinit_id (&o_id, NMP_OBJECT_UP_CAST (received)); - nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), TRUE); - nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), FALSE); - - if (data->ifindex && data->ifindex != received->ifindex) - return; - if (data->change_type != change_type) - return; - - if (data->loop) - g_main_loop_quit (data->loop); - - data->received_count++; - _LOGD ("Received signal '%s' %dth time.", data->name, data->received_count); + const NMPObjectType obj_type = obj_type_i; + const NMPlatformSignalChangeType change_type = change_type_i; + NMPObject o_id; + nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new(NMP_OBJECT_TYPE_IP6_ROUTE, NULL); + + g_assert_cmpint(obj_type, ==, NMP_OBJECT_TYPE_IP6_ROUTE); + g_assert(received); + g_assert_cmpint(received->ifindex, ==, ifindex); + g_assert(data && data->name); + g_assert_cmpstr(data->name, ==, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED); + + /* run code for initializing the ID only */ + nmp_object_stackinit_id(&o_id, NMP_OBJECT_UP_CAST(received)); + nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), TRUE); + nmp_object_copy(o_id_p, NMP_OBJECT_UP_CAST(received), FALSE); + + if (data->ifindex && data->ifindex != received->ifindex) + return; + if (data->change_type != change_type) + return; + + if (data->loop) + g_main_loop_quit(data->loop); + + data->received_count++; + _LOGD("Received signal '%s' %dth time.", data->name, data->received_count); } static void -test_ip4_route_metric0 (void) +test_ip4_route_metric0(void) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_route_callback); - SignalData *route_changed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip4_route_callback); - SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_route_callback); - in_addr_t network = nmtst_inet4_from_string ("192.0.2.5"); /* from 192.0.2.0/24 (TEST-NET-1) (rfc5737) */ - int plen = 32; - int metric = 22987; - int mss = 1000; - - /* No routes initially */ - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); - - /* add the first route */ - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss); - accept_signal (route_added); - - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); - - /* Deleting route with metric 0 does nothing */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); - ensure_no_signal (route_removed); - - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); - - /* add the second route */ - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss); - accept_signal (route_added); - - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, 0, 0); - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); - - /* Delete route with metric 0 */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); - accept_signal (route_removed); - - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); - - /* Delete route with metric 0 again (we expect nothing to happen) */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); - ensure_no_signal (route_removed); - - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); - - /* Delete the other route */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - accept_signal (route_removed); - - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); - - free_signal (route_added); - free_signal (route_changed); - free_signal (route_removed); + int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + SignalData *route_added = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip4_route_callback); + SignalData *route_changed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + ip4_route_callback); + SignalData *route_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip4_route_callback); + in_addr_t network = + nmtst_inet4_from_string("192.0.2.5"); /* from 192.0.2.0/24 (TEST-NET-1) (rfc5737) */ + int plen = 32; + int metric = 22987; + int mss = 1000; + + /* No routes initially */ + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0); + + /* add the first route */ + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network, + plen, + INADDR_ANY, + 0, + metric, + mss); + accept_signal(route_added); + + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0); + + /* Deleting route with metric 0 does nothing */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, 0)); + ensure_no_signal(route_removed); + + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0); + + /* add the second route */ + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network, + plen, + INADDR_ANY, + 0, + 0, + mss); + accept_signal(route_added); + + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0); + + /* Delete route with metric 0 */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, 0)); + accept_signal(route_removed); + + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0); + + /* Delete route with metric 0 again (we expect nothing to happen) */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, 0)); + ensure_no_signal(route_removed); + + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0); + + /* Delete the other route */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric)); + accept_signal(route_removed); + + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0); + + free_signal(route_added); + free_signal(route_changed); + free_signal(route_removed); } static void -test_ip4_route (void) +test_ip4_route(void) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_route_callback); - SignalData *route_changed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip4_route_callback); - SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_route_callback); - GPtrArray *routes; - NMPlatformIP4Route rts[3]; - in_addr_t network; - guint8 plen = 24; - in_addr_t gateway; - /* Choose a high metric so that we hopefully don't conflict. */ - int metric = 22986; - int mss = 1000; - - inet_pton (AF_INET, "192.0.3.0", &network); - inet_pton (AF_INET, "198.51.100.1", &gateway); - - /* Add route to gateway */ - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 32, INADDR_ANY, 0, metric, mss); - accept_signal (route_added); - - /* Add route */ - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss); - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); - accept_signal (route_added); - - /* Add route again */ - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss); - accept_signals (route_changed, 0, 1); - - /* Add default route */ - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, 0, 0, metric, 0); - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss); - nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, 0, 0, metric, 0); - accept_signal (route_added); - - /* Add default route again */ - nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss); - accept_signals (route_changed, 0, 1); - - /* Test route listing */ - routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); - memset (rts, 0, sizeof (rts)); - rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[0].network = gateway; - rts[0].plen = 32; - rts[0].ifindex = ifindex; - rts[0].gateway = INADDR_ANY; - rts[0].metric = metric; - rts[0].mss = mss; - rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK); - rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[1].network = network; - rts[1].plen = plen; - rts[1].ifindex = ifindex; - rts[1].gateway = gateway; - rts[1].metric = metric; - rts[1].mss = mss; - rts[1].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE); - rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[2].network = 0; - rts[2].plen = 0; - rts[2].ifindex = ifindex; - rts[2].gateway = gateway; - rts[2].metric = metric; - rts[2].mss = mss; - rts[2].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE); - g_assert_cmpint (routes->len, ==, 3); - nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE); - g_ptr_array_unref (routes); - - /* Remove route */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); - accept_signal (route_removed); - - /* Remove route again */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - - /* Remove default route */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, 0, 0, metric)); - accept_signal (route_removed); - - /* Remove route to gateway */ - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, gateway, 32, metric)); - accept_signal (route_removed); - - free_signal (route_added); - free_signal (route_changed); - free_signal (route_removed); + int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + SignalData * route_added = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip4_route_callback); + SignalData * route_changed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + ip4_route_callback); + SignalData * route_removed = add_signal(NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip4_route_callback); + GPtrArray * routes; + NMPlatformIP4Route rts[3]; + in_addr_t network; + guint8 plen = 24; + in_addr_t gateway; + /* Choose a high metric so that we hopefully don't conflict. */ + int metric = 22986; + int mss = 1000; + + inet_pton(AF_INET, "192.0.3.0", &network); + inet_pton(AF_INET, "198.51.100.1", &gateway); + + /* Add route to gateway */ + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + gateway, + 32, + INADDR_ANY, + 0, + metric, + mss); + accept_signal(route_added); + + /* Add route */ + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0); + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network, + plen, + gateway, + 0, + metric, + mss); + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, network, plen, metric, 0); + accept_signal(route_added); + + /* Add route again */ + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network, + plen, + gateway, + 0, + metric, + mss); + accept_signals(route_changed, 0, 1); + + /* Add default route */ + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, 0, 0, metric, 0); + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + 0, + 0, + gateway, + 0, + metric, + mss); + nmtstp_assert_ip4_route_exists(NULL, 1, DEVICE_NAME, 0, 0, metric, 0); + accept_signal(route_added); + + /* Add default route again */ + nmtstp_ip4_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + 0, + 0, + gateway, + 0, + metric, + mss); + accept_signals(route_changed, 0, 1); + + /* Test route listing */ + routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex); + memset(rts, 0, sizeof(rts)); + rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[0].network = gateway; + rts[0].plen = 32; + rts[0].ifindex = ifindex; + rts[0].gateway = INADDR_ANY; + rts[0].metric = metric; + rts[0].mss = mss; + rts[0].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_LINK); + rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[1].network = network; + rts[1].plen = plen; + rts[1].ifindex = ifindex; + rts[1].gateway = gateway; + rts[1].metric = metric; + rts[1].mss = mss; + rts[1].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE); + rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[2].network = 0; + rts[2].plen = 0; + rts[2].ifindex = ifindex; + rts[2].gateway = gateway; + rts[2].metric = metric; + rts[2].mss = mss; + rts[2].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE); + g_assert_cmpint(routes->len, ==, 3); + nmtst_platform_ip4_routes_equal_aptr((const NMPObject *const *) routes->pdata, + rts, + routes->len, + TRUE); + g_ptr_array_unref(routes); + + /* Remove route */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric)); + nmtstp_assert_ip4_route_exists(NULL, 0, DEVICE_NAME, network, plen, metric, 0); + accept_signal(route_removed); + + /* Remove route again */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric)); + + /* Remove default route */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, 0, 0, metric)); + accept_signal(route_removed); + + /* Remove route to gateway */ + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, ifindex, gateway, 32, metric)); + accept_signal(route_removed); + + free_signal(route_added); + free_signal(route_changed); + free_signal(route_removed); } static void -test_ip6_route (void) +test_ip6_route(void) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_route_callback); - SignalData *route_changed = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip6_route_callback); - SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip6_route_callback); - GPtrArray *routes; - NMPlatformIP6Route rts[3]; - struct in6_addr network; - guint8 plen = 64; - struct in6_addr gateway, pref_src; - /* Choose a high metric so that we hopefully don't conflict. */ - const int metric = 22987; - int mss = 1000; - - inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network); - inet_pton (AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway); - inet_pton (AF_INET6, "::42", &pref_src); - - g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, pref_src, 128, in6addr_any, - NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0)); - accept_signals (route_added, 0, 3); - - _wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 200, ifindex, 1, &pref_src); - - /* Add route to gateway */ - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, in6addr_any, metric, mss); - accept_signals (route_added, 0, 3); - - /* Add route */ - g_assert (!nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, pref_src, metric, mss); - g_assert (nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); - accept_signal (route_added); - - /* Add route again */ - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, pref_src, metric, mss); - accept_signals (route_changed, 0, 1); - - /* Add default route */ - g_assert (!nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0)); - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, in6addr_any, metric, mss); - g_assert (nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0)); - accept_signal (route_added); - - /* Add default route again */ - nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, in6addr_any, metric, mss); - accept_signals (route_changed, 0, 1); - - /* Test route listing */ - routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex); - memset (rts, 0, sizeof (rts)); - rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[0].network = gateway; - rts[0].plen = 128; - rts[0].ifindex = ifindex; - rts[0].gateway = in6addr_any; - rts[0].pref_src = in6addr_any; - rts[0].metric = metric; - rts[0].mss = mss; - rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[1].network = network; - rts[1].plen = plen; - rts[1].ifindex = ifindex; - rts[1].gateway = gateway; - rts[1].pref_src = pref_src; - rts[1].metric = metric; - rts[1].mss = mss; - rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[2].network = in6addr_any; - rts[2].plen = 0; - rts[2].ifindex = ifindex; - rts[2].gateway = gateway; - rts[2].pref_src = in6addr_any; - rts[2].metric = metric; - rts[2].mss = mss; - g_assert_cmpint (routes->len, ==, 3); - nmtst_platform_ip6_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE); - g_ptr_array_unref (routes); - - /* Remove route */ - g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - g_assert (!nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); - accept_signal (route_removed); - - /* Remove route again */ - g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - - /* Remove default route */ - g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); - accept_signal (route_removed); - - /* Remove route to gateway */ - g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, gateway, 128, metric)); - accept_signal (route_removed); - - free_signal (route_added); - free_signal (route_changed); - free_signal (route_removed); + int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + SignalData * route_added = add_signal(NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_ADDED, + ip6_route_callback); + SignalData * route_changed = add_signal(NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_CHANGED, + ip6_route_callback); + SignalData * route_removed = add_signal(NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, + NM_PLATFORM_SIGNAL_REMOVED, + ip6_route_callback); + GPtrArray * routes; + NMPlatformIP6Route rts[3]; + struct in6_addr network; + guint8 plen = 64; + struct in6_addr gateway, pref_src; + /* Choose a high metric so that we hopefully don't conflict. */ + const int metric = 22987; + int mss = 1000; + + inet_pton(AF_INET6, "2001:db8:a:b:0:0:0:0", &network); + inet_pton(AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway); + inet_pton(AF_INET6, "::42", &pref_src); + + g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET, + ifindex, + pref_src, + 128, + in6addr_any, + NM_PLATFORM_LIFETIME_PERMANENT, + NM_PLATFORM_LIFETIME_PERMANENT, + 0)); + accept_signals(route_added, 0, 3); + + _wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 200, ifindex, 1, &pref_src); + + /* Add route to gateway */ + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + gateway, + 128, + in6addr_any, + in6addr_any, + metric, + mss); + accept_signals(route_added, 0, 3); + + /* Add route */ + g_assert(!nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network, + plen, + gateway, + pref_src, + metric, + mss); + g_assert(nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); + accept_signal(route_added); + + /* Add route again */ + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + network, + plen, + gateway, + pref_src, + metric, + mss); + accept_signals(route_changed, 0, 1); + + /* Add default route */ + g_assert(!nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0)); + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + in6addr_any, + 0, + gateway, + in6addr_any, + metric, + mss); + g_assert(nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0)); + accept_signal(route_added); + + /* Add default route again */ + nmtstp_ip6_route_add(NM_PLATFORM_GET, + ifindex, + NM_IP_CONFIG_SOURCE_USER, + in6addr_any, + 0, + gateway, + in6addr_any, + metric, + mss); + accept_signals(route_changed, 0, 1); + + /* Test route listing */ + routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex); + memset(rts, 0, sizeof(rts)); + rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[0].network = gateway; + rts[0].plen = 128; + rts[0].ifindex = ifindex; + rts[0].gateway = in6addr_any; + rts[0].pref_src = in6addr_any; + rts[0].metric = metric; + rts[0].mss = mss; + rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[1].network = network; + rts[1].plen = plen; + rts[1].ifindex = ifindex; + rts[1].gateway = gateway; + rts[1].pref_src = pref_src; + rts[1].metric = metric; + rts[1].mss = mss; + rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER); + rts[2].network = in6addr_any; + rts[2].plen = 0; + rts[2].ifindex = ifindex; + rts[2].gateway = gateway; + rts[2].pref_src = in6addr_any; + rts[2].metric = metric; + rts[2].mss = mss; + g_assert_cmpint(routes->len, ==, 3); + nmtst_platform_ip6_routes_equal_aptr((const NMPObject *const *) routes->pdata, + rts, + routes->len, + TRUE); + g_ptr_array_unref(routes); + + /* Remove route */ + g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert(!nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); + accept_signal(route_removed); + + /* Remove route again */ + g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, network, plen, metric)); + + /* Remove default route */ + g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + accept_signal(route_removed); + + /* Remove route to gateway */ + g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, ifindex, gateway, 128, metric)); + accept_signal(route_removed); + + free_signal(route_added); + free_signal(route_changed); + free_signal(route_removed); } /*****************************************************************************/ static void -test_ip4_route_get (void) +test_ip4_route_get(void) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - in_addr_t a; - int result; - nm_auto_nmpobj NMPObject *route = NULL; - const NMPlatformIP4Route *r; - - nmtstp_run_command_check ("ip route add 1.2.3.0/24 dev %s", DEVICE_NAME); - - NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (NM_PLATFORM_GET, 10); - if (nmtstp_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.0"), 24, 0, 0)) - break; - }); - - a = nmtst_inet4_from_string ("1.2.3.1"); - result = nm_platform_ip_route_get (NM_PLATFORM_GET, - AF_INET, - &a, - nmtst_get_rand_uint32 () % 2 ? 0 : ifindex, - &route); - - g_assert (NMTST_NM_ERR_SUCCESS (result)); - g_assert (NMP_OBJECT_GET_TYPE (route) == NMP_OBJECT_TYPE_IP4_ROUTE); - g_assert (!NMP_OBJECT_IS_STACKINIT (route)); - g_assert (route->parent._ref_count == 1); - r = NMP_OBJECT_CAST_IP4_ROUTE (route); - g_assert (NM_FLAGS_HAS (r->r_rtm_flags, RTM_F_CLONED)); - g_assert (r->ifindex == ifindex); - g_assert (r->network == a); - g_assert (r->plen == 32); - - nmtstp_run_command_check ("ip route flush dev %s", DEVICE_NAME); - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); + int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + in_addr_t a; + int result; + nm_auto_nmpobj NMPObject *route = NULL; + const NMPlatformIP4Route *r; + + nmtstp_run_command_check("ip route add 1.2.3.0/24 dev %s", DEVICE_NAME); + + NMTST_WAIT_ASSERT(100, { + nmtstp_wait_for_signal(NM_PLATFORM_GET, 10); + if (nmtstp_ip4_route_get(NM_PLATFORM_GET, + ifindex, + nmtst_inet4_from_string("1.2.3.0"), + 24, + 0, + 0)) + break; + }); + + a = nmtst_inet4_from_string("1.2.3.1"); + result = nm_platform_ip_route_get(NM_PLATFORM_GET, + AF_INET, + &a, + nmtst_get_rand_uint32() % 2 ? 0 : ifindex, + &route); + + g_assert(NMTST_NM_ERR_SUCCESS(result)); + g_assert(NMP_OBJECT_GET_TYPE(route) == NMP_OBJECT_TYPE_IP4_ROUTE); + g_assert(!NMP_OBJECT_IS_STACKINIT(route)); + g_assert(route->parent._ref_count == 1); + r = NMP_OBJECT_CAST_IP4_ROUTE(route); + g_assert(NM_FLAGS_HAS(r->r_rtm_flags, RTM_F_CLONED)); + g_assert(r->ifindex == ifindex); + g_assert(r->network == a); + g_assert(r->plen == 32); + + nmtstp_run_command_check("ip route flush dev %s", DEVICE_NAME); + + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); } static void -test_ip4_zero_gateway (void) +test_ip4_zero_gateway(void) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - - nmtstp_run_command_check ("ip route add 1.2.3.1/32 via 0.0.0.0 dev %s", DEVICE_NAME); - nmtstp_run_command_check ("ip route add 1.2.3.2/32 dev %s", DEVICE_NAME); - - NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (NM_PLATFORM_GET, 10); - if ( nmtstp_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.1"), 32, 0, 0) - && nmtstp_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.2"), 32, 0, 0)) - break; - }); - - nmtstp_run_command_check ("ip route flush dev %s", DEVICE_NAME); - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); + int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + + nmtstp_run_command_check("ip route add 1.2.3.1/32 via 0.0.0.0 dev %s", DEVICE_NAME); + nmtstp_run_command_check("ip route add 1.2.3.2/32 dev %s", DEVICE_NAME); + + NMTST_WAIT_ASSERT(100, { + nmtstp_wait_for_signal(NM_PLATFORM_GET, 10); + if (nmtstp_ip4_route_get(NM_PLATFORM_GET, + ifindex, + nmtst_inet4_from_string("1.2.3.1"), + 32, + 0, + 0) + && nmtstp_ip4_route_get(NM_PLATFORM_GET, + ifindex, + nmtst_inet4_from_string("1.2.3.2"), + 32, + 0, + 0)) + break; + }); + + nmtstp_run_command_check("ip route flush dev %s", DEVICE_NAME); + + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); } static void -test_ip4_route_options (gconstpointer test_data) +test_ip4_route_options(gconstpointer test_data) { - const int TEST_IDX = GPOINTER_TO_INT (test_data); - const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - gs_unref_ptrarray GPtrArray *routes = NULL; + const int TEST_IDX = GPOINTER_TO_INT(test_data); + const int IFINDEX = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + gs_unref_ptrarray GPtrArray *routes = NULL; #define RTS_MAX 3 - NMPlatformIP4Route rts_add[RTS_MAX] = { }; - NMPlatformIP4Route rts_cmp[RTS_MAX] = { }; - NMPlatformIP4Address addr[1] = { }; - guint i; - guint rts_n = 0; - guint addr_n = 0; - - switch (TEST_IDX) { - case 1: - rts_add[rts_n++] = ((NMPlatformIP4Route) { - .ifindex = IFINDEX, - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .network = nmtst_inet4_from_string ("172.16.1.0"), - .plen = 24, - .metric = 20, - .tos = 0x28, - .window = 10000, - .cwnd = 16, - .initcwnd = 30, - .initrwnd = 50, - .mtu = 1350, - .lock_cwnd = TRUE, - }); - break; - case 2: - addr[addr_n++] = ((NMPlatformIP4Address) { - .ifindex = IFINDEX, - .address = nmtst_inet4_from_string ("172.16.1.5"), - .peer_address = nmtst_inet4_from_string ("172.16.1.5"), - .plen = 24, - .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, - .preferred = NM_PLATFORM_LIFETIME_PERMANENT, - .n_ifa_flags = 0, - }); - rts_add[rts_n++] = ((NMPlatformIP4Route) { - .ifindex = IFINDEX, - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .network = nmtst_inet4_from_string ("172.17.1.0"), - .gateway = nmtst_inet4_from_string ("172.16.1.1"), - .plen = 24, - .metric = 20, - }); - rts_add[rts_n++] = ((NMPlatformIP4Route) { - .ifindex = IFINDEX, - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .network = nmtst_inet4_from_string ("172.19.1.0"), - .gateway = nmtst_inet4_from_string ("172.18.1.1"), - .r_rtm_flags = RTNH_F_ONLINK, - .plen = 24, - .metric = 20, - }); - break; - default: - g_assert_not_reached (); - break; - } - g_assert (rts_n <= G_N_ELEMENTS (rts_add)); - g_assert (addr_n <= G_N_ELEMENTS (addr)); - - for (i = 0; i < addr_n; i++) { - const NMPlatformIP4Address *a = &addr[i]; - - g_assert (a->ifindex == IFINDEX); - g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, - a->ifindex, - a->address, - a->plen, - a->peer_address, - nm_platform_ip4_broadcast_address_create (a->address, a->plen), - a->lifetime, - a->preferred, - a->n_ifa_flags, - a->label)); - if (a->peer_address == a->address) - _wait_for_ipv4_addr_device_route (NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen); - } - - for (i = 0; i < rts_n; i++) - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]))); - - for (i = 0; i < rts_n; i++) { - rts_cmp[i] = rts_add[i]; - nm_platform_ip_route_normalize (AF_INET, NM_PLATFORM_IP_ROUTE_CAST (&rts_cmp[i])); - } - - routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, IFINDEX); - g_assert_cmpint (routes->len, ==, rts_n); - nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts_cmp, routes->len, TRUE); - - for (i = 0; i < rts_n; i++) { - g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, IFINDEX, - rts_add[i].network, rts_add[i].plen, - rts_add[i].metric)); - } + NMPlatformIP4Route rts_add[RTS_MAX] = {}; + NMPlatformIP4Route rts_cmp[RTS_MAX] = {}; + NMPlatformIP4Address addr[1] = {}; + guint i; + guint rts_n = 0; + guint addr_n = 0; + + switch (TEST_IDX) { + case 1: + rts_add[rts_n++] = ((NMPlatformIP4Route){ + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = nmtst_inet4_from_string("172.16.1.0"), + .plen = 24, + .metric = 20, + .tos = 0x28, + .window = 10000, + .cwnd = 16, + .initcwnd = 30, + .initrwnd = 50, + .mtu = 1350, + .lock_cwnd = TRUE, + }); + break; + case 2: + addr[addr_n++] = ((NMPlatformIP4Address){ + .ifindex = IFINDEX, + .address = nmtst_inet4_from_string("172.16.1.5"), + .peer_address = nmtst_inet4_from_string("172.16.1.5"), + .plen = 24, + .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, + .preferred = NM_PLATFORM_LIFETIME_PERMANENT, + .n_ifa_flags = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP4Route){ + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = nmtst_inet4_from_string("172.17.1.0"), + .gateway = nmtst_inet4_from_string("172.16.1.1"), + .plen = 24, + .metric = 20, + }); + rts_add[rts_n++] = ((NMPlatformIP4Route){ + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = nmtst_inet4_from_string("172.19.1.0"), + .gateway = nmtst_inet4_from_string("172.18.1.1"), + .r_rtm_flags = RTNH_F_ONLINK, + .plen = 24, + .metric = 20, + }); + break; + default: + g_assert_not_reached(); + break; + } + g_assert(rts_n <= G_N_ELEMENTS(rts_add)); + g_assert(addr_n <= G_N_ELEMENTS(addr)); + + for (i = 0; i < addr_n; i++) { + const NMPlatformIP4Address *a = &addr[i]; + + g_assert(a->ifindex == IFINDEX); + g_assert(nm_platform_ip4_address_add( + NM_PLATFORM_GET, + a->ifindex, + a->address, + a->plen, + a->peer_address, + nm_platform_ip4_broadcast_address_create(a->address, a->plen), + a->lifetime, + a->preferred, + a->n_ifa_flags, + a->label)); + if (a->peer_address == a->address) + _wait_for_ipv4_addr_device_route(NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen); + } + + for (i = 0; i < rts_n; i++) + g_assert(NMTST_NM_ERR_SUCCESS( + nm_platform_ip4_route_add(NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]))); + + for (i = 0; i < rts_n; i++) { + rts_cmp[i] = rts_add[i]; + nm_platform_ip_route_normalize(AF_INET, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i])); + } + + routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, IFINDEX); + g_assert_cmpint(routes->len, ==, rts_n); + nmtst_platform_ip4_routes_equal_aptr((const NMPObject *const *) routes->pdata, + rts_cmp, + routes->len, + TRUE); + + for (i = 0; i < rts_n; i++) { + g_assert(nmtstp_platform_ip4_route_delete(NM_PLATFORM_GET, + IFINDEX, + rts_add[i].network, + rts_add[i].plen, + rts_add[i].metric)); + } #undef RTS_MAX } static void -test_ip6_route_get (void) +test_ip6_route_get(void) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - const struct in6_addr *a; - int result; - nm_auto_nmpobj NMPObject *route = NULL; - const NMPlatformIP6Route *r; - - nmtstp_run_command_check ("ip -6 route add fd01:abcd::/64 via fe80::99 dev %s", DEVICE_NAME); - - NMTST_WAIT_ASSERT (100, { - nmtstp_wait_for_signal (NM_PLATFORM_GET, 10); - if (nmtstp_ip6_route_get (NM_PLATFORM_GET, - ifindex, - nmtst_inet6_from_string ("fd01:abcd::"), - 64, - NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, - NULL, - 0)) - break; - }); - - a = nmtst_inet6_from_string ("fd01:abcd::42"); - result = nm_platform_ip_route_get (NM_PLATFORM_GET, - AF_INET6, - a, - nmtst_get_rand_uint32 () % 2 ? 0 : ifindex, - &route); - - g_assert (NMTST_NM_ERR_SUCCESS (result)); - g_assert (NMP_OBJECT_GET_TYPE (route) == NMP_OBJECT_TYPE_IP6_ROUTE); - g_assert (!NMP_OBJECT_IS_STACKINIT (route)); - g_assert (route->parent._ref_count == 1); - r = NMP_OBJECT_CAST_IP6_ROUTE (route); - g_assert (r->ifindex == ifindex); - nmtst_assert_ip6_address (&r->network, "fd01:abcd::42"); - g_assert_cmpint (r->plen, ==, 128); - nmtst_assert_ip6_address (&r->gateway, "fe80::99"); - - nmtstp_run_command_check ("ip -6 route flush dev %s", DEVICE_NAME); - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); + int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + const struct in6_addr *a; + int result; + nm_auto_nmpobj NMPObject *route = NULL; + const NMPlatformIP6Route *r; + + nmtstp_run_command_check("ip -6 route add fd01:abcd::/64 via fe80::99 dev %s", DEVICE_NAME); + + NMTST_WAIT_ASSERT(100, { + nmtstp_wait_for_signal(NM_PLATFORM_GET, 10); + if (nmtstp_ip6_route_get(NM_PLATFORM_GET, + ifindex, + nmtst_inet6_from_string("fd01:abcd::"), + 64, + NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, + NULL, + 0)) + break; + }); + + a = nmtst_inet6_from_string("fd01:abcd::42"); + result = nm_platform_ip_route_get(NM_PLATFORM_GET, + AF_INET6, + a, + nmtst_get_rand_uint32() % 2 ? 0 : ifindex, + &route); + + g_assert(NMTST_NM_ERR_SUCCESS(result)); + g_assert(NMP_OBJECT_GET_TYPE(route) == NMP_OBJECT_TYPE_IP6_ROUTE); + g_assert(!NMP_OBJECT_IS_STACKINIT(route)); + g_assert(route->parent._ref_count == 1); + r = NMP_OBJECT_CAST_IP6_ROUTE(route); + g_assert(r->ifindex == ifindex); + nmtst_assert_ip6_address(&r->network, "fd01:abcd::42"); + g_assert_cmpint(r->plen, ==, 128); + nmtst_assert_ip6_address(&r->gateway, "fe80::99"); + + nmtstp_run_command_check("ip -6 route flush dev %s", DEVICE_NAME); + + nmtstp_wait_for_signal(NM_PLATFORM_GET, 50); } static void -test_ip6_route_options (gconstpointer test_data) +test_ip6_route_options(gconstpointer test_data) { - const int TEST_IDX = GPOINTER_TO_INT (test_data); - const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - gs_unref_ptrarray GPtrArray *routes = NULL; + const int TEST_IDX = GPOINTER_TO_INT(test_data); + const int IFINDEX = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + gs_unref_ptrarray GPtrArray *routes = NULL; #define RTS_MAX 3 - NMPlatformIP6Route rts_add[RTS_MAX] = { }; - NMPlatformIP6Route rts_cmp[RTS_MAX] = { }; - NMPlatformIP6Address addr[1] = { }; - struct in6_addr addr_in6[G_N_ELEMENTS (addr)] = { }; - guint rts_n = 0; - guint addr_n = 0; - guint i; - - switch (TEST_IDX) { - case 1: - rts_add[rts_n++] = ((NMPlatformIP6Route) { - .ifindex = IFINDEX, - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .network = *nmtst_inet6_from_string ("2001:db8:a:b:0:0:0:0"), - .plen = 64, - .gateway = in6addr_any, - .metric = 1024, - .window = 20000, - .cwnd = 8, - .initcwnd = 22, - .initrwnd = 33, - .mtu = 1300, - .lock_mtu = TRUE, - }); - break; - case 2: - addr[addr_n++] = ((NMPlatformIP6Address) { - .ifindex = IFINDEX, - .address = *nmtst_inet6_from_string ("2000::2"), - .plen = 128, - .peer_address = in6addr_any, - .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, - .preferred = NM_PLATFORM_LIFETIME_PERMANENT, - .n_ifa_flags = 0, - }); - rts_add[rts_n++] = ((NMPlatformIP6Route) { - .ifindex = IFINDEX, - .rt_source = NM_IP_CONFIG_SOURCE_USER, - .network = *nmtst_inet6_from_string ("1010::1"), - .plen = 128, - .gateway = in6addr_any, - .metric = 256, - .pref_src = *nmtst_inet6_from_string ("2000::2"), - }); - break; - case 3: - addr[addr_n++] = ((NMPlatformIP6Address) { - .ifindex = IFINDEX, - .address = *nmtst_inet6_from_string ("2001:db8:8086::5"), - .plen = 128, - .peer_address = in6addr_any, - .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, - .preferred = NM_PLATFORM_LIFETIME_PERMANENT, - .n_ifa_flags = 0, - }); - rts_add[rts_n++] = ((NMPlatformIP6Route) { - .ifindex = IFINDEX, - .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), - .network = *nmtst_inet6_from_string ("2001:db8:8086::"), - .plen = 110, - .metric = 10021, - .mss = 0, - }); - rts_add[rts_n++] = ((NMPlatformIP6Route) { - .ifindex = IFINDEX, - .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), - .network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"), - .plen = 64, - .gateway = *nmtst_inet6_from_string ("2001:db8:8086::1"), - .metric = 21, - .mss = 0, - }); - break; - default: - g_assert_not_reached (); - } - g_assert (rts_n <= G_N_ELEMENTS (rts_add)); - g_assert (addr_n <= G_N_ELEMENTS (addr)); - - for (i = 0; i < addr_n; i++) { - g_assert (addr[i].ifindex == IFINDEX); - addr_in6[i] = addr[i].address; - g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, - IFINDEX, - addr[i].address, - addr[i].plen, - addr[i].peer_address, - addr[i].lifetime, - addr[i].preferred, - addr[i].n_ifa_flags)); - } - _wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6); - - for (i = 0; i < rts_n; i++) - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_ip6_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]))); - - for (i = 0; i < rts_n; i++) { - rts_cmp[i] = rts_add[i]; - nm_platform_ip_route_normalize (AF_INET6, NM_PLATFORM_IP_ROUTE_CAST (&rts_cmp[i])); - } - - routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX); - g_assert_cmpint (routes->len, ==, rts_n); - nmtst_platform_ip6_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts_cmp, routes->len, TRUE); - - for (i = 0; i < rts_n; i++) { - g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, IFINDEX, - rts_add[i].network, rts_add[i].plen, - rts_add[i].metric)); - } - - for (i = 0; i < addr_n; i++) { - nmtstp_ip6_address_del (NM_PLATFORM_GET, - EX, - IFINDEX, - rts_add[i].network, - rts_add[i].plen); - } + NMPlatformIP6Route rts_add[RTS_MAX] = {}; + NMPlatformIP6Route rts_cmp[RTS_MAX] = {}; + NMPlatformIP6Address addr[1] = {}; + struct in6_addr addr_in6[G_N_ELEMENTS(addr)] = {}; + guint rts_n = 0; + guint addr_n = 0; + guint i; + + switch (TEST_IDX) { + case 1: + rts_add[rts_n++] = ((NMPlatformIP6Route){ + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = *nmtst_inet6_from_string("2001:db8:a:b:0:0:0:0"), + .plen = 64, + .gateway = in6addr_any, + .metric = 1024, + .window = 20000, + .cwnd = 8, + .initcwnd = 22, + .initrwnd = 33, + .mtu = 1300, + .lock_mtu = TRUE, + }); + break; + case 2: + addr[addr_n++] = ((NMPlatformIP6Address){ + .ifindex = IFINDEX, + .address = *nmtst_inet6_from_string("2000::2"), + .plen = 128, + .peer_address = in6addr_any, + .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, + .preferred = NM_PLATFORM_LIFETIME_PERMANENT, + .n_ifa_flags = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP6Route){ + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = *nmtst_inet6_from_string("1010::1"), + .plen = 128, + .gateway = in6addr_any, + .metric = 256, + .pref_src = *nmtst_inet6_from_string("2000::2"), + }); + break; + case 3: + addr[addr_n++] = ((NMPlatformIP6Address){ + .ifindex = IFINDEX, + .address = *nmtst_inet6_from_string("2001:db8:8086::5"), + .plen = 128, + .peer_address = in6addr_any, + .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, + .preferred = NM_PLATFORM_LIFETIME_PERMANENT, + .n_ifa_flags = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP6Route){ + .ifindex = IFINDEX, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER), + .network = *nmtst_inet6_from_string("2001:db8:8086::"), + .plen = 110, + .metric = 10021, + .mss = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP6Route){ + .ifindex = IFINDEX, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER), + .network = *nmtst_inet6_from_string("2001:db8:abad:c0de::"), + .plen = 64, + .gateway = *nmtst_inet6_from_string("2001:db8:8086::1"), + .metric = 21, + .mss = 0, + }); + break; + default: + g_assert_not_reached(); + } + g_assert(rts_n <= G_N_ELEMENTS(rts_add)); + g_assert(addr_n <= G_N_ELEMENTS(addr)); + + for (i = 0; i < addr_n; i++) { + g_assert(addr[i].ifindex == IFINDEX); + addr_in6[i] = addr[i].address; + g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET, + IFINDEX, + addr[i].address, + addr[i].plen, + addr[i].peer_address, + addr[i].lifetime, + addr[i].preferred, + addr[i].n_ifa_flags)); + } + _wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6); + + for (i = 0; i < rts_n; i++) + g_assert(NMTST_NM_ERR_SUCCESS( + nm_platform_ip6_route_add(NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]))); + + for (i = 0; i < rts_n; i++) { + rts_cmp[i] = rts_add[i]; + nm_platform_ip_route_normalize(AF_INET6, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i])); + } + + routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, IFINDEX); + g_assert_cmpint(routes->len, ==, rts_n); + nmtst_platform_ip6_routes_equal_aptr((const NMPObject *const *) routes->pdata, + rts_cmp, + routes->len, + TRUE); + + for (i = 0; i < rts_n; i++) { + g_assert(nmtstp_platform_ip6_route_delete(NM_PLATFORM_GET, + IFINDEX, + rts_add[i].network, + rts_add[i].plen, + rts_add[i].metric)); + } + + for (i = 0; i < addr_n; i++) { + nmtstp_ip6_address_del(NM_PLATFORM_GET, EX, IFINDEX, rts_add[i].network, rts_add[i].plen); + } #undef RTS_MAX } /*****************************************************************************/ static void -test_ip (gconstpointer test_data) +test_ip(gconstpointer test_data) { - const int TEST_IDX = GPOINTER_TO_INT (test_data); - const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - guint i, j, k; - const NMPlatformLink *l; - char ifname[IFNAMSIZ]; - char ifname2[IFNAMSIZ]; - char s1[NM_UTILS_INET_ADDRSTRLEN]; - NMPlatform *platform = NM_PLATFORM_GET; - const int EX_ = -1; - struct { - int ifindex; - } iface_data[10] = { { 0 }, }; - int order_idx[G_N_ELEMENTS (iface_data)] = { 0 }; - guint order_len; - guint try; - - for (i = 0; i < G_N_ELEMENTS (iface_data); i++) { - nm_sprintf_buf (ifname, "v%02u", i); - nm_sprintf_buf (ifname2, "w%02u", i); - - g_assert (!nm_platform_link_get_by_ifname (platform, ifname)); - g_assert (!nm_platform_link_get_by_ifname (platform, ifname2)); - l = nmtstp_link_veth_add (platform, EX_, ifname, ifname2); - iface_data[i].ifindex = l->ifindex; - - nmtstp_link_set_updown (platform, EX_, iface_data[i].ifindex, TRUE); - nmtstp_link_set_updown (platform, EX_, nmtstp_link_get (platform, -1, ifname2)->ifindex, TRUE); - - nm_sprintf_buf (s1, "192.168.7.%d", 100 + i); - nmtstp_ip4_address_add (platform, - EX_, - iface_data[i].ifindex, - nmtst_inet4_from_string (s1), - 24, - nmtst_inet4_from_string (s1), - 3600, - 3600, - 0, - NULL); - } - - order_len = 0; - for (try = 0; try < 5 * G_N_ELEMENTS (order_idx); try++) { - NMPObject o; - NMPlatformIP4Route *r; - guint idx; - const NMDedupMultiHeadEntry *head_entry; - NMPLookup lookup; - - nmp_object_stackinit (&o, NMP_OBJECT_TYPE_IP4_ROUTE, NULL); - r = NMP_OBJECT_CAST_IP4_ROUTE (&o); - r->network = nmtst_inet4_from_string ("192.168.9.0"); - r->plen = 24; - r->metric = 109; - - if ( order_len == 0 - || ( order_len < G_N_ELEMENTS (order_idx) - && nmtst_get_rand_uint32 () % 2)) { + const int TEST_IDX = GPOINTER_TO_INT(test_data); + const int IFINDEX = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + guint i, j, k; + const NMPlatformLink *l; + char ifname[IFNAMSIZ]; + char ifname2[IFNAMSIZ]; + char s1[NM_UTILS_INET_ADDRSTRLEN]; + NMPlatform * platform = NM_PLATFORM_GET; + const int EX_ = -1; + struct { + int ifindex; + } iface_data[10] = { + {0}, + }; + int order_idx[G_N_ELEMENTS(iface_data)] = {0}; + guint order_len; + guint try; + + for (i = 0; i < G_N_ELEMENTS(iface_data); i++) { + nm_sprintf_buf(ifname, "v%02u", i); + nm_sprintf_buf(ifname2, "w%02u", i); + + g_assert(!nm_platform_link_get_by_ifname(platform, ifname)); + g_assert(!nm_platform_link_get_by_ifname(platform, ifname2)); + l = nmtstp_link_veth_add(platform, EX_, ifname, ifname2); + iface_data[i].ifindex = l->ifindex; + + nmtstp_link_set_updown(platform, EX_, iface_data[i].ifindex, TRUE); + nmtstp_link_set_updown(platform, + EX_, + nmtstp_link_get(platform, -1, ifname2)->ifindex, + TRUE); + + nm_sprintf_buf(s1, "192.168.7.%d", 100 + i); + nmtstp_ip4_address_add(platform, + EX_, + iface_data[i].ifindex, + nmtst_inet4_from_string(s1), + 24, + nmtst_inet4_from_string(s1), + 3600, + 3600, + 0, + NULL); + } + + order_len = 0; + for (try = 0; try < 5 * G_N_ELEMENTS(order_idx); try++) { + NMPObject o; + NMPlatformIP4Route * r; + guint idx; + const NMDedupMultiHeadEntry *head_entry; + NMPLookup lookup; + + nmp_object_stackinit(&o, NMP_OBJECT_TYPE_IP4_ROUTE, NULL); + r = NMP_OBJECT_CAST_IP4_ROUTE(&o); + r->network = nmtst_inet4_from_string("192.168.9.0"); + r->plen = 24; + r->metric = 109; + + if (order_len == 0 + || (order_len < G_N_ELEMENTS(order_idx) && nmtst_get_rand_uint32() % 2)) { again_find_idx: - idx = nmtst_get_rand_uint32 () % G_N_ELEMENTS (iface_data); - for (i = 0; i < order_len; i++) { - if (order_idx[i] == idx) - goto again_find_idx; - } - order_idx[order_len++] = idx; - - r->ifindex = iface_data[idx].ifindex; - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_APPEND, r))); - } else { - i = nmtst_get_rand_uint32 () % order_len; - idx = order_idx[i]; - for (i++; i < order_len; i++) - order_idx[i - 1] = order_idx[i]; - order_len--; - - r->ifindex = iface_data[idx].ifindex; - g_assert (nm_platform_object_delete (platform, &o)); - } - - head_entry = nm_platform_lookup (platform, - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_IP4_ROUTE)); - for (j = 0; j < G_N_ELEMENTS (iface_data); j++) { - gboolean has; - NMDedupMultiIter iter; - const NMPObject *o_cached; - - has = FALSE; - for (k = 0; k < order_len; k++) { - if (order_idx[k] == j) { - g_assert (!has); - has = TRUE; - } - } - - nmp_cache_iter_for_each (&iter, head_entry, &o_cached) { - const NMPlatformIP4Route *r_cached = NMP_OBJECT_CAST_IP4_ROUTE (o_cached); - - if ( r_cached->ifindex != iface_data[j].ifindex - || r_cached->metric != 109) - continue; - - g_assert (has); - has = FALSE; - } - g_assert (!has); - } - } - - for (i = 0; i < G_N_ELEMENTS (iface_data); i++) - g_assert (nm_platform_link_delete (platform, iface_data[i].ifindex)); - - (void) TEST_IDX; - (void) IFINDEX; + idx = nmtst_get_rand_uint32() % G_N_ELEMENTS(iface_data); + for (i = 0; i < order_len; i++) { + if (order_idx[i] == idx) + goto again_find_idx; + } + order_idx[order_len++] = idx; + + r->ifindex = iface_data[idx].ifindex; + g_assert( + NMTST_NM_ERR_SUCCESS(nm_platform_ip4_route_add(platform, NMP_NLM_FLAG_APPEND, r))); + } else { + i = nmtst_get_rand_uint32() % order_len; + idx = order_idx[i]; + for (i++; i < order_len; i++) + order_idx[i - 1] = order_idx[i]; + order_len--; + + r->ifindex = iface_data[idx].ifindex; + g_assert(nm_platform_object_delete(platform, &o)); + } + + head_entry = + nm_platform_lookup(platform, + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_IP4_ROUTE)); + for (j = 0; j < G_N_ELEMENTS(iface_data); j++) { + gboolean has; + NMDedupMultiIter iter; + const NMPObject *o_cached; + + has = FALSE; + for (k = 0; k < order_len; k++) { + if (order_idx[k] == j) { + g_assert(!has); + has = TRUE; + } + } + + nmp_cache_iter_for_each (&iter, head_entry, &o_cached) { + const NMPlatformIP4Route *r_cached = NMP_OBJECT_CAST_IP4_ROUTE(o_cached); + + if (r_cached->ifindex != iface_data[j].ifindex || r_cached->metric != 109) + continue; + + g_assert(has); + has = FALSE; + } + g_assert(!has); + } + } + + for (i = 0; i < G_N_ELEMENTS(iface_data); i++) + g_assert(nm_platform_link_delete(platform, iface_data[i].ifindex)); + + (void) TEST_IDX; + (void) IFINDEX; } /*****************************************************************************/ -#define FRA_SUPPRESS_IFGROUP 13 -#define FRA_SUPPRESS_PREFIXLEN 14 -#define FRA_L3MDEV 19 -#define FRA_UID_RANGE 20 -#define FRA_PROTOCOL 21 -#define FRA_IP_PROTO 22 -#define FRA_SPORT_RANGE 23 -#define FRA_DPORT_RANGE 24 +#define FRA_SUPPRESS_IFGROUP 13 +#define FRA_SUPPRESS_PREFIXLEN 14 +#define FRA_L3MDEV 19 +#define FRA_UID_RANGE 20 +#define FRA_PROTOCOL 21 +#define FRA_IP_PROTO 22 +#define FRA_SPORT_RANGE 23 +#define FRA_DPORT_RANGE 24 static const NMPObject * -_rule_find_by_priority (NMPlatform *platform, - guint32 priority) +_rule_find_by_priority(NMPlatform *platform, guint32 priority) { - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; - const NMPObject *o; - const NMPObject *obj = NULL; - NMPLookup lookup; - - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - head_entry = nm_platform_lookup (platform, &lookup); - nmp_cache_iter_for_each (&iter, head_entry, &o) { - if (NMP_OBJECT_CAST_ROUTING_RULE (o)->priority != priority) - continue; - g_assert (!obj); - obj = o; - } - return obj; + const NMDedupMultiHeadEntry *head_entry; + NMDedupMultiIter iter; + const NMPObject * o; + const NMPObject * obj = NULL; + NMPLookup lookup; + + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); + head_entry = nm_platform_lookup(platform, &lookup); + nmp_cache_iter_for_each (&iter, head_entry, &o) { + if (NMP_OBJECT_CAST_ROUTING_RULE(o)->priority != priority) + continue; + g_assert(!obj); + obj = o; + } + return obj; } static const NMPObject * -_rule_check_kernel_support_one (NMPlatform *platform, - const NMPlatformRoutingRule *rr) +_rule_check_kernel_support_one(NMPlatform *platform, const NMPlatformRoutingRule *rr) { - nm_auto_nmpobj const NMPObject *obj = NULL; - int r; + nm_auto_nmpobj const NMPObject *obj = NULL; + int r; - g_assert (!_rule_find_by_priority (platform, rr->priority)); + g_assert(!_rule_find_by_priority(platform, rr->priority)); - r = nm_platform_routing_rule_add (platform, NMP_NLM_FLAG_ADD, rr); - g_assert_cmpint (r, ==, 0); + r = nm_platform_routing_rule_add(platform, NMP_NLM_FLAG_ADD, rr); + g_assert_cmpint(r, ==, 0); - obj = nmp_object_ref (_rule_find_by_priority (platform, rr->priority)); - g_assert (obj); + obj = nmp_object_ref(_rule_find_by_priority(platform, rr->priority)); + g_assert(obj); - r = nm_platform_object_delete (platform, obj); - g_assert_cmpint (r, ==, TRUE); + r = nm_platform_object_delete(platform, obj); + g_assert_cmpint(r, ==, TRUE); - g_assert (!_rule_find_by_priority (platform, rr->priority)); + g_assert(!_rule_find_by_priority(platform, rr->priority)); - return g_steal_pointer (&obj); + return g_steal_pointer(&obj); } static gboolean -_rule_check_kernel_support (NMPlatform *platform, - int attribute) +_rule_check_kernel_support(NMPlatform *platform, int attribute) { - static int support[] = { - [FRA_SUPPRESS_IFGROUP] = 0, - [FRA_SUPPRESS_PREFIXLEN] = 0, - [FRA_L3MDEV] = 0, - [FRA_UID_RANGE] = 0, - [FRA_PROTOCOL] = 0, - [FRA_IP_PROTO] = 0, - [FRA_SPORT_RANGE] = 0, - [FRA_DPORT_RANGE] = 0, - }; - const guint32 PROBE_PRORITY = 12033; - gboolean sup; - int i; - - g_assert (NM_IS_PLATFORM (platform)); - - if (attribute == -1) { - for (i = 0; i < G_N_ELEMENTS (support); i++) { - if (support[i] < 0) { - /* indicate that some test was skipped. */ - return FALSE; - } - } - return TRUE; - } - - g_assert (attribute >= 0 && attribute < G_N_ELEMENTS (support)); - - if (support[attribute] != 0) - return support[attribute] >= 0; - - switch (attribute) { - case FRA_SUPPRESS_IFGROUP: { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformRoutingRule rr = { - .addr_family = AF_INET, - .priority = PROBE_PRORITY, - .suppress_ifgroup_inverse = ~((guint32) 1245), - }; - - obj = _rule_check_kernel_support_one (platform, &rr); - - sup = NMP_OBJECT_CAST_ROUTING_RULE (obj)->suppress_prefixlen_inverse == rr.suppress_ifgroup_inverse; - break; - } - case FRA_SUPPRESS_PREFIXLEN: { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformRoutingRule rr = { - .addr_family = AF_INET, - .priority = PROBE_PRORITY, - .suppress_prefixlen_inverse = ~((guint32) 1245), - }; - - obj = _rule_check_kernel_support_one (platform, &rr); - - sup = NMP_OBJECT_CAST_ROUTING_RULE (obj)->suppress_prefixlen_inverse == rr.suppress_prefixlen_inverse; - break; - } - case FRA_L3MDEV: { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformRoutingRule rr = { - .addr_family = AF_INET, - .priority = PROBE_PRORITY, - .l3mdev = TRUE, - }; - - obj = _rule_check_kernel_support_one (platform, &rr); - - sup = NMP_OBJECT_CAST_ROUTING_RULE (obj)->l3mdev != 0; - break; - } - case FRA_UID_RANGE: { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformRoutingRule rr = { - .addr_family = AF_INET, - .priority = PROBE_PRORITY, - .uid_range = { - .start = 0, - .end = 0, - }, - .uid_range_has = TRUE, - }; - - obj = _rule_check_kernel_support_one (platform, &rr); - - sup = NMP_OBJECT_CAST_ROUTING_RULE (obj)->uid_range_has; - break; - } - case FRA_PROTOCOL: { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformRoutingRule rr = { - .addr_family = AF_INET, - .priority = PROBE_PRORITY, - .protocol = 30, - }; - - obj = _rule_check_kernel_support_one (platform, &rr); - - sup = NMP_OBJECT_CAST_ROUTING_RULE (obj)->protocol == 30; - break; - } - case FRA_IP_PROTO: { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformRoutingRule rr = { - .addr_family = AF_INET, - .priority = PROBE_PRORITY, - .ip_proto = 30, - }; - - obj = _rule_check_kernel_support_one (platform, &rr); - - sup = NMP_OBJECT_CAST_ROUTING_RULE (obj)->ip_proto == 30; - break; - } - case FRA_SPORT_RANGE: - case FRA_DPORT_RANGE: - /* these were added at the same time as FRA_IP_PROTO. */ - sup = _rule_check_kernel_support (platform, FRA_IP_PROTO); - break; - default: - g_assert_not_reached (); - return FALSE; - } - - support[attribute] = sup ? 1 : -1; - - _LOGD ("kernel support for routing rule attribute #%d %s", attribute, sup ? "detected" : "not detected"); - return sup; + static int support[] = { + [FRA_SUPPRESS_IFGROUP] = 0, + [FRA_SUPPRESS_PREFIXLEN] = 0, + [FRA_L3MDEV] = 0, + [FRA_UID_RANGE] = 0, + [FRA_PROTOCOL] = 0, + [FRA_IP_PROTO] = 0, + [FRA_SPORT_RANGE] = 0, + [FRA_DPORT_RANGE] = 0, + }; + const guint32 PROBE_PRORITY = 12033; + gboolean sup; + int i; + + g_assert(NM_IS_PLATFORM(platform)); + + if (attribute == -1) { + for (i = 0; i < G_N_ELEMENTS(support); i++) { + if (support[i] < 0) { + /* indicate that some test was skipped. */ + return FALSE; + } + } + return TRUE; + } + + g_assert(attribute >= 0 && attribute < G_N_ELEMENTS(support)); + + if (support[attribute] != 0) + return support[attribute] >= 0; + + switch (attribute) { + case FRA_SUPPRESS_IFGROUP: + { + nm_auto_nmpobj const NMPObject *obj = NULL; + const NMPlatformRoutingRule rr = { + .addr_family = AF_INET, + .priority = PROBE_PRORITY, + .suppress_ifgroup_inverse = ~((guint32) 1245), + }; + + obj = _rule_check_kernel_support_one(platform, &rr); + + sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->suppress_prefixlen_inverse + == rr.suppress_ifgroup_inverse; + break; + } + case FRA_SUPPRESS_PREFIXLEN: + { + nm_auto_nmpobj const NMPObject *obj = NULL; + const NMPlatformRoutingRule rr = { + .addr_family = AF_INET, + .priority = PROBE_PRORITY, + .suppress_prefixlen_inverse = ~((guint32) 1245), + }; + + obj = _rule_check_kernel_support_one(platform, &rr); + + sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->suppress_prefixlen_inverse + == rr.suppress_prefixlen_inverse; + break; + } + case FRA_L3MDEV: + { + nm_auto_nmpobj const NMPObject *obj = NULL; + const NMPlatformRoutingRule rr = { + .addr_family = AF_INET, + .priority = PROBE_PRORITY, + .l3mdev = TRUE, + }; + + obj = _rule_check_kernel_support_one(platform, &rr); + + sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->l3mdev != 0; + break; + } + case FRA_UID_RANGE: + { + nm_auto_nmpobj const NMPObject *obj = NULL; + const NMPlatformRoutingRule rr = { + .addr_family = AF_INET, + .priority = PROBE_PRORITY, + .uid_range = + { + .start = 0, + .end = 0, + }, + .uid_range_has = TRUE, + }; + + obj = _rule_check_kernel_support_one(platform, &rr); + + sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->uid_range_has; + break; + } + case FRA_PROTOCOL: + { + nm_auto_nmpobj const NMPObject *obj = NULL; + const NMPlatformRoutingRule rr = { + .addr_family = AF_INET, + .priority = PROBE_PRORITY, + .protocol = 30, + }; + + obj = _rule_check_kernel_support_one(platform, &rr); + + sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->protocol == 30; + break; + } + case FRA_IP_PROTO: + { + nm_auto_nmpobj const NMPObject *obj = NULL; + const NMPlatformRoutingRule rr = { + .addr_family = AF_INET, + .priority = PROBE_PRORITY, + .ip_proto = 30, + }; + + obj = _rule_check_kernel_support_one(platform, &rr); + + sup = NMP_OBJECT_CAST_ROUTING_RULE(obj)->ip_proto == 30; + break; + } + case FRA_SPORT_RANGE: + case FRA_DPORT_RANGE: + /* these were added at the same time as FRA_IP_PROTO. */ + sup = _rule_check_kernel_support(platform, FRA_IP_PROTO); + break; + default: + g_assert_not_reached(); + return FALSE; + } + + support[attribute] = sup ? 1 : -1; + + _LOGD("kernel support for routing rule attribute #%d %s", + attribute, + sup ? "detected" : "not detected"); + return sup; } static const NMPObject * -_platform_has_routing_rule (NMPlatform *platform, - const NMPObject *obj) +_platform_has_routing_rule(NMPlatform *platform, const NMPObject *obj) { - const NMPObject *o; + const NMPObject *o; - g_assert (NM_IS_PLATFORM (platform)); - g_assert (NMP_OBJECT_IS_VALID (obj)); - g_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_ROUTING_RULE); + g_assert(NM_IS_PLATFORM(platform)); + g_assert(NMP_OBJECT_IS_VALID(obj)); + g_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_ROUTING_RULE); - o = nm_platform_lookup_obj (platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj); - if (o) - g_assert (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (obj), NMP_OBJECT_CAST_ROUTING_RULE (o), NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0); + o = nm_platform_lookup_obj(platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj); + if (o) + g_assert(nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(obj), + NMP_OBJECT_CAST_ROUTING_RULE(o), + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) + == 0); - return o; + return o; } static guint32 -_rr_rand_choose_u32 (guint32 p) +_rr_rand_choose_u32(guint32 p) { - /* mostly, we just return zero. We want that each rule only has few - * fields set -- having most fields at zero. */ - if ((p % 10000u) < 7500u) - return 0; + /* mostly, we just return zero. We want that each rule only has few + * fields set -- having most fields at zero. */ + if ((p % 10000u) < 7500u) + return 0; - /* give 0xFFFFFFFFu extra probability. */ - if ((p % 10000u) < 8250u) - return 0xFFFFFFFFu; + /* give 0xFFFFFFFFu extra probability. */ + if ((p % 10000u) < 8250u) + return 0xFFFFFFFFu; - /* choose a small number. */ - if ((p % 10000u) < 9125u) - return (~p) % 10; + /* choose a small number. */ + if ((p % 10000u) < 9125u) + return (~p) % 10; - /* finally, full random number. */ - return ~p; + /* finally, full random number. */ + return ~p; } -#define _rr_rand_choose_u8(p) ((guint8) _rr_rand_choose_u32 ((p))) +#define _rr_rand_choose_u8(p) ((guint8) _rr_rand_choose_u32((p))) static const NMPObject * -_rule_create_random (NMPlatform *platform) +_rule_create_random(NMPlatform *platform) { - NMPObject *obj; - NMPlatformRoutingRule *rr; - guint32 p; - int addr_size; - guint i; - char saddr[NM_UTILS_INET_ADDRSTRLEN]; - static struct { - guint32 uid; - guint32 euid; - bool initialized; - } uids; - - if (G_UNLIKELY (!uids.initialized)) { - uids.uid = getuid (); - uids.euid = geteuid (); - uids.initialized = TRUE; - } - - obj = nmp_object_new (NMP_OBJECT_TYPE_ROUTING_RULE, NULL); - rr = NMP_OBJECT_CAST_ROUTING_RULE (obj); - - rr->addr_family = nmtst_rand_select (AF_INET, AF_INET6); - - addr_size = nm_utils_addr_family_to_size (rr->addr_family); - - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 50) - rr->priority = 10000 + ((~p) % 20u); - - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 40) - nm_sprintf_buf (rr->iifname, "t-iif-%u", (~p) % 20); - else if ((p % 1000u) < 80) - nm_sprintf_buf (rr->iifname, "%s", DEVICE_NAME); - - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 40) - nm_sprintf_buf (rr->oifname, "t-oif-%d", (~p) % 20); - else if ((p % 1000u) < 80) - nm_sprintf_buf (rr->oifname, "%s", DEVICE_NAME); - - for (i = 0; i < 2; i++) { - NMIPAddr *p_addr = i ? &rr->src : &rr->dst; - guint8 *p_len = i ? &rr->src_len : &rr->dst_len; - - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 100) { - /* if we set src_len/dst_len to zero, the src/dst is actually ignored. - * - * For fuzzying, still set the address. It shall have no further effect. - * */ - *p_len = (~p) % (addr_size * 8 + 1); - p = nmtst_get_rand_uint32 (); - if ((p % 3u) == 0) { - if (rr->addr_family == AF_INET) - p_addr->addr4 = nmtst_inet4_from_string (nm_sprintf_buf (saddr, "192.192.5.%u", (~p) % 256u)); - else - p_addr->addr6 = *nmtst_inet6_from_string (nm_sprintf_buf (saddr, "1:2:3:4::f:%02x", (~p) % 256u)); - } else if ((p % 3u) == 1) - nmtst_rand_buf (NULL, p_addr, addr_size); - } - } - - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 50) - rr->tun_id = 10000 + ((~p) % 20); + NMPObject * obj; + NMPlatformRoutingRule *rr; + guint32 p; + int addr_size; + guint i; + char saddr[NM_UTILS_INET_ADDRSTRLEN]; + static struct { + guint32 uid; + guint32 euid; + bool initialized; + } uids; + + if (G_UNLIKELY(!uids.initialized)) { + uids.uid = getuid(); + uids.euid = geteuid(); + uids.initialized = TRUE; + } + + obj = nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, NULL); + rr = NMP_OBJECT_CAST_ROUTING_RULE(obj); + + rr->addr_family = nmtst_rand_select(AF_INET, AF_INET6); + + addr_size = nm_utils_addr_family_to_size(rr->addr_family); + + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 50) + rr->priority = 10000 + ((~p) % 20u); + + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 40) + nm_sprintf_buf(rr->iifname, "t-iif-%u", (~p) % 20); + else if ((p % 1000u) < 80) + nm_sprintf_buf(rr->iifname, "%s", DEVICE_NAME); + + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 40) + nm_sprintf_buf(rr->oifname, "t-oif-%d", (~p) % 20); + else if ((p % 1000u) < 80) + nm_sprintf_buf(rr->oifname, "%s", DEVICE_NAME); + + for (i = 0; i < 2; i++) { + NMIPAddr *p_addr = i ? &rr->src : &rr->dst; + guint8 * p_len = i ? &rr->src_len : &rr->dst_len; + + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 100) { + /* if we set src_len/dst_len to zero, the src/dst is actually ignored. + * + * For fuzzying, still set the address. It shall have no further effect. + * */ + *p_len = (~p) % (addr_size * 8 + 1); + p = nmtst_get_rand_uint32(); + if ((p % 3u) == 0) { + if (rr->addr_family == AF_INET) + p_addr->addr4 = + nmtst_inet4_from_string(nm_sprintf_buf(saddr, "192.192.5.%u", (~p) % 256u)); + else + p_addr->addr6 = *nmtst_inet6_from_string( + nm_sprintf_buf(saddr, "1:2:3:4::f:%02x", (~p) % 256u)); + } else if ((p % 3u) == 1) + nmtst_rand_buf(NULL, p_addr, addr_size); + } + } + + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 50) + rr->tun_id = 10000 + ((~p) % 20); again_action: - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 500) - rr->action = FR_ACT_UNSPEC; - else if ((p % 1000u) < 750) - rr->action = (~p) % 12u; - else - rr->action = (~p) % 0x100u; - - rr->priority = _rr_rand_choose_u32 (nmtst_get_rand_uint32 ()); - - if ( rr->action == FR_ACT_GOTO - && rr->priority == G_MAXINT32) - goto again_action; - - p = nmtst_get_rand_uint32 (); - if ((p % 10000u) < 100) - rr->goto_target = rr->priority + 1; - else - rr->goto_target = _rr_rand_choose_u32 (nmtst_get_rand_uint32 ()); - if ( rr->action == FR_ACT_GOTO - && rr->goto_target <= rr->priority) - goto again_action; - - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 25) { - if (_rule_check_kernel_support (platform, FRA_L3MDEV)) { - rr->l3mdev = TRUE; - rr->table = RT_TABLE_UNSPEC; - } - } + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 500) + rr->action = FR_ACT_UNSPEC; + else if ((p % 1000u) < 750) + rr->action = (~p) % 12u; + else + rr->action = (~p) % 0x100u; + + rr->priority = _rr_rand_choose_u32(nmtst_get_rand_uint32()); + + if (rr->action == FR_ACT_GOTO && rr->priority == G_MAXINT32) + goto again_action; + + p = nmtst_get_rand_uint32(); + if ((p % 10000u) < 100) + rr->goto_target = rr->priority + 1; + else + rr->goto_target = _rr_rand_choose_u32(nmtst_get_rand_uint32()); + if (rr->action == FR_ACT_GOTO && rr->goto_target <= rr->priority) + goto again_action; + + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 25) { + if (_rule_check_kernel_support(platform, FRA_L3MDEV)) { + rr->l3mdev = TRUE; + rr->table = RT_TABLE_UNSPEC; + } + } again_table: - if (!rr->l3mdev) { - p = nmtst_get_rand_uint32 (); - if ((p % 1000u) < 700) - rr->table = RT_TABLE_UNSPEC; - else if ((p % 1000u) < 850) - rr->table = RT_TABLE_MAIN; - else - rr->table = 10000 + ((~p) % 10); - if ( rr->action == FR_ACT_TO_TBL - && rr->table == RT_TABLE_UNSPEC) - goto again_table; - } - - rr->fwmark = _rr_rand_choose_u32 (nmtst_get_rand_uint32 ()); - rr->fwmask = _rr_rand_choose_u32 (nmtst_get_rand_uint32 ()); - - rr->flow = _rr_rand_choose_u32 (nmtst_get_rand_uint32 ()); - - if (_rule_check_kernel_support (platform, FRA_PROTOCOL)) - rr->protocol = _rr_rand_choose_u8 (nmtst_get_rand_uint32 ()); + if (!rr->l3mdev) { + p = nmtst_get_rand_uint32(); + if ((p % 1000u) < 700) + rr->table = RT_TABLE_UNSPEC; + else if ((p % 1000u) < 850) + rr->table = RT_TABLE_MAIN; + else + rr->table = 10000 + ((~p) % 10); + if (rr->action == FR_ACT_TO_TBL && rr->table == RT_TABLE_UNSPEC) + goto again_table; + } + + rr->fwmark = _rr_rand_choose_u32(nmtst_get_rand_uint32()); + rr->fwmask = _rr_rand_choose_u32(nmtst_get_rand_uint32()); + + rr->flow = _rr_rand_choose_u32(nmtst_get_rand_uint32()); + + if (_rule_check_kernel_support(platform, FRA_PROTOCOL)) + rr->protocol = _rr_rand_choose_u8(nmtst_get_rand_uint32()); #define IPTOS_TOS_MASK 0x1E again_tos: - rr->tos = _rr_rand_choose_u8 (nmtst_get_rand_uint32 ()); - if ( rr->addr_family == AF_INET - && rr->tos & ~IPTOS_TOS_MASK) - goto again_tos; + rr->tos = _rr_rand_choose_u8(nmtst_get_rand_uint32()); + if (rr->addr_family == AF_INET && rr->tos & ~IPTOS_TOS_MASK) + goto again_tos; - if (_rule_check_kernel_support (platform, FRA_IP_PROTO)) - rr->ip_proto = _rr_rand_choose_u8 (nmtst_get_rand_uint32 ()); + if (_rule_check_kernel_support(platform, FRA_IP_PROTO)) + rr->ip_proto = _rr_rand_choose_u8(nmtst_get_rand_uint32()); - if (_rule_check_kernel_support (platform, FRA_SUPPRESS_PREFIXLEN)) - rr->suppress_prefixlen_inverse = ~_rr_rand_choose_u32 (nmtst_get_rand_uint32 ()); + if (_rule_check_kernel_support(platform, FRA_SUPPRESS_PREFIXLEN)) + rr->suppress_prefixlen_inverse = ~_rr_rand_choose_u32(nmtst_get_rand_uint32()); - if (_rule_check_kernel_support (platform, FRA_SUPPRESS_IFGROUP)) - rr->suppress_ifgroup_inverse = ~_rr_rand_choose_u32 (nmtst_get_rand_uint32 ()); + if (_rule_check_kernel_support(platform, FRA_SUPPRESS_IFGROUP)) + rr->suppress_ifgroup_inverse = ~_rr_rand_choose_u32(nmtst_get_rand_uint32()); - if (_rule_check_kernel_support (platform, FRA_UID_RANGE)) { - p = nmtst_get_rand_uint32 (); - rr->uid_range_has = (p % 10000u) < 200; - } + if (_rule_check_kernel_support(platform, FRA_UID_RANGE)) { + p = nmtst_get_rand_uint32(); + rr->uid_range_has = (p % 10000u) < 200; + } again_uid_range: - rr->uid_range.start = nmtst_rand_select (0u, uids.uid, uids.euid); - rr->uid_range.end = nmtst_rand_select (0u, uids.uid, uids.euid); - if (rr->uid_range_has) { - if (rr->uid_range.end < rr->uid_range.start) - NM_SWAP (rr->uid_range.start, rr->uid_range.end); - if ( rr->uid_range.start == ((guint32) -1) - || rr->uid_range.end == ((guint32) -1)) - goto again_uid_range; - } - - for (i = 0; i < 2; i++) { - NMFibRulePortRange *range = i ? &rr->sport_range : &rr->dport_range; - int attribute = i ? FRA_SPORT_RANGE : FRA_DPORT_RANGE; - - if (!_rule_check_kernel_support (platform, attribute)) - continue; - - p = nmtst_get_rand_uint32 (); - if ((p % 10000u) < 300) { - while (range->start == 0) { - p = p ^ nmtst_get_rand_uint32 (); - range->start = nmtst_rand_select (1u, 0xFFFEu, ((p ) % 0xFFFEu) + 1); - range->end = nmtst_rand_select (1u, 0xFFFEu, ((p >> 16) % 0xFFFEu) + 1, range->start); - if (range->end < range->start) - NM_SWAP (range->start, range->end); - } - } - } - - p = nmtst_get_rand_uint32 () % 1000u; - if (p < 100) - rr->flags |= FIB_RULE_INVERT; - - return obj; + rr->uid_range.start = nmtst_rand_select(0u, uids.uid, uids.euid); + rr->uid_range.end = nmtst_rand_select(0u, uids.uid, uids.euid); + if (rr->uid_range_has) { + if (rr->uid_range.end < rr->uid_range.start) + NM_SWAP(&rr->uid_range.start, &rr->uid_range.end); + if (rr->uid_range.start == ((guint32) -1) || rr->uid_range.end == ((guint32) -1)) + goto again_uid_range; + } + + for (i = 0; i < 2; i++) { + NMFibRulePortRange *range = i ? &rr->sport_range : &rr->dport_range; + int attribute = i ? FRA_SPORT_RANGE : FRA_DPORT_RANGE; + + if (!_rule_check_kernel_support(platform, attribute)) + continue; + + p = nmtst_get_rand_uint32(); + if ((p % 10000u) < 300) { + while (range->start == 0) { + p = p ^ nmtst_get_rand_uint32(); + range->start = nmtst_rand_select(1u, 0xFFFEu, ((p) % 0xFFFEu) + 1); + range->end = + nmtst_rand_select(1u, 0xFFFEu, ((p >> 16) % 0xFFFEu) + 1, range->start); + if (range->end < range->start) + NM_SWAP(&range->start, &range->end); + } + } + } + + p = nmtst_get_rand_uint32() % 1000u; + if (p < 100) + rr->flags |= FIB_RULE_INVERT; + + return obj; } static gboolean -_rule_fuzzy_equal (const NMPObject *obj, - const NMPObject *obj_comp, - int op_type) +_rule_fuzzy_equal(const NMPObject *obj, const NMPObject *obj_comp, int op_type) { - const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (obj); - NMPlatformRoutingRule rr_co = *NMP_OBJECT_CAST_ROUTING_RULE (obj_comp); - - switch (op_type) { - case RTM_NEWRULE: - /* when adding rules with RTM_NEWRULE, kernel checks whether an existing - * rule already exists and may fail with EEXIST. This check has issues - * and reject legitimate rules (rh#1686075). - * - * Work around that. */ - if (rr->src_len == 0) - rr_co.src_len = 0; - if (rr->dst_len == 0) - rr_co.dst_len = 0; - if (rr->flow == 0) - rr_co.flow = 0; - if (rr->tos == 0) - rr_co.tos = 0; - rr_co.suppress_prefixlen_inverse = rr->suppress_prefixlen_inverse; - rr_co.suppress_ifgroup_inverse = rr->suppress_ifgroup_inverse; - if (!NM_FLAGS_HAS (rr->flags, FIB_RULE_INVERT)) - rr_co.flags &= ~((guint32) FIB_RULE_INVERT); - else - rr_co.flags |= ((guint32) FIB_RULE_INVERT); - break; - case RTM_DELRULE: - /* when deleting a rule with RTM_DELRULE, kernel tries to find the - * cadidate to delete. It might delete the wrong rule (rh#1685816). */ - if (rr->action == FR_ACT_UNSPEC) - rr_co.action = FR_ACT_UNSPEC; - if (rr->iifname[0] == '\0') - rr_co.iifname[0] = '\0'; - if (rr->oifname[0] == '\0') - rr_co.oifname[0] = '\0'; - if (rr->src_len == 0) - rr_co.src_len = 0; - if (rr->dst_len == 0) - rr_co.dst_len = 0; - if (rr->tun_id == 0) - rr_co.tun_id = 0; - if (rr->fwmark == 0) - rr_co.fwmark = 0; - if (rr->fwmask == 0) - rr_co.fwmask = 0; - if (rr->flow == 0) - rr_co.flow = 0; - if (rr->protocol == 0) - rr_co.protocol = 0; - if (rr->table == RT_TABLE_UNSPEC) - rr_co.table = RT_TABLE_UNSPEC; - if (rr->l3mdev == 0) - rr_co.l3mdev = 0; - if (rr->tos == 0) - rr_co.tos = 0; - if (rr->ip_proto == 0) - rr_co.ip_proto = 0; - rr_co.suppress_prefixlen_inverse = rr->suppress_prefixlen_inverse; - if (rr->suppress_ifgroup_inverse == 0) - rr_co.suppress_ifgroup_inverse = 0; - if (!rr->uid_range_has) - rr_co.uid_range_has = FALSE; - if (rr->sport_range.start == 0 && rr->sport_range.end == 0) { - rr_co.sport_range.start = 0; - rr_co.sport_range.end = 0; - } - if (rr->dport_range.start == 0 && rr->dport_range.end == 0) { - rr_co.dport_range.start = 0; - rr_co.dport_range.end = 0; - } - if (!NM_FLAGS_HAS (rr->flags, FIB_RULE_INVERT)) - rr_co.flags &= ~((guint32) FIB_RULE_INVERT); - else - rr_co.flags |= ((guint32) FIB_RULE_INVERT); - break; - default: - g_assert_not_reached (); - break; - } - - return nm_platform_routing_rule_cmp (rr, &rr_co, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0; + const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE(obj); + NMPlatformRoutingRule rr_co = *NMP_OBJECT_CAST_ROUTING_RULE(obj_comp); + + switch (op_type) { + case RTM_NEWRULE: + /* when adding rules with RTM_NEWRULE, kernel checks whether an existing + * rule already exists and may fail with EEXIST. This check has issues + * and reject legitimate rules (rh#1686075). + * + * Work around that. */ + if (rr->src_len == 0) + rr_co.src_len = 0; + if (rr->dst_len == 0) + rr_co.dst_len = 0; + if (rr->flow == 0) + rr_co.flow = 0; + if (rr->tos == 0) + rr_co.tos = 0; + rr_co.suppress_prefixlen_inverse = rr->suppress_prefixlen_inverse; + rr_co.suppress_ifgroup_inverse = rr->suppress_ifgroup_inverse; + if (!NM_FLAGS_HAS(rr->flags, FIB_RULE_INVERT)) + rr_co.flags &= ~((guint32) FIB_RULE_INVERT); + else + rr_co.flags |= ((guint32) FIB_RULE_INVERT); + break; + case RTM_DELRULE: + /* when deleting a rule with RTM_DELRULE, kernel tries to find the + * candidate to delete. It might delete the wrong rule (rh#1685816). */ + if (rr->action == FR_ACT_UNSPEC) + rr_co.action = FR_ACT_UNSPEC; + if (rr->iifname[0] == '\0') + rr_co.iifname[0] = '\0'; + if (rr->oifname[0] == '\0') + rr_co.oifname[0] = '\0'; + if (rr->src_len == 0) + rr_co.src_len = 0; + if (rr->dst_len == 0) + rr_co.dst_len = 0; + if (rr->tun_id == 0) + rr_co.tun_id = 0; + if (rr->fwmark == 0) + rr_co.fwmark = 0; + if (rr->fwmask == 0) + rr_co.fwmask = 0; + if (rr->flow == 0) + rr_co.flow = 0; + if (rr->protocol == 0) + rr_co.protocol = 0; + if (rr->table == RT_TABLE_UNSPEC) + rr_co.table = RT_TABLE_UNSPEC; + if (rr->l3mdev == 0) + rr_co.l3mdev = 0; + if (rr->tos == 0) + rr_co.tos = 0; + if (rr->ip_proto == 0) + rr_co.ip_proto = 0; + rr_co.suppress_prefixlen_inverse = rr->suppress_prefixlen_inverse; + if (rr->suppress_ifgroup_inverse == 0) + rr_co.suppress_ifgroup_inverse = 0; + if (!rr->uid_range_has) + rr_co.uid_range_has = FALSE; + if (rr->sport_range.start == 0 && rr->sport_range.end == 0) { + rr_co.sport_range.start = 0; + rr_co.sport_range.end = 0; + } + if (rr->dport_range.start == 0 && rr->dport_range.end == 0) { + rr_co.dport_range.start = 0; + rr_co.dport_range.end = 0; + } + if (!NM_FLAGS_HAS(rr->flags, FIB_RULE_INVERT)) + rr_co.flags &= ~((guint32) FIB_RULE_INVERT); + else + rr_co.flags |= ((guint32) FIB_RULE_INVERT); + break; + default: + g_assert_not_reached(); + break; + } + + return nm_platform_routing_rule_cmp(rr, &rr_co, NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0; } static void -test_rule (gconstpointer test_data) +test_rule(gconstpointer test_data) { - const int TEST_IDX = GPOINTER_TO_INT (test_data); - const gboolean TEST_SYNC = (TEST_IDX == 4); - gs_unref_ptrarray GPtrArray *objs = NULL; - gs_unref_ptrarray GPtrArray *objs_initial = NULL; - NMPlatform *platform = NM_PLATFORM_GET; - guint i, j, n; - int r; - gboolean had_an_issue_exist = FALSE; - - nm_platform_process_events (platform); - - objs_initial = nmtstp_platform_routing_rules_get_all (platform, AF_UNSPEC); - g_assert (objs_initial); - g_assert_cmpint (objs_initial->len, ==, 5); - - nmtstp_run_command_check ("ip rule add table 766"); - nm_platform_process_events (platform); - - for (i = 6; i > 0; i--) { - gs_unref_ptrarray GPtrArray *objs_extern = NULL; - const NMPObject *obj; - - objs_extern = nmtstp_platform_routing_rules_get_all (platform, AF_UNSPEC); - - g_assert (objs_extern); - g_assert_cmpint (objs_extern->len, ==, i); - - if (TEST_IDX != 1) - nmtst_rand_perm (NULL, objs_extern->pdata, NULL, sizeof (gpointer), objs_extern->len); - - obj = objs_extern->pdata[0]; - - r = nm_platform_object_delete (platform, obj); - g_assert_cmpint (r, ==, TRUE); - - g_assert (!_platform_has_routing_rule (platform, obj)); - } - - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, 0); - -#define RR(...) \ - nmp_object_new (NMP_OBJECT_TYPE_ROUTING_RULE, \ - (const NMPlatformObject *) &((NMPlatformRoutingRule) { \ - __VA_ARGS__ \ - })) - - objs = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET, - .priority = 10, - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET, - .priority = 400, - .action = FR_ACT_GOTO, - .goto_target = 10000, - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET6, - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET6, - .action = FR_ACT_TO_TBL, - .table = RT_TABLE_MAIN, - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET6, - .priority = 30, - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET6, - .priority = 50, - .iifname = "t-iif-1", - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET6, - .priority = 50, - .iifname = "t-oif-1", - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET, - .priority = 50, - .iifname = "t-oif-2", - )); - - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET, - .priority = 51, - .iifname = DEVICE_NAME, - )); - - if (TEST_IDX == 1) { - g_ptr_array_add (objs, RR ( - .addr_family = AF_INET, - .table = 10000, - )); - } - - if (TEST_IDX != 1) { - nmtst_rand_perm (NULL, objs->pdata, NULL, sizeof (gpointer), objs->len); - g_ptr_array_set_size (objs, nmtst_get_rand_uint32 () % (objs->len + 1)); - } - - n = (TEST_IDX != 1) ? nmtst_get_rand_uint32 () % 50u : 0u; - for (i = 0; i < n; i++) { - nm_auto_nmpobj const NMPObject *o = NULL; - guint try = 0; + const int TEST_IDX = GPOINTER_TO_INT(test_data); + const gboolean TEST_SYNC = (TEST_IDX == 4); + gs_unref_ptrarray GPtrArray *objs = NULL; + gs_unref_ptrarray GPtrArray *objs_initial = NULL; + NMPlatform * platform = NM_PLATFORM_GET; + guint i, j, n; + int r; + gboolean had_an_issue_exist = FALSE; + + nm_platform_process_events(platform); + + objs_initial = nmtstp_platform_routing_rules_get_all(platform, AF_UNSPEC); + g_assert(objs_initial); + g_assert_cmpint(objs_initial->len, ==, 5); + + nmtstp_run_command_check("ip rule add table 766"); + nm_platform_process_events(platform); + + for (i = 6; i > 0; i--) { + gs_unref_ptrarray GPtrArray *objs_extern = NULL; + const NMPObject * obj; + + objs_extern = nmtstp_platform_routing_rules_get_all(platform, AF_UNSPEC); + + g_assert(objs_extern); + g_assert_cmpint(objs_extern->len, ==, i); + + if (TEST_IDX != 1) + nmtst_rand_perm(NULL, objs_extern->pdata, NULL, sizeof(gpointer), objs_extern->len); + + obj = objs_extern->pdata[0]; + + r = nm_platform_object_delete(platform, obj); + g_assert_cmpint(r, ==, TRUE); + + g_assert(!_platform_has_routing_rule(platform, obj)); + } + + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), ==, 0); + +#define RR(...) \ + nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, \ + (const NMPlatformObject *) &((NMPlatformRoutingRule){__VA_ARGS__})) + + objs = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + + g_ptr_array_add(objs, RR(.addr_family = AF_INET, .priority = 10, )); + + g_ptr_array_add( + objs, + RR(.addr_family = AF_INET, .priority = 400, .action = FR_ACT_GOTO, .goto_target = 10000, )); + + g_ptr_array_add(objs, RR(.addr_family = AF_INET6, )); + + g_ptr_array_add(objs, + RR(.addr_family = AF_INET6, .action = FR_ACT_TO_TBL, .table = RT_TABLE_MAIN, )); + + g_ptr_array_add(objs, RR(.addr_family = AF_INET6, .priority = 30, )); + + g_ptr_array_add(objs, RR(.addr_family = AF_INET6, .priority = 50, .iifname = "t-iif-1", )); + + g_ptr_array_add(objs, RR(.addr_family = AF_INET6, .priority = 50, .iifname = "t-oif-1", )); + + g_ptr_array_add(objs, RR(.addr_family = AF_INET, .priority = 50, .iifname = "t-oif-2", )); + + g_ptr_array_add(objs, RR(.addr_family = AF_INET, .priority = 51, .iifname = DEVICE_NAME, )); + + if (TEST_IDX == 1) { + g_ptr_array_add(objs, RR(.addr_family = AF_INET, .table = 10000, )); + } + + if (TEST_IDX != 1) { + nmtst_rand_perm(NULL, objs->pdata, NULL, sizeof(gpointer), objs->len); + g_ptr_array_set_size(objs, nmtst_get_rand_uint32() % (objs->len + 1)); + } + + n = (TEST_IDX != 1) ? nmtst_get_rand_uint32() % 50u : 0u; + for (i = 0; i < n; i++) { + nm_auto_nmpobj const NMPObject *o = NULL; + guint try = 0; again: - o = _rule_create_random (platform); - for (j = 0; j < objs->len; j++) { - if (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (o), - NMP_OBJECT_CAST_ROUTING_RULE (objs->pdata[j]), - NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0) { - try++; - g_assert (try < 200); - nm_clear_pointer (&o, nmp_object_unref); - goto again; - } - } - g_ptr_array_add (objs, (gpointer) g_steal_pointer (&o)); - } - - if (TEST_IDX != 1) - nmtst_rand_perm (NULL, objs->pdata, NULL, sizeof (gpointer), objs->len); - - if (TEST_SYNC) { - gs_unref_hashtable GHashTable *unique_priorities = g_hash_table_new (NULL, NULL); - nm_auto_unref_rules_manager NMPRulesManager *rules_manager = nmp_rules_manager_new (platform); - gs_unref_ptrarray GPtrArray *objs_sync = NULL; - gconstpointer USER_TAG_1 = &platform; - gconstpointer USER_TAG_2 = &unique_priorities; - - objs_sync = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - - /* ensure that priorities are unique. Otherwise it confuses the test, because - * kernel may wrongly be unable to add/delete routes based on a wrong match - * (rh#1685816, rh#1685816). */ - for (i = 0; i < objs->len; i++) { - const NMPObject *obj = objs->pdata[i]; - guint32 prio = NMP_OBJECT_CAST_ROUTING_RULE (obj)->priority; - - if ( !NM_IN_SET (prio, 0, 32766, 32767) - && !g_hash_table_contains (unique_priorities, GUINT_TO_POINTER (prio))) { - g_hash_table_add (unique_priorities, GUINT_TO_POINTER (prio)); - g_ptr_array_add (objs_sync, (gpointer) nmp_object_ref (obj)); - } - } - - for (i = 0; i < objs_sync->len; i++) { - nmp_rules_manager_track (rules_manager, - NMP_OBJECT_CAST_ROUTING_RULE (objs_sync->pdata[i]), - 1, - USER_TAG_1, - NULL); - if (nmtst_get_rand_bool ()) { - /* this has no effect, because a negative priority (of same absolute value) - * has lower priority than the positive priority above. */ - nmp_rules_manager_track (rules_manager, - NMP_OBJECT_CAST_ROUTING_RULE (objs_sync->pdata[i]), - -1, - USER_TAG_2, - NULL); - } - if (nmtst_get_rand_uint32 () % objs_sync->len == 0) { - nmp_rules_manager_sync (rules_manager, FALSE); - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, i + 1); - } - } - - nmp_rules_manager_sync (rules_manager, FALSE); - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs_sync->len); - - for (i = 0; i < objs_sync->len; i++) { - switch (nmtst_get_rand_uint32 () % 3) { - case 0: - nmp_rules_manager_untrack (rules_manager, - NMP_OBJECT_CAST_ROUTING_RULE (objs_sync->pdata[i]), - USER_TAG_1); - nmp_rules_manager_untrack (rules_manager, - NMP_OBJECT_CAST_ROUTING_RULE (objs_sync->pdata[i]), - USER_TAG_1); - break; - case 1: - nmp_rules_manager_track (rules_manager, - NMP_OBJECT_CAST_ROUTING_RULE (objs_sync->pdata[i]), - -1, - USER_TAG_1, - NULL); - break; - case 2: - nmp_rules_manager_track (rules_manager, - NMP_OBJECT_CAST_ROUTING_RULE (objs_sync->pdata[i]), - -2, - USER_TAG_2, - NULL); - break; - } - if (nmtst_get_rand_uint32 () % objs_sync->len == 0) { - nmp_rules_manager_sync (rules_manager, FALSE); - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs_sync->len - i - 1); - } - } - - nmp_rules_manager_sync (rules_manager, FALSE); - - } else { - for (i = 0; i < objs->len;) { - const NMPObject *obj = objs->pdata[i]; - - for (j = 0; j < objs->len; j++) - g_assert ((j < i) == (!!_platform_has_routing_rule (platform, objs->pdata[j]))); - - r = nm_platform_routing_rule_add (platform, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_ROUTING_RULE (obj)); - - if (r == -EEXIST) { - g_assert (!_platform_has_routing_rule (platform, obj)); - /* this should not happen, but there are bugs in kernel (rh#1686075). */ - for (j = 0; j < i; j++) { - const NMPObject *obj2 = objs->pdata[j]; - - g_assert (_platform_has_routing_rule (platform, obj2)); - - if (_rule_fuzzy_equal (obj, obj2, RTM_NEWRULE)) { - r = 0; - break; - } - } - if (r == 0) { - /* OK, the rule is shadowed by another rule, and kernel does not allow - * us to add this one (rh#1686075). Drop this from the test. */ - g_ptr_array_remove_index (objs, i); - had_an_issue_exist = TRUE; - continue; - } - } - - if (r != 0) { - NMPLookup lookup; - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter iter; - const NMPObject *o; - - g_print (">>> failing... errno=%d, rule=%s\n", r, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); - - nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); - head_entry = nm_platform_lookup (platform, &lookup); - nmp_cache_iter_for_each (&iter, head_entry, &o) { - char ch = ' '; - - if ( NMP_OBJECT_CAST_ROUTING_RULE (o)->addr_family == NMP_OBJECT_CAST_ROUTING_RULE (obj)->addr_family - && NMP_OBJECT_CAST_ROUTING_RULE (o)->priority == NMP_OBJECT_CAST_ROUTING_RULE (obj)->priority) - ch = '*'; - g_print (">>> existing rule: %c %s\n", ch, nmp_object_to_string (o, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); - } - - nmtstp_run_command_check ("ip rule"); - nmtstp_run_command_check ("ip -6 rule"); - g_assert_cmpint (r, ==, 0); - } - - g_assert (_platform_has_routing_rule (platform, obj)); - - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, i + 1); - - i++; - } - - if (TEST_IDX != 1) - nmtst_rand_perm (NULL, objs->pdata, NULL, sizeof (gpointer), objs->len); - - if (_LOGD_ENABLED ()) { - nmtstp_run_command_check ("ip rule"); - nmtstp_run_command_check ("ip -6 rule"); - } - - for (i = 0; i < objs->len; i++) { - const NMPObject *obj = objs->pdata[i]; - const NMPObject *obj2; - - for (j = 0; j < objs->len; j++) - g_assert ((j < i) == (!_platform_has_routing_rule (platform, objs->pdata[j]))); - - g_assert (_platform_has_routing_rule (platform, obj)); - - r = nm_platform_object_delete (platform, obj); - g_assert_cmpint (r, ==, TRUE); - - obj2 = _platform_has_routing_rule (platform, obj); - - if (obj2) { - guint k; - - /* When deleting a rule, kernel does a fuzzy match, ignoring for example: - * - action, if it is FR_ACT_UNSPEC - * - iifname,oifname if it is unspecified - * rh#1685816 - * - * That means, we may have deleted the wrong rule. Which one? */ - k = i; - for (j = i + 1; j < objs->len; j++) { - if (!_platform_has_routing_rule (platform, objs->pdata[j])) { - g_assert_cmpint (k, ==, i); - k = j; - } - } - g_assert_cmpint (k, >, i); - - if (!_rule_fuzzy_equal (obj, objs->pdata[k], RTM_DELRULE)) { - g_print (">>> failing...\n"); - g_print (">>> no fuzzy match between: %s\n", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); - g_print (">>> and: %s\n", nmp_object_to_string (objs->pdata[k], NMP_OBJECT_TO_STRING_ALL, NULL, 0)); - g_assert_not_reached (); - } - - objs->pdata[i] = objs->pdata[k]; - objs->pdata[k] = (gpointer) obj; - obj2 = NULL; - } - - g_assert (!obj2); - - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs->len -i - 1); - } - } - - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, 0); - - for (i = 0; i < objs_initial->len; i++) { - const NMPObject *obj = objs_initial->pdata[i]; - - for (j = 0; j < objs_initial->len; j++) - g_assert ((j < i) == (!!_platform_has_routing_rule (platform, objs_initial->pdata[j]))); - - r = nm_platform_routing_rule_add (platform, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_ROUTING_RULE (obj)); - g_assert_cmpint (r, ==, 0); - } - for (j = 0; j < objs_initial->len; j++) - g_assert (_platform_has_routing_rule (platform, objs_initial->pdata[j])); - g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs_initial->len); - - /* the tests passed as good as we could (as good as we implemented workarounds for them). - * Still, with this kernel, not all features were fully tested. Mark the test as skipped. */ - if (had_an_issue_exist) - g_test_skip ("adding a rule failed with EEXIST although it should not (rh#1686075)"); - else if (!_rule_check_kernel_support (platform, -1)) - g_test_skip ("some kernel features were not available and skipped for the test"); + o = _rule_create_random(platform); + for (j = 0; j < objs->len; j++) { + if (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(o), + NMP_OBJECT_CAST_ROUTING_RULE(objs->pdata[j]), + NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) + == 0) { + try++; + g_assert(try < 200); + nm_clear_pointer(&o, nmp_object_unref); + goto again; + } + } + g_ptr_array_add(objs, (gpointer) g_steal_pointer(&o)); + } + + if (TEST_IDX != 1) + nmtst_rand_perm(NULL, objs->pdata, NULL, sizeof(gpointer), objs->len); + + if (TEST_SYNC) { + gs_unref_hashtable GHashTable *unique_priorities = g_hash_table_new(NULL, NULL); + nm_auto_unref_rules_manager NMPRulesManager *rules_manager = + nmp_rules_manager_new(platform); + gs_unref_ptrarray GPtrArray *objs_sync = NULL; + gconstpointer USER_TAG_1 = &platform; + gconstpointer USER_TAG_2 = &unique_priorities; + + objs_sync = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + + /* ensure that priorities are unique. Otherwise, it confuses the test, because + * kernel may wrongly be unable to add/delete routes based on a wrong match + * (rh#1685816, rh#1685816). */ + for (i = 0; i < objs->len; i++) { + const NMPObject *obj = objs->pdata[i]; + guint32 prio = NMP_OBJECT_CAST_ROUTING_RULE(obj)->priority; + + if (!NM_IN_SET(prio, 0, 32766, 32767) + && !g_hash_table_contains(unique_priorities, GUINT_TO_POINTER(prio))) { + g_hash_table_add(unique_priorities, GUINT_TO_POINTER(prio)); + g_ptr_array_add(objs_sync, (gpointer) nmp_object_ref(obj)); + } + } + + for (i = 0; i < objs_sync->len; i++) { + nmp_rules_manager_track(rules_manager, + NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]), + 1, + USER_TAG_1, + NULL); + if (nmtst_get_rand_bool()) { + /* this has no effect, because a negative priority (of same absolute value) + * has lower priority than the positive priority above. */ + nmp_rules_manager_track(rules_manager, + NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]), + -1, + USER_TAG_2, + NULL); + } + if (nmtst_get_rand_uint32() % objs_sync->len == 0) { + nmp_rules_manager_sync(rules_manager, FALSE); + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), + ==, + i + 1); + } + } + + nmp_rules_manager_sync(rules_manager, FALSE); + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), + ==, + objs_sync->len); + + for (i = 0; i < objs_sync->len; i++) { + switch (nmtst_get_rand_uint32() % 3) { + case 0: + nmp_rules_manager_untrack(rules_manager, + NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]), + USER_TAG_1); + nmp_rules_manager_untrack(rules_manager, + NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]), + USER_TAG_1); + break; + case 1: + nmp_rules_manager_track(rules_manager, + NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]), + -1, + USER_TAG_1, + NULL); + break; + case 2: + nmp_rules_manager_track(rules_manager, + NMP_OBJECT_CAST_ROUTING_RULE(objs_sync->pdata[i]), + -2, + USER_TAG_2, + NULL); + break; + } + if (nmtst_get_rand_uint32() % objs_sync->len == 0) { + nmp_rules_manager_sync(rules_manager, FALSE); + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), + ==, + objs_sync->len - i - 1); + } + } + + nmp_rules_manager_sync(rules_manager, FALSE); + + } else { + for (i = 0; i < objs->len;) { + const NMPObject *obj = objs->pdata[i]; + + for (j = 0; j < objs->len; j++) + g_assert((j < i) == (!!_platform_has_routing_rule(platform, objs->pdata[j]))); + + r = nm_platform_routing_rule_add(platform, + NMP_NLM_FLAG_ADD, + NMP_OBJECT_CAST_ROUTING_RULE(obj)); + + if (r == -EEXIST) { + g_assert(!_platform_has_routing_rule(platform, obj)); + /* this should not happen, but there are bugs in kernel (rh#1686075). */ + for (j = 0; j < i; j++) { + const NMPObject *obj2 = objs->pdata[j]; + + g_assert(_platform_has_routing_rule(platform, obj2)); + + if (_rule_fuzzy_equal(obj, obj2, RTM_NEWRULE)) { + r = 0; + break; + } + } + if (r == 0) { + /* OK, the rule is shadowed by another rule, and kernel does not allow + * us to add this one (rh#1686075). Drop this from the test. */ + g_ptr_array_remove_index(objs, i); + had_an_issue_exist = TRUE; + continue; + } + } + + if (r != 0) { + NMPLookup lookup; + const NMDedupMultiHeadEntry *head_entry; + NMDedupMultiIter iter; + const NMPObject * o; + + g_print(">>> failing... errno=%d, rule=%s\n", + r, + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + + nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE); + head_entry = nm_platform_lookup(platform, &lookup); + nmp_cache_iter_for_each (&iter, head_entry, &o) { + char ch = ' '; + + if (NMP_OBJECT_CAST_ROUTING_RULE(o)->addr_family + == NMP_OBJECT_CAST_ROUTING_RULE(obj)->addr_family + && NMP_OBJECT_CAST_ROUTING_RULE(o)->priority + == NMP_OBJECT_CAST_ROUTING_RULE(obj)->priority) + ch = '*'; + g_print(">>> existing rule: %c %s\n", + ch, + nmp_object_to_string(o, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + } + + nmtstp_run_command_check("ip rule"); + nmtstp_run_command_check("ip -6 rule"); + g_assert_cmpint(r, ==, 0); + } + + g_assert(_platform_has_routing_rule(platform, obj)); + + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), + ==, + i + 1); + + i++; + } + + if (TEST_IDX != 1) + nmtst_rand_perm(NULL, objs->pdata, NULL, sizeof(gpointer), objs->len); + + if (_LOGD_ENABLED()) { + nmtstp_run_command_check("ip rule"); + nmtstp_run_command_check("ip -6 rule"); + } + + for (i = 0; i < objs->len; i++) { + const NMPObject *obj = objs->pdata[i]; + const NMPObject *obj2; + + for (j = 0; j < objs->len; j++) + g_assert((j < i) == (!_platform_has_routing_rule(platform, objs->pdata[j]))); + + g_assert(_platform_has_routing_rule(platform, obj)); + + r = nm_platform_object_delete(platform, obj); + g_assert_cmpint(r, ==, TRUE); + + obj2 = _platform_has_routing_rule(platform, obj); + + if (obj2) { + guint k; + + /* When deleting a rule, kernel does a fuzzy match, ignoring for example: + * - action, if it is FR_ACT_UNSPEC + * - iifname,oifname if it is unspecified + * rh#1685816 + * + * That means, we may have deleted the wrong rule. Which one? */ + k = i; + for (j = i + 1; j < objs->len; j++) { + if (!_platform_has_routing_rule(platform, objs->pdata[j])) { + g_assert_cmpint(k, ==, i); + k = j; + } + } + g_assert_cmpint(k, >, i); + + if (!_rule_fuzzy_equal(obj, objs->pdata[k], RTM_DELRULE)) { + g_print(">>> failing...\n"); + g_print(">>> no fuzzy match between: %s\n", + nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + g_print( + ">>> and: %s\n", + nmp_object_to_string(objs->pdata[k], NMP_OBJECT_TO_STRING_ALL, NULL, 0)); + g_assert_not_reached(); + } + + objs->pdata[i] = objs->pdata[k]; + objs->pdata[k] = (gpointer) obj; + obj2 = NULL; + } + + g_assert(!obj2); + + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), + ==, + objs->len - i - 1); + } + } + + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), ==, 0); + + for (i = 0; i < objs_initial->len; i++) { + const NMPObject *obj = objs_initial->pdata[i]; + + for (j = 0; j < objs_initial->len; j++) + g_assert((j < i) == (!!_platform_has_routing_rule(platform, objs_initial->pdata[j]))); + + r = nm_platform_routing_rule_add(platform, + NMP_NLM_FLAG_ADD, + NMP_OBJECT_CAST_ROUTING_RULE(obj)); + g_assert_cmpint(r, ==, 0); + } + for (j = 0; j < objs_initial->len; j++) + g_assert(_platform_has_routing_rule(platform, objs_initial->pdata[j])); + g_assert_cmpint(nmtstp_platform_routing_rules_get_count(platform, AF_UNSPEC), + ==, + objs_initial->len); + + /* the tests passed as good as we could (as good as we implemented workarounds for them). + * Still, with this kernel, not all features were fully tested. Mark the test as skipped. */ + if (had_an_issue_exist) + g_test_skip("adding a rule failed with EEXIST although it should not (rh#1686075)"); + else if (!_rule_check_kernel_support(platform, -1)) + g_test_skip("some kernel features were not available and skipped for the test"); } /*****************************************************************************/ @@ -1729,37 +1889,38 @@ again: NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; void -_nmtstp_init_tests (int *argc, char ***argv) +_nmtstp_init_tests(int *argc, char ***argv) { - nmtst_init_with_logging (argc, argv, NULL, "ALL"); + nmtst_init_with_logging(argc, argv, NULL, "ALL"); } void -_nmtstp_setup_tests (void) +_nmtstp_setup_tests(void) { #define add_test_func(testpath, test_func) nmtstp_env1_add_test_func(testpath, test_func, TRUE) -#define add_test_func_data(testpath, test_func, arg) nmtstp_env1_add_test_func_data(testpath, test_func, arg, TRUE) - add_test_func ("/route/ip4", test_ip4_route); - add_test_func ("/route/ip6", test_ip6_route); - add_test_func ("/route/ip4_metric0", test_ip4_route_metric0); - add_test_func_data ("/route/ip4_options/1", test_ip4_route_options, GINT_TO_POINTER (1)); - if (nmtstp_is_root_test ()) - add_test_func_data ("/route/ip4_options/2", test_ip4_route_options, GINT_TO_POINTER (2)); - add_test_func_data ("/route/ip6_options/1", test_ip6_route_options, GINT_TO_POINTER (1)); - add_test_func_data ("/route/ip6_options/2", test_ip6_route_options, GINT_TO_POINTER (2)); - add_test_func_data ("/route/ip6_options/3", test_ip6_route_options, GINT_TO_POINTER (3)); - - if (nmtstp_is_root_test ()) { - add_test_func_data ("/route/ip/1", test_ip, GINT_TO_POINTER (1)); - add_test_func ("/route/ip4_route_get", test_ip4_route_get); - add_test_func ("/route/ip6_route_get", test_ip6_route_get); - add_test_func ("/route/ip4_zero_gateway", test_ip4_zero_gateway); - } - - if (nmtstp_is_root_test ()) { - add_test_func_data ("/route/rule/1", test_rule, GINT_TO_POINTER (1)); - add_test_func_data ("/route/rule/2", test_rule, GINT_TO_POINTER (2)); - add_test_func_data ("/route/rule/3", test_rule, GINT_TO_POINTER (3)); - add_test_func_data ("/route/rule/4", test_rule, GINT_TO_POINTER (4)); - } +#define add_test_func_data(testpath, test_func, arg) \ + nmtstp_env1_add_test_func_data(testpath, test_func, arg, TRUE) + add_test_func("/route/ip4", test_ip4_route); + add_test_func("/route/ip6", test_ip6_route); + add_test_func("/route/ip4_metric0", test_ip4_route_metric0); + add_test_func_data("/route/ip4_options/1", test_ip4_route_options, GINT_TO_POINTER(1)); + if (nmtstp_is_root_test()) + add_test_func_data("/route/ip4_options/2", test_ip4_route_options, GINT_TO_POINTER(2)); + add_test_func_data("/route/ip6_options/1", test_ip6_route_options, GINT_TO_POINTER(1)); + add_test_func_data("/route/ip6_options/2", test_ip6_route_options, GINT_TO_POINTER(2)); + add_test_func_data("/route/ip6_options/3", test_ip6_route_options, GINT_TO_POINTER(3)); + + if (nmtstp_is_root_test()) { + add_test_func_data("/route/ip/1", test_ip, GINT_TO_POINTER(1)); + add_test_func("/route/ip4_route_get", test_ip4_route_get); + add_test_func("/route/ip6_route_get", test_ip6_route_get); + add_test_func("/route/ip4_zero_gateway", test_ip4_zero_gateway); + } + + if (nmtstp_is_root_test()) { + add_test_func_data("/route/rule/1", test_rule, GINT_TO_POINTER(1)); + add_test_func_data("/route/rule/2", test_rule, GINT_TO_POINTER(2)); + add_test_func_data("/route/rule/3", test_rule, GINT_TO_POINTER(3)); + add_test_func_data("/route/rule/4", test_rule, GINT_TO_POINTER(4)); + } } diff --git a/src/platform/tests/test-tc.c b/src/platform/tests/test-tc.c index 0c90fcfa..4cbe4f5d 100644 --- a/src/platform/tests/test-tc.c +++ b/src/platform/tests/test-tc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ #include "nm-default.h" @@ -11,194 +11,193 @@ #include "test-common.h" static NMPObject * -qdisc_new (int ifindex, const char *kind, guint32 parent) +qdisc_new(int ifindex, const char *kind, guint32 parent) { - NMPObject *obj; + NMPObject *obj; - obj = nmp_object_new (NMP_OBJECT_TYPE_QDISC, NULL); - obj->qdisc = (NMPlatformQdisc) { - .ifindex = ifindex, - .kind = kind, - .parent = parent, - }; + obj = nmp_object_new(NMP_OBJECT_TYPE_QDISC, NULL); + obj->qdisc = (NMPlatformQdisc){ + .ifindex = ifindex, + .kind = kind, + .parent = parent, + }; - return obj; + return obj; } static GPtrArray * -qdiscs_lookup (int ifindex) +qdiscs_lookup(int ifindex) { - NMPLookup lookup; + NMPLookup lookup; - return nm_platform_lookup_clone (NM_PLATFORM_GET, - nmp_lookup_init_object (&lookup, - NMP_OBJECT_TYPE_QDISC, - ifindex), - NULL, NULL); + return nm_platform_lookup_clone(NM_PLATFORM_GET, + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_QDISC, ifindex), + NULL, + NULL); } static void -test_qdisc1 (void) +test_qdisc1(void) { - int ifindex; - gs_unref_ptrarray GPtrArray *known = NULL; - gs_unref_ptrarray GPtrArray *plat = NULL; - NMPObject *obj; - NMPlatformQdisc *qdisc; - - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert_cmpint (ifindex, >, 0); - - nmtstp_run_command ("tc qdisc del dev %s root", DEVICE_NAME); - nmtstp_run_command_check ("tc qdisc add dev %s root sfq", DEVICE_NAME); - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 0); - - known = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - g_ptr_array_add (known, qdisc_new (ifindex, "fq_codel", TC_H_ROOT)); - g_ptr_array_add (known, qdisc_new (ifindex, "ingress", TC_H_INGRESS)); - - g_assert (nm_platform_qdisc_sync (NM_PLATFORM_GET, ifindex, known)); - plat = qdiscs_lookup (ifindex); - g_assert (plat); - g_assert_cmpint (plat->len, ==, 2); - - obj = plat->pdata[0]; - qdisc = NMP_OBJECT_CAST_QDISC (obj); - g_assert_cmpint (qdisc->parent, ==, TC_H_ROOT); - g_assert_cmpstr (qdisc->kind, ==, "fq_codel"); - - obj = plat->pdata[1]; - qdisc = NMP_OBJECT_CAST_QDISC (obj); - g_assert_cmpint (qdisc->parent, ==, TC_H_INGRESS); - g_assert_cmpstr (qdisc->kind, ==, "ingress"); + int ifindex; + gs_unref_ptrarray GPtrArray *known = NULL; + gs_unref_ptrarray GPtrArray *plat = NULL; + NMPObject * obj; + NMPlatformQdisc * qdisc; + + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert_cmpint(ifindex, >, 0); + + nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME); + nmtstp_run_command_check("tc qdisc add dev %s root sfq", DEVICE_NAME); + + nmtstp_wait_for_signal(NM_PLATFORM_GET, 0); + + known = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + g_ptr_array_add(known, qdisc_new(ifindex, "fq_codel", TC_H_ROOT)); + g_ptr_array_add(known, qdisc_new(ifindex, "ingress", TC_H_INGRESS)); + + g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + plat = qdiscs_lookup(ifindex); + g_assert(plat); + g_assert_cmpint(plat->len, ==, 2); + + obj = plat->pdata[0]; + qdisc = NMP_OBJECT_CAST_QDISC(obj); + g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT); + g_assert_cmpstr(qdisc->kind, ==, "fq_codel"); + + obj = plat->pdata[1]; + qdisc = NMP_OBJECT_CAST_QDISC(obj); + g_assert_cmpint(qdisc->parent, ==, TC_H_INGRESS); + g_assert_cmpstr(qdisc->kind, ==, "ingress"); } static void -test_qdisc_fq_codel (void) +test_qdisc_fq_codel(void) { - int ifindex; - gs_unref_ptrarray GPtrArray *known = NULL; - gs_unref_ptrarray GPtrArray *plat = NULL; - NMPObject *obj; - NMPlatformQdisc *qdisc; - - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert_cmpint (ifindex, >, 0); - - nmtstp_run_command ("tc qdisc del dev %s root", DEVICE_NAME); - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 0); - - known = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - obj = qdisc_new (ifindex, "fq_codel", TC_H_ROOT); - obj->qdisc.handle = TC_H_MAKE (0x8142 << 16, 0); - obj->qdisc.fq_codel.limit = 2048; - obj->qdisc.fq_codel.flows = 64; - obj->qdisc.fq_codel.quantum = 1000; - g_ptr_array_add (known, obj); - - g_assert (nm_platform_qdisc_sync (NM_PLATFORM_GET, ifindex, known)); - plat = qdiscs_lookup (ifindex); - g_assert (plat); - g_assert_cmpint (plat->len, ==, 1); - - obj = plat->pdata[0]; - qdisc = NMP_OBJECT_CAST_QDISC (obj); - g_assert_cmpstr (qdisc->kind, ==, "fq_codel"); - g_assert_cmpint (qdisc->handle, ==, TC_H_MAKE (0x8142 << 16, 0)); - g_assert_cmpint (qdisc->parent, ==, TC_H_ROOT); - g_assert_cmpint (qdisc->fq_codel.limit, ==, 2048); - g_assert_cmpint (qdisc->fq_codel.flows, ==, 64); - g_assert_cmpint (qdisc->fq_codel.quantum, ==, 1000); + int ifindex; + gs_unref_ptrarray GPtrArray *known = NULL; + gs_unref_ptrarray GPtrArray *plat = NULL; + NMPObject * obj; + NMPlatformQdisc * qdisc; + + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert_cmpint(ifindex, >, 0); + + nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME); + + nmtstp_wait_for_signal(NM_PLATFORM_GET, 0); + + known = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + obj = qdisc_new(ifindex, "fq_codel", TC_H_ROOT); + obj->qdisc.handle = TC_H_MAKE(0x8142 << 16, 0); + obj->qdisc.fq_codel.limit = 2048; + obj->qdisc.fq_codel.flows = 64; + obj->qdisc.fq_codel.quantum = 1000; + g_ptr_array_add(known, obj); + + g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + plat = qdiscs_lookup(ifindex); + g_assert(plat); + g_assert_cmpint(plat->len, ==, 1); + + obj = plat->pdata[0]; + qdisc = NMP_OBJECT_CAST_QDISC(obj); + g_assert_cmpstr(qdisc->kind, ==, "fq_codel"); + g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8142 << 16, 0)); + g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT); + g_assert_cmpint(qdisc->fq_codel.limit, ==, 2048); + g_assert_cmpint(qdisc->fq_codel.flows, ==, 64); + g_assert_cmpint(qdisc->fq_codel.quantum, ==, 1000); } static void -test_qdisc_sfq (void) +test_qdisc_sfq(void) { - int ifindex; - gs_unref_ptrarray GPtrArray *known = NULL; - gs_unref_ptrarray GPtrArray *plat = NULL; - NMPObject *obj; - NMPlatformQdisc *qdisc; - - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert_cmpint (ifindex, >, 0); - - nmtstp_run_command ("tc qdisc del dev %s root", DEVICE_NAME); - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 0); - - known = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - obj = qdisc_new (ifindex, "sfq", TC_H_ROOT); - obj->qdisc.handle = TC_H_MAKE (0x8143 << 16, 0); - obj->qdisc.sfq.perturb_period = 10; - obj->qdisc.sfq.quantum = 1540; - obj->qdisc.sfq.flows = 256; - g_ptr_array_add (known, obj); - - g_assert (nm_platform_qdisc_sync (NM_PLATFORM_GET, ifindex, known)); - plat = qdiscs_lookup (ifindex); - g_assert (plat); - g_assert_cmpint (plat->len, ==, 1); - - obj = plat->pdata[0]; - qdisc = NMP_OBJECT_CAST_QDISC (obj); - g_assert_cmpstr (qdisc->kind, ==, "sfq"); - g_assert_cmpint (qdisc->handle, ==, TC_H_MAKE (0x8143 << 16, 0)); - g_assert_cmpint (qdisc->parent, ==, TC_H_ROOT); - g_assert_cmpint (qdisc->sfq.perturb_period, ==, 10); - g_assert_cmpint (qdisc->sfq.quantum, ==, 1540); - g_assert_cmpint (qdisc->sfq.flows, ==, 256); + int ifindex; + gs_unref_ptrarray GPtrArray *known = NULL; + gs_unref_ptrarray GPtrArray *plat = NULL; + NMPObject * obj; + NMPlatformQdisc * qdisc; + + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert_cmpint(ifindex, >, 0); + + nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME); + + nmtstp_wait_for_signal(NM_PLATFORM_GET, 0); + + known = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + obj = qdisc_new(ifindex, "sfq", TC_H_ROOT); + obj->qdisc.handle = TC_H_MAKE(0x8143 << 16, 0); + obj->qdisc.sfq.perturb_period = 10; + obj->qdisc.sfq.quantum = 1540; + obj->qdisc.sfq.flows = 256; + g_ptr_array_add(known, obj); + + g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + plat = qdiscs_lookup(ifindex); + g_assert(plat); + g_assert_cmpint(plat->len, ==, 1); + + obj = plat->pdata[0]; + qdisc = NMP_OBJECT_CAST_QDISC(obj); + g_assert_cmpstr(qdisc->kind, ==, "sfq"); + g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8143 << 16, 0)); + g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT); + g_assert_cmpint(qdisc->sfq.perturb_period, ==, 10); + g_assert_cmpint(qdisc->sfq.quantum, ==, 1540); + g_assert_cmpint(qdisc->sfq.flows, ==, 256); } static void -test_qdisc_tbf (void) +test_qdisc_tbf(void) { - int ifindex; - gs_unref_ptrarray GPtrArray *known = NULL; - gs_unref_ptrarray GPtrArray *plat = NULL; - NMPObject *obj; - NMPlatformQdisc *qdisc; - - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert_cmpint (ifindex, >, 0); - - nmtstp_run_command ("tc qdisc del dev %s root", DEVICE_NAME); - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 0); - - known = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref); - obj = qdisc_new (ifindex, "tbf", TC_H_ROOT); - obj->qdisc.handle = TC_H_MAKE (0x8143 << 16, 0); - obj->qdisc.tbf.rate = 1000000; - obj->qdisc.tbf.burst = 2000; - obj->qdisc.tbf.limit = 3000; - g_ptr_array_add (known, obj); - - obj = qdisc_new (ifindex, "sfq", TC_H_MAKE (0x8143 << 16, 0)); - obj->qdisc.handle = TC_H_MAKE (0x8005 << 16, 0); - g_ptr_array_add (known, obj); - - g_assert (nm_platform_qdisc_sync (NM_PLATFORM_GET, ifindex, known)); - plat = qdiscs_lookup (ifindex); - g_assert (plat); - g_assert_cmpint (plat->len, ==, 2); - - obj = plat->pdata[0]; - qdisc = NMP_OBJECT_CAST_QDISC (obj); - g_assert_cmpstr (qdisc->kind, ==, "tbf"); - g_assert_cmpint (qdisc->handle, ==, TC_H_MAKE (0x8143 << 16, 0)); - g_assert_cmpint (qdisc->parent, ==, TC_H_ROOT); - g_assert_cmpint (qdisc->tbf.rate, ==, 1000000); - g_assert_cmpint (qdisc->tbf.burst, ==, 2000); - g_assert_cmpint (qdisc->tbf.limit, ==, 3000); - - obj = plat->pdata[1]; - qdisc = NMP_OBJECT_CAST_QDISC (obj); - g_assert_cmpstr (qdisc->kind, ==, "sfq"); - g_assert_cmpint (qdisc->parent, ==, TC_H_MAKE (0x8143 << 16, 0)); - g_assert_cmpint (qdisc->handle, ==, TC_H_MAKE (0x8005 << 16, 0)); + int ifindex; + gs_unref_ptrarray GPtrArray *known = NULL; + gs_unref_ptrarray GPtrArray *plat = NULL; + NMPObject * obj; + NMPlatformQdisc * qdisc; + + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, DEVICE_NAME); + g_assert_cmpint(ifindex, >, 0); + + nmtstp_run_command("tc qdisc del dev %s root", DEVICE_NAME); + + nmtstp_wait_for_signal(NM_PLATFORM_GET, 0); + + known = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref); + obj = qdisc_new(ifindex, "tbf", TC_H_ROOT); + obj->qdisc.handle = TC_H_MAKE(0x8143 << 16, 0); + obj->qdisc.tbf.rate = 1000000; + obj->qdisc.tbf.burst = 2000; + obj->qdisc.tbf.limit = 3000; + g_ptr_array_add(known, obj); + + obj = qdisc_new(ifindex, "sfq", TC_H_MAKE(0x8143 << 16, 0)); + obj->qdisc.handle = TC_H_MAKE(0x8005 << 16, 0); + g_ptr_array_add(known, obj); + + g_assert(nm_platform_qdisc_sync(NM_PLATFORM_GET, ifindex, known)); + plat = qdiscs_lookup(ifindex); + g_assert(plat); + g_assert_cmpint(plat->len, ==, 2); + + obj = plat->pdata[0]; + qdisc = NMP_OBJECT_CAST_QDISC(obj); + g_assert_cmpstr(qdisc->kind, ==, "tbf"); + g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8143 << 16, 0)); + g_assert_cmpint(qdisc->parent, ==, TC_H_ROOT); + g_assert_cmpint(qdisc->tbf.rate, ==, 1000000); + g_assert_cmpint(qdisc->tbf.burst, ==, 2000); + g_assert_cmpint(qdisc->tbf.limit, ==, 3000); + + obj = plat->pdata[1]; + qdisc = NMP_OBJECT_CAST_QDISC(obj); + g_assert_cmpstr(qdisc->kind, ==, "sfq"); + g_assert_cmpint(qdisc->parent, ==, TC_H_MAKE(0x8143 << 16, 0)); + g_assert_cmpint(qdisc->handle, ==, TC_H_MAKE(0x8005 << 16, 0)); } /*****************************************************************************/ @@ -206,18 +205,18 @@ test_qdisc_tbf (void) NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; void -_nmtstp_init_tests (int *argc, char ***argv) +_nmtstp_init_tests(int *argc, char ***argv) { - nmtst_init_with_logging (argc, argv, NULL, "ALL"); + nmtst_init_with_logging(argc, argv, NULL, "ALL"); } void -_nmtstp_setup_tests (void) +_nmtstp_setup_tests(void) { - if (nmtstp_is_root_test ()) { - nmtstp_env1_add_test_func ("/link/qdisc/1", test_qdisc1, TRUE); - nmtstp_env1_add_test_func ("/link/qdisc/fq_codel", test_qdisc_fq_codel, TRUE); - nmtstp_env1_add_test_func ("/link/qdisc/sfq", test_qdisc_sfq, TRUE); - nmtstp_env1_add_test_func ("/link/qdisc/tbf", test_qdisc_tbf, TRUE); - } + if (nmtstp_is_root_test()) { + nmtstp_env1_add_test_func("/link/qdisc/1", test_qdisc1, TRUE); + nmtstp_env1_add_test_func("/link/qdisc/fq_codel", test_qdisc_fq_codel, TRUE); + nmtstp_env1_add_test_func("/link/qdisc/sfq", test_qdisc_sfq, TRUE); + nmtstp_env1_add_test_func("/link/qdisc/tbf", test_qdisc_tbf, TRUE); + } } diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c index a090ef9e..dddfa8fa 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/platform/wifi/nm-wifi-utils-nl80211.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -21,684 +21,664 @@ #include "platform/nm-platform-utils.h" #include "nm-utils.h" -#define _NMLOG_PREFIX_NAME "wifi-nl80211" -#define _NMLOG_DOMAIN LOGD_PLATFORM | LOGD_WIFI -#define _NMLOG(level, ...) \ - G_STMT_START { \ - char _ifname_buf[IFNAMSIZ]; \ - const char *_ifname = self ? nmp_utils_if_indextoname (self->parent.ifindex, _ifname_buf) : NULL; \ - \ - nm_log ((level), _NMLOG_DOMAIN, _ifname ?: NULL, NULL, \ - "%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - NM_PRINT_FMT_QUOTED (_ifname, " (", _ifname, ")", "") \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } G_STMT_END +#define _NMLOG_PREFIX_NAME "wifi-nl80211" +#define _NMLOG_DOMAIN LOGD_PLATFORM | LOGD_WIFI +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + char _ifname_buf[IFNAMSIZ]; \ + const char *_ifname = \ + self ? nmp_utils_if_indextoname(self->parent.ifindex, _ifname_buf) : NULL; \ + \ + nm_log((level), \ + _NMLOG_DOMAIN, \ + _ifname ?: NULL, \ + NULL, \ + "%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + NM_PRINT_FMT_QUOTED(_ifname, " (", _ifname, ")", "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END typedef struct { - NMWifiUtils parent; - struct nl_sock *nl_sock; - guint32 *freqs; - int id; - int num_freqs; - int phy; - bool can_wowlan:1; + NMWifiUtils parent; + struct nl_sock *nl_sock; + guint32 * freqs; + int id; + int num_freqs; + int phy; + bool can_wowlan : 1; } NMWifiUtilsNl80211; typedef struct { - NMWifiUtilsClass parent; + NMWifiUtilsClass parent; } NMWifiUtilsNl80211Class; -G_DEFINE_TYPE (NMWifiUtilsNl80211, nm_wifi_utils_nl80211, NM_TYPE_WIFI_UTILS) +G_DEFINE_TYPE(NMWifiUtilsNl80211, nm_wifi_utils_nl80211, NM_TYPE_WIFI_UTILS) static int -ack_handler (struct nl_msg *msg, void *arg) +ack_handler(struct nl_msg *msg, void *arg) { - int *done = arg; - *done = 1; - return NL_STOP; + int *done = arg; + *done = 1; + return NL_STOP; } static int -finish_handler (struct nl_msg *msg, void *arg) +finish_handler(struct nl_msg *msg, void *arg) { - int *done = arg; - *done = 1; - return NL_SKIP; + int *done = arg; + *done = 1; + return NL_SKIP; } static int -error_handler (struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) +error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { - int *done = arg; - *done = err->error; - return NL_SKIP; + int *done = arg; + *done = err->error; + return NL_SKIP; } static struct nl_msg * -_nl80211_alloc_msg (int id, int ifindex, int phy, guint32 cmd, guint32 flags) +_nl80211_alloc_msg(int id, int ifindex, int phy, guint32 cmd, guint32 flags) { - nm_auto_nlmsg struct nl_msg *msg = NULL; + nm_auto_nlmsg struct nl_msg *msg = NULL; - msg = nlmsg_alloc (); - genlmsg_put (msg, 0, 0, id, 0, flags, cmd, 0); - NLA_PUT_U32 (msg, NL80211_ATTR_IFINDEX, ifindex); - if (phy != -1) - NLA_PUT_U32 (msg, NL80211_ATTR_WIPHY, phy); - return g_steal_pointer (&msg); + msg = nlmsg_alloc(); + genlmsg_put(msg, 0, 0, id, 0, flags, cmd, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); + if (phy != -1) + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, phy); + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static struct nl_msg * -nl80211_alloc_msg (NMWifiUtilsNl80211 *self, guint32 cmd, guint32 flags) +nl80211_alloc_msg(NMWifiUtilsNl80211 *self, guint32 cmd, guint32 flags) { - return _nl80211_alloc_msg (self->id, self->parent.ifindex, self->phy, cmd, flags); + return _nl80211_alloc_msg(self->id, self->parent.ifindex, self->phy, cmd, flags); } static int -nl80211_send_and_recv (NMWifiUtilsNl80211 *self, - struct nl_msg *msg, - int (*valid_handler) (struct nl_msg *, void *), - void *valid_data) +nl80211_send_and_recv(NMWifiUtilsNl80211 *self, + struct nl_msg * msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) { - int err; - int done = 0; - const struct nl_cb cb = { - .err_cb = error_handler, - .err_arg = &done, - .finish_cb = finish_handler, - .finish_arg = &done, - .ack_cb = ack_handler, - .ack_arg = &done, - .valid_cb = valid_handler, - .valid_arg = valid_data, - }; - - g_return_val_if_fail (msg != NULL, -ENOMEM); - - err = nl_send_auto (self->nl_sock, msg); - if (err < 0) - return err; - - /* Loop until one of our NL callbacks says we're done; on success - * done will be 1, on error it will be < 0. - */ - while (!done) { - err = nl_recvmsgs (self->nl_sock, &cb); - if (err < 0 && err != -EAGAIN) { - /* Kernel scan list can change while we are dumping it, as new scan - * results from H/W can arrive. BSS info is assured to be consistent - * and we don't need consistent view of whole scan list. Hence do - * not warn on DUMP_INTR error for get scan command. - */ - if (err == -NME_NL_DUMP_INTR && - genlmsg_hdr (nlmsg_hdr (msg))->cmd == NL80211_CMD_GET_SCAN) - break; - - _LOGW ("nl_recvmsgs() error: (%d) %s", err, nm_strerror (err)); - break; - } - } - - if (err >= 0 && done < 0) - err = done; - return err; + int err; + int done = 0; + const struct nl_cb cb = { + .err_cb = error_handler, + .err_arg = &done, + .finish_cb = finish_handler, + .finish_arg = &done, + .ack_cb = ack_handler, + .ack_arg = &done, + .valid_cb = valid_handler, + .valid_arg = valid_data, + }; + + g_return_val_if_fail(msg != NULL, -ENOMEM); + + err = nl_send_auto(self->nl_sock, msg); + if (err < 0) + return err; + + /* Loop until one of our NL callbacks says we're done; on success + * done will be 1, on error it will be < 0. + */ + while (!done) { + err = nl_recvmsgs(self->nl_sock, &cb); + if (err < 0 && err != -EAGAIN) { + /* Kernel scan list can change while we are dumping it, as new scan + * results from H/W can arrive. BSS info is assured to be consistent + * and we don't need consistent view of whole scan list. Hence do + * not warn on DUMP_INTR error for get scan command. + */ + if (err == -NME_NL_DUMP_INTR + && genlmsg_hdr(nlmsg_hdr(msg))->cmd == NL80211_CMD_GET_SCAN) + break; + + _LOGW("nl_recvmsgs() error: (%d) %s", err, nm_strerror(err)); + break; + } + } + + if (err >= 0 && done < 0) + err = done; + return err; } static void -dispose (GObject *object) +dispose(GObject *object) { - NMWifiUtilsNl80211 *self = NM_WIFI_UTILS_NL80211 (object); + NMWifiUtilsNl80211 *self = NM_WIFI_UTILS_NL80211(object); - nm_clear_g_free (&self->freqs); + nm_clear_g_free(&self->freqs); } struct nl80211_iface_info { - NM80211Mode mode; + NM80211Mode mode; }; static int -nl80211_iface_info_handler (struct nl_msg *msg, void *arg) +nl80211_iface_info_handler(struct nl_msg *msg, void *arg) { - struct nl80211_iface_info *info = arg; - struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - - if (nla_parse_arr (tb, - genlmsg_attrdata (gnlh, 0), - genlmsg_attrlen (gnlh, 0), - NULL) < 0) - return NL_SKIP; - - if (!tb[NL80211_ATTR_IFTYPE]) - return NL_SKIP; - - switch (nla_get_u32 (tb[NL80211_ATTR_IFTYPE])) { - case NL80211_IFTYPE_ADHOC: - info->mode = NM_802_11_MODE_ADHOC; - break; - case NL80211_IFTYPE_AP: - info->mode = NM_802_11_MODE_AP; - break; - case NL80211_IFTYPE_STATION: - info->mode = NM_802_11_MODE_INFRA; - break; - case NL80211_IFTYPE_MESH_POINT: - info->mode = NM_802_11_MODE_MESH; - break; - } - - return NL_SKIP; + struct nl80211_iface_info *info = arg; + struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr * tb[NL80211_ATTR_MAX + 1]; + + if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) + return NL_SKIP; + + if (!tb[NL80211_ATTR_IFTYPE]) + return NL_SKIP; + + switch (nla_get_u32(tb[NL80211_ATTR_IFTYPE])) { + case NL80211_IFTYPE_ADHOC: + info->mode = NM_802_11_MODE_ADHOC; + break; + case NL80211_IFTYPE_AP: + info->mode = NM_802_11_MODE_AP; + break; + case NL80211_IFTYPE_STATION: + info->mode = NM_802_11_MODE_INFRA; + break; + case NL80211_IFTYPE_MESH_POINT: + info->mode = NM_802_11_MODE_MESH; + break; + } + + return NL_SKIP; } static NM80211Mode -wifi_nl80211_get_mode (NMWifiUtils *data) +wifi_nl80211_get_mode(NMWifiUtils *data) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - struct nl80211_iface_info iface_info = { - .mode = NM_802_11_MODE_UNKNOWN, - }; - nm_auto_nlmsg struct nl_msg *msg = NULL; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + struct nl80211_iface_info iface_info = { + .mode = NM_802_11_MODE_UNKNOWN, + }; + nm_auto_nlmsg struct nl_msg *msg = NULL; - msg = nl80211_alloc_msg (self, NL80211_CMD_GET_INTERFACE, 0); + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_INTERFACE, 0); - if (nl80211_send_and_recv (self, msg, nl80211_iface_info_handler, - &iface_info) < 0) - return NM_802_11_MODE_UNKNOWN; + if (nl80211_send_and_recv(self, msg, nl80211_iface_info_handler, &iface_info) < 0) + return NM_802_11_MODE_UNKNOWN; - return iface_info.mode; + return iface_info.mode; } static gboolean -wifi_nl80211_set_mode (NMWifiUtils *data, const NM80211Mode mode) +wifi_nl80211_set_mode(NMWifiUtils *data, const NM80211Mode mode) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - msg = nl80211_alloc_msg (self, NL80211_CMD_SET_INTERFACE, 0); - - switch (mode) { - case NM_802_11_MODE_INFRA: - NLA_PUT_U32 (msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_STATION); - break; - case NM_802_11_MODE_ADHOC: - NLA_PUT_U32 (msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_ADHOC); - break; - case NM_802_11_MODE_AP: - NLA_PUT_U32 (msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP); - break; - case NM_802_11_MODE_MESH: - NLA_PUT_U32 (msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MESH_POINT); - break; - default: - g_assert_not_reached (); - } - - err = nl80211_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; + + msg = nl80211_alloc_msg(self, NL80211_CMD_SET_INTERFACE, 0); + + switch (mode) { + case NM_802_11_MODE_INFRA: + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_STATION); + break; + case NM_802_11_MODE_ADHOC: + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_ADHOC); + break; + case NM_802_11_MODE_AP: + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP); + break; + case NM_802_11_MODE_MESH: + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MESH_POINT); + break; + default: + g_assert_not_reached(); + } + + err = nl80211_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static gboolean -wifi_nl80211_set_powersave (NMWifiUtils *data, guint32 powersave) +wifi_nl80211_set_powersave(NMWifiUtils *data, guint32 powersave) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; - msg = nl80211_alloc_msg (self, NL80211_CMD_SET_POWER_SAVE, 0); - NLA_PUT_U32 (msg, NL80211_ATTR_PS_STATE, - powersave == 1 ? NL80211_PS_ENABLED : NL80211_PS_DISABLED); - err = nl80211_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + msg = nl80211_alloc_msg(self, NL80211_CMD_SET_POWER_SAVE, 0); + NLA_PUT_U32(msg, + NL80211_ATTR_PS_STATE, + powersave == 1 ? NL80211_PS_ENABLED : NL80211_PS_DISABLED); + err = nl80211_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static int -nl80211_get_wake_on_wlan_handler (struct nl_msg *msg, void *arg) +nl80211_get_wake_on_wlan_handler(struct nl_msg *msg, void *arg) { - NMSettingWirelessWakeOnWLan *wowl = arg; - struct nlattr *attrs[NL80211_ATTR_MAX + 1]; - struct nlattr *trig[NUM_NL80211_WOWLAN_TRIG]; - struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); - - nla_parse_arr (attrs, - genlmsg_attrdata (gnlh, 0), - genlmsg_attrlen (gnlh, 0), - NULL); - - if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) - return NL_SKIP; - - nla_parse_arr (trig, - nla_data (attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), - nla_len (attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), - NULL); - - *wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE; - if (trig[NL80211_WOWLAN_TRIG_ANY]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY; - if (trig[NL80211_WOWLAN_TRIG_DISCONNECT]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT; - if (trig[NL80211_WOWLAN_TRIG_MAGIC_PKT]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC; - if (trig[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE; - if (trig[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST; - if (trig[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE; - if (trig[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE; - if (trig[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) - *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP; - - return NL_SKIP; + NMSettingWirelessWakeOnWLan *wowl = arg; + struct nlattr * attrs[NL80211_ATTR_MAX + 1]; + struct nlattr * trig[NUM_NL80211_WOWLAN_TRIG]; + struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); + + nla_parse_arr(attrs, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); + + if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) + return NL_SKIP; + + nla_parse_arr(trig, + nla_data(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), + nla_len(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), + NULL); + + *wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE; + if (trig[NL80211_WOWLAN_TRIG_ANY]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY; + if (trig[NL80211_WOWLAN_TRIG_DISCONNECT]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT; + if (trig[NL80211_WOWLAN_TRIG_MAGIC_PKT]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC; + if (trig[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE; + if (trig[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST; + if (trig[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE; + if (trig[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE; + if (trig[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) + *wowl |= NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP; + + return NL_SKIP; } static NMSettingWirelessWakeOnWLan -wifi_nl80211_get_wake_on_wlan (NMWifiUtils *data) +wifi_nl80211_get_wake_on_wlan(NMWifiUtils *data) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - NMSettingWirelessWakeOnWLan wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; - nm_auto_nlmsg struct nl_msg *msg = NULL; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + NMSettingWirelessWakeOnWLan wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; + nm_auto_nlmsg struct nl_msg *msg = NULL; - msg = nl80211_alloc_msg (self, NL80211_CMD_GET_WOWLAN, 0); + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WOWLAN, 0); - nl80211_send_and_recv (self, msg, nl80211_get_wake_on_wlan_handler, &wowl); + nl80211_send_and_recv(self, msg, nl80211_get_wake_on_wlan_handler, &wowl); - return wowl; + return wowl; } static gboolean -wifi_nl80211_set_wake_on_wlan (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl) +wifi_nl80211_set_wake_on_wlan(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nlattr *triggers; - int err; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nlattr * triggers; + int err; - if (wowl == NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) - return TRUE; + if (wowl == NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) + return TRUE; - msg = nl80211_alloc_msg (self, NL80211_CMD_SET_WOWLAN, 0); + msg = nl80211_alloc_msg(self, NL80211_CMD_SET_WOWLAN, 0); - triggers = nla_nest_start (msg, NL80211_ATTR_WOWLAN_TRIGGERS); - if (!triggers) - goto nla_put_failure; + triggers = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); + if (!triggers) + goto nla_put_failure; - if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY)) - NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_ANY); - if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT)) - NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_DISCONNECT); - if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC)) - NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); - if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE)) - NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); - if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST)) - NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); - if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE)) - NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); - if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE)) - NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); + if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY)) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); + if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT)) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); + if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC)) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); + if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE)) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); + if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST)) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); + if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE)) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); + if (NM_FLAGS_HAS(wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE)) + NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); - nla_nest_end (msg, triggers); + nla_nest_end(msg, triggers); - err = nl80211_send_and_recv (self, msg, NULL, NULL); + err = nl80211_send_and_recv(self, msg, NULL, NULL); - return err >= 0; + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } /* @divisor: pass what value @xbm should be divided by to get dBm */ static guint32 -nl80211_xbm_to_percent (gint32 xbm, guint32 divisor) +nl80211_xbm_to_percent(gint32 xbm, guint32 divisor) { -#define NOISE_FLOOR_DBM -90 -#define SIGNAL_MAX_DBM -20 +#define NOISE_FLOOR_DBM -90 +#define SIGNAL_MAX_DBM -20 - xbm /= divisor; - xbm = CLAMP (xbm, NOISE_FLOOR_DBM, SIGNAL_MAX_DBM); + xbm /= divisor; + xbm = CLAMP(xbm, NOISE_FLOOR_DBM, SIGNAL_MAX_DBM); - return 100 - 70 * (((float) SIGNAL_MAX_DBM - (float) xbm) / - ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM)); + return 100 + - 70 + * (((float) SIGNAL_MAX_DBM - (float) xbm) + / ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM)); } struct nl80211_bss_info { - guint32 freq; - guint8 bssid[ETH_ALEN]; - guint8 ssid[32]; - guint32 ssid_len; - guint32 beacon_signal; - gboolean valid; + guint32 freq; + guint8 bssid[ETH_ALEN]; + guint8 ssid[32]; + guint32 ssid_len; + guint32 beacon_signal; + gboolean valid; }; #define WLAN_EID_SSID 0 static void -find_ssid (guint8 *ies, guint32 ies_len, - guint8 **ssid, guint32 *ssid_len) +find_ssid(guint8 *ies, guint32 ies_len, guint8 **ssid, guint32 *ssid_len) { - *ssid = NULL; - *ssid_len = 0; - - while (ies_len > 2 && ies[0] != WLAN_EID_SSID) { - ies_len -= ies[1] + 2; - ies += ies[1] + 2; - } - if (ies_len < 2) - return; - if (ies_len < 2 + ies[1]) - return; - - *ssid_len = ies[1]; - *ssid = ies + 2; + *ssid = NULL; + *ssid_len = 0; + + while (ies_len > 2 && ies[0] != WLAN_EID_SSID) { + ies_len -= ies[1] + 2; + ies += ies[1] + 2; + } + if (ies_len < 2) + return; + if (ies_len < 2 + ies[1]) + return; + + *ssid_len = ies[1]; + *ssid = ies + 2; } static int -nl80211_bss_dump_handler (struct nl_msg *msg, void *arg) +nl80211_bss_dump_handler(struct nl_msg *msg, void *arg) { - static const struct nla_policy bss_policy[] = { - [NL80211_BSS_TSF] = { .type = NLA_U64 }, - [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, - [NL80211_BSS_BSSID] = { .minlen = ETH_ALEN }, - [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, - [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, - [NL80211_BSS_INFORMATION_ELEMENTS] = { }, - [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, - [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, - [NL80211_BSS_STATUS] = { .type = NLA_U32 }, - }; - struct nl80211_bss_info *info = arg; - struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct nlattr *bss[G_N_ELEMENTS (bss_policy)]; - guint32 status; - - if (nla_parse_arr (tb, - genlmsg_attrdata (gnlh, 0), - genlmsg_attrlen (gnlh, 0), - NULL) < 0) - return NL_SKIP; - - if (tb[NL80211_ATTR_BSS] == NULL) - return NL_SKIP; - - if (nla_parse_nested_arr (bss, - tb[NL80211_ATTR_BSS], - bss_policy)) - return NL_SKIP; - - if (bss[NL80211_BSS_STATUS] == NULL) - return NL_SKIP; - - status = nla_get_u32 (bss[NL80211_BSS_STATUS]); - - if (status != NL80211_BSS_STATUS_ASSOCIATED && - status != NL80211_BSS_STATUS_IBSS_JOINED) - return NL_SKIP; - - if (bss[NL80211_BSS_BSSID] == NULL) - return NL_SKIP; - memcpy (info->bssid, nla_data (bss[NL80211_BSS_BSSID]), ETH_ALEN); - - if (bss[NL80211_BSS_FREQUENCY]) - info->freq = nla_get_u32 (bss[NL80211_BSS_FREQUENCY]); - - if (bss[NL80211_BSS_SIGNAL_UNSPEC]) - info->beacon_signal = nla_get_u8 (bss[NL80211_BSS_SIGNAL_UNSPEC]); - - if (bss[NL80211_BSS_SIGNAL_MBM]) - info->beacon_signal = nl80211_xbm_to_percent (nla_get_u32 (bss[NL80211_BSS_SIGNAL_MBM]), 100); - - if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { - guint8 *ssid; - guint32 ssid_len; - - find_ssid (nla_data (bss[NL80211_BSS_INFORMATION_ELEMENTS]), - nla_len (bss[NL80211_BSS_INFORMATION_ELEMENTS]), - &ssid, - &ssid_len); - if ( ssid - && ssid_len - && ssid_len <= sizeof (info->ssid)) { - memcpy (info->ssid, ssid, ssid_len); - info->ssid_len = ssid_len; - } - } - - info->valid = TRUE; - - return NL_SKIP; + static const struct nla_policy bss_policy[] = { + [NL80211_BSS_TSF] = {.type = NLA_U64}, + [NL80211_BSS_FREQUENCY] = {.type = NLA_U32}, + [NL80211_BSS_BSSID] = {.minlen = ETH_ALEN}, + [NL80211_BSS_BEACON_INTERVAL] = {.type = NLA_U16}, + [NL80211_BSS_CAPABILITY] = {.type = NLA_U16}, + [NL80211_BSS_INFORMATION_ELEMENTS] = {}, + [NL80211_BSS_SIGNAL_MBM] = {.type = NLA_U32}, + [NL80211_BSS_SIGNAL_UNSPEC] = {.type = NLA_U8}, + [NL80211_BSS_STATUS] = {.type = NLA_U32}, + }; + struct nl80211_bss_info *info = arg; + struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr * tb[NL80211_ATTR_MAX + 1]; + struct nlattr * bss[G_N_ELEMENTS(bss_policy)]; + guint32 status; + + if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) + return NL_SKIP; + + if (tb[NL80211_ATTR_BSS] == NULL) + return NL_SKIP; + + if (nla_parse_nested_arr(bss, tb[NL80211_ATTR_BSS], bss_policy)) + return NL_SKIP; + + if (bss[NL80211_BSS_STATUS] == NULL) + return NL_SKIP; + + status = nla_get_u32(bss[NL80211_BSS_STATUS]); + + if (status != NL80211_BSS_STATUS_ASSOCIATED && status != NL80211_BSS_STATUS_IBSS_JOINED) + return NL_SKIP; + + if (bss[NL80211_BSS_BSSID] == NULL) + return NL_SKIP; + memcpy(info->bssid, nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN); + + if (bss[NL80211_BSS_FREQUENCY]) + info->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); + + if (bss[NL80211_BSS_SIGNAL_UNSPEC]) + info->beacon_signal = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); + + if (bss[NL80211_BSS_SIGNAL_MBM]) + info->beacon_signal = nl80211_xbm_to_percent(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]), 100); + + if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { + guint8 *ssid; + guint32 ssid_len; + + find_ssid(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), + nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), + &ssid, + &ssid_len); + if (ssid && ssid_len && ssid_len <= sizeof(info->ssid)) { + memcpy(info->ssid, ssid, ssid_len); + info->ssid_len = ssid_len; + } + } + + info->valid = TRUE; + + return NL_SKIP; } static void -nl80211_get_bss_info (NMWifiUtilsNl80211 *self, - struct nl80211_bss_info *bss_info) +nl80211_get_bss_info(NMWifiUtilsNl80211 *self, struct nl80211_bss_info *bss_info) { - nm_auto_nlmsg struct nl_msg *msg = NULL; + nm_auto_nlmsg struct nl_msg *msg = NULL; - memset (bss_info, 0, sizeof (*bss_info)); + memset(bss_info, 0, sizeof(*bss_info)); - msg = nl80211_alloc_msg (self, NL80211_CMD_GET_SCAN, NLM_F_DUMP); + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_SCAN, NLM_F_DUMP); - nl80211_send_and_recv (self, msg, nl80211_bss_dump_handler, bss_info); + nl80211_send_and_recv(self, msg, nl80211_bss_dump_handler, bss_info); } static guint32 -wifi_nl80211_get_freq (NMWifiUtils *data) +wifi_nl80211_get_freq(NMWifiUtils *data) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - struct nl80211_bss_info bss_info; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + struct nl80211_bss_info bss_info; - nl80211_get_bss_info (self, &bss_info); + nl80211_get_bss_info(self, &bss_info); - return bss_info.freq; + return bss_info.freq; } static guint32 -wifi_nl80211_find_freq (NMWifiUtils *data, const guint32 *freqs) +wifi_nl80211_find_freq(NMWifiUtils *data, const guint32 *freqs) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - int i; - - for (i = 0; i < self->num_freqs; i++) { - while (*freqs) { - if (self->freqs[i] == *freqs) - return *freqs; - freqs++; - } - } - return 0; + NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; + int i; + + for (i = 0; i < self->num_freqs; i++) { + while (*freqs) { + if (self->freqs[i] == *freqs) + return *freqs; + freqs++; + } + } + return 0; } static gboolean -wifi_nl80211_get_bssid (NMWifiUtils *data, guint8 *out_bssid) +wifi_nl80211_get_bssid(NMWifiUtils *data, guint8 *out_bssid) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - struct nl80211_bss_info bss_info; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + struct nl80211_bss_info bss_info; - nl80211_get_bss_info (self, &bss_info); + nl80211_get_bss_info(self, &bss_info); - if (bss_info.valid) - memcpy (out_bssid, bss_info.bssid, ETH_ALEN); + if (bss_info.valid) + memcpy(out_bssid, bss_info.bssid, ETH_ALEN); - return bss_info.valid; + return bss_info.valid; } struct nl80211_station_info { - guint32 txrate; - gboolean txrate_valid; - guint8 signal; - gboolean signal_valid; + guint32 txrate; + gboolean txrate_valid; + guint8 signal; + gboolean signal_valid; }; static int -nl80211_station_handler (struct nl_msg *msg, void *arg) +nl80211_station_handler(struct nl_msg *msg, void *arg) { - static const struct nla_policy stats_policy[] = { - [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 }, - [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 }, - [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, - [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, - [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, - [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, - [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED }, - [NL80211_STA_INFO_LLID] = { .type = NLA_U16 }, - [NL80211_STA_INFO_PLID] = { .type = NLA_U16 }, - [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 }, - }; - static const struct nla_policy rate_policy[] = { - [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 }, - [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 }, - [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG }, - [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, - }; - struct nlattr *rinfo[G_N_ELEMENTS (rate_policy)]; - struct nlattr *sinfo[G_N_ELEMENTS (stats_policy)]; - struct nl80211_station_info *info = arg; - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); - - if (nla_parse_arr (tb, - genlmsg_attrdata (gnlh, 0), - genlmsg_attrlen (gnlh, 0), - NULL) < 0) - return NL_SKIP; - - if (tb[NL80211_ATTR_STA_INFO] == NULL) - return NL_SKIP; - - if (nla_parse_nested_arr (sinfo, - tb[NL80211_ATTR_STA_INFO], - stats_policy)) - return NL_SKIP; - - if (sinfo[NL80211_STA_INFO_TX_BITRATE] == NULL) - return NL_SKIP; - - if (nla_parse_nested_arr (rinfo, - sinfo[NL80211_STA_INFO_TX_BITRATE], - rate_policy)) - return NL_SKIP; - - if (rinfo[NL80211_RATE_INFO_BITRATE] == NULL) - return NL_SKIP; - - /* convert from nl80211's units of 100kbps to NM's kbps */ - info->txrate = nla_get_u16 (rinfo[NL80211_RATE_INFO_BITRATE]) * 100; - info->txrate_valid = TRUE; - - if (sinfo[NL80211_STA_INFO_SIGNAL] != NULL) { - info->signal = nl80211_xbm_to_percent ((gint8) nla_get_u8 (sinfo[NL80211_STA_INFO_SIGNAL]), 1); - info->signal_valid = TRUE; - } - - return NL_SKIP; + static const struct nla_policy stats_policy[] = { + [NL80211_STA_INFO_INACTIVE_TIME] = {.type = NLA_U32}, + [NL80211_STA_INFO_RX_BYTES] = {.type = NLA_U32}, + [NL80211_STA_INFO_TX_BYTES] = {.type = NLA_U32}, + [NL80211_STA_INFO_RX_PACKETS] = {.type = NLA_U32}, + [NL80211_STA_INFO_TX_PACKETS] = {.type = NLA_U32}, + [NL80211_STA_INFO_SIGNAL] = {.type = NLA_U8}, + [NL80211_STA_INFO_TX_BITRATE] = {.type = NLA_NESTED}, + [NL80211_STA_INFO_LLID] = {.type = NLA_U16}, + [NL80211_STA_INFO_PLID] = {.type = NLA_U16}, + [NL80211_STA_INFO_PLINK_STATE] = {.type = NLA_U8}, + }; + static const struct nla_policy rate_policy[] = { + [NL80211_RATE_INFO_BITRATE] = {.type = NLA_U16}, + [NL80211_RATE_INFO_MCS] = {.type = NLA_U8}, + [NL80211_RATE_INFO_40_MHZ_WIDTH] = {.type = NLA_FLAG}, + [NL80211_RATE_INFO_SHORT_GI] = {.type = NLA_FLAG}, + }; + struct nlattr * rinfo[G_N_ELEMENTS(rate_policy)]; + struct nlattr * sinfo[G_N_ELEMENTS(stats_policy)]; + struct nl80211_station_info *info = arg; + struct nlattr * tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); + + if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) + return NL_SKIP; + + if (tb[NL80211_ATTR_STA_INFO] == NULL) + return NL_SKIP; + + if (nla_parse_nested_arr(sinfo, tb[NL80211_ATTR_STA_INFO], stats_policy)) + return NL_SKIP; + + if (sinfo[NL80211_STA_INFO_TX_BITRATE] == NULL) + return NL_SKIP; + + if (nla_parse_nested_arr(rinfo, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) + return NL_SKIP; + + if (rinfo[NL80211_RATE_INFO_BITRATE] == NULL) + return NL_SKIP; + + /* convert from nl80211's units of 100kbps to NM's kbps */ + info->txrate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100; + info->txrate_valid = TRUE; + + if (sinfo[NL80211_STA_INFO_SIGNAL] != NULL) { + info->signal = + nl80211_xbm_to_percent((gint8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]), 1); + info->signal_valid = TRUE; + } + + return NL_SKIP; } static void -nl80211_get_ap_info (NMWifiUtilsNl80211 *self, - struct nl80211_station_info *sta_info) +nl80211_get_ap_info(NMWifiUtilsNl80211 *self, struct nl80211_station_info *sta_info) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nl80211_bss_info bss_info; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nl80211_bss_info bss_info; - memset (sta_info, 0, sizeof (*sta_info)); + memset(sta_info, 0, sizeof(*sta_info)); - nl80211_get_bss_info (self, &bss_info); - if (!bss_info.valid) - return; + nl80211_get_bss_info(self, &bss_info); + if (!bss_info.valid) + return; - msg = nl80211_alloc_msg (self, NL80211_CMD_GET_STATION, 0); - NLA_PUT (msg, NL80211_ATTR_MAC, ETH_ALEN, bss_info.bssid); + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_STATION, 0); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bss_info.bssid); - nl80211_send_and_recv (self, msg, nl80211_station_handler, sta_info); - if (!sta_info->signal_valid) { - /* Fall back to bss_info signal quality (both are in percent) */ - sta_info->signal = bss_info.beacon_signal; - } + nl80211_send_and_recv(self, msg, nl80211_station_handler, sta_info); + if (!sta_info->signal_valid) { + /* Fall back to bss_info signal quality (both are in percent) */ + sta_info->signal = bss_info.beacon_signal; + } - return; + return; nla_put_failure: - g_return_if_reached (); + g_return_if_reached(); } static guint32 -wifi_nl80211_get_rate (NMWifiUtils *data) +wifi_nl80211_get_rate(NMWifiUtils *data) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - struct nl80211_station_info sta_info; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + struct nl80211_station_info sta_info; - nl80211_get_ap_info (self, &sta_info); + nl80211_get_ap_info(self, &sta_info); - return sta_info.txrate; + return sta_info.txrate; } static int -wifi_nl80211_get_qual (NMWifiUtils *data) +wifi_nl80211_get_qual(NMWifiUtils *data) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - struct nl80211_station_info sta_info; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + struct nl80211_station_info sta_info; - nl80211_get_ap_info (self, &sta_info); - return sta_info.signal; + nl80211_get_ap_info(self, &sta_info); + return sta_info.signal; } static gboolean -wifi_nl80211_indicate_addressing_running (NMWifiUtils *data, gboolean running) +wifi_nl80211_indicate_addressing_running(NMWifiUtils *data, gboolean running) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - msg = nl80211_alloc_msg (self, - running - ? 98 /* NL80211_CMD_CRIT_PROTOCOL_START */ - : 99 /* NL80211_CMD_CRIT_PROTOCOL_STOP */, - 0); - /* Despite the DHCP name, we're using this for any type of IP addressing, - * DHCPv4, DHCPv6, and IPv6 SLAAC. - */ - NLA_PUT_U16 (msg, - 179 /* NL80211_ATTR_CRIT_PROT_ID */, - 1 /* NL80211_CRIT_PROTO_DHCP */); - if (running) { - /* Give DHCP 5 seconds to complete */ - NLA_PUT_U16 (msg, - 180 /* NL80211_ATTR_MAX_CRIT_PROT_DURATION */, - 5000); - } - - err = nl80211_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; + + msg = nl80211_alloc_msg(self, + running ? 98 /* NL80211_CMD_CRIT_PROTOCOL_START */ + : 99 /* NL80211_CMD_CRIT_PROTOCOL_STOP */, + 0); + /* Despite the DHCP name, we're using this for any type of IP addressing, + * DHCPv4, DHCPv6, and IPv6 SLAAC. + */ + NLA_PUT_U16(msg, 179 /* NL80211_ATTR_CRIT_PROT_ID */, 1 /* NL80211_CRIT_PROTO_DHCP */); + if (running) { + /* Give DHCP 5 seconds to complete */ + NLA_PUT_U16(msg, 180 /* NL80211_ATTR_MAX_CRIT_PROT_DURATION */, 5000); + } + + err = nl80211_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } struct nl80211_device_info { - NMWifiUtilsNl80211 *self; - int phy; - guint32 *freqs; - int num_freqs; - guint32 freq; - guint32 caps; - gboolean can_scan; - gboolean can_scan_ssid; - gboolean supported; - gboolean success; - gboolean can_wowlan; + NMWifiUtilsNl80211 *self; + int phy; + guint32 * freqs; + int num_freqs; + guint32 freq; + guint32 caps; + gboolean can_scan; + gboolean can_scan_ssid; + gboolean supported; + gboolean success; + gboolean can_wowlan; }; #define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 @@ -710,353 +690,339 @@ struct nl80211_device_info { #define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 #define WLAN_CIPHER_SUITE_SMS4 0x00147201 -static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) +static int +nl80211_wiphy_info_handler(struct nl_msg *msg, void *arg) { - static const struct nla_policy freq_policy[] = { - [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, - [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, + static const struct nla_policy freq_policy[] = { + [NL80211_FREQUENCY_ATTR_FREQ] = {.type = NLA_U32}, + [NL80211_FREQUENCY_ATTR_DISABLED] = {.type = NLA_FLAG}, #ifdef NL80211_FREQUENCY_ATTR_NO_IR - [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_NO_IR] = {.type = NLA_FLAG}, #else - [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = {.type = NLA_FLAG}, + [NL80211_FREQUENCY_ATTR_NO_IBSS] = {.type = NLA_FLAG}, #endif - [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, - }; - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); - struct nl80211_device_info *info = arg; - NMWifiUtilsNl80211 *self = info->self; - struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; - struct nlattr *tb_freq[G_N_ELEMENTS (freq_policy)]; - struct nlattr *nl_band; - struct nlattr *nl_freq; - int rem_freq; - int rem_band; - int freq_idx; + [NL80211_FREQUENCY_ATTR_RADAR] = {.type = NLA_FLAG}, + [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = {.type = NLA_U32}, + }; + struct nlattr * tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nl80211_device_info *info = arg; + NMWifiUtilsNl80211 * self = info->self; + struct nlattr * tb_band[NL80211_BAND_ATTR_MAX + 1]; + struct nlattr * tb_freq[G_N_ELEMENTS(freq_policy)]; + struct nlattr * nl_band; + struct nlattr * nl_freq; + int rem_freq; + int rem_band; + int freq_idx; #ifdef NL80211_FREQUENCY_ATTR_NO_IR - G_STATIC_ASSERT_EXPR (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR && NL80211_FREQUENCY_ATTR_NO_IBSS == NL80211_FREQUENCY_ATTR_NO_IR); + G_STATIC_ASSERT_EXPR(NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR + && NL80211_FREQUENCY_ATTR_NO_IBSS == NL80211_FREQUENCY_ATTR_NO_IR); #else - G_STATIC_ASSERT_EXPR (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN != NL80211_FREQUENCY_ATTR_NO_IBSS); + G_STATIC_ASSERT_EXPR(NL80211_FREQUENCY_ATTR_PASSIVE_SCAN != NL80211_FREQUENCY_ATTR_NO_IBSS); #endif - if (nla_parse_arr (tb, - genlmsg_attrdata (gnlh, 0), - genlmsg_attrlen (gnlh, 0), - NULL) < 0) - return NL_SKIP; - - if ( tb[NL80211_ATTR_WIPHY] == NULL - || tb[NL80211_ATTR_WIPHY_BANDS] == NULL) - return NL_SKIP; - - info->phy = nla_get_u32 (tb[NL80211_ATTR_WIPHY]); - - if (tb[NL80211_ATTR_WIPHY_FREQ]) - info->freq = nla_get_u32 (tb[NL80211_ATTR_WIPHY_FREQ]); - else - info->freq = 0; - - if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) { - info->can_scan_ssid = - nla_get_u8 (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) > 0; - } else { - /* old kernel that only had mac80211, so assume it can */ - info->can_scan_ssid = TRUE; - } - - if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { - struct nlattr *nl_cmd; - int i; - - nla_for_each_nested (nl_cmd, tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { - switch (nla_get_u32 (nl_cmd)) { - case NL80211_CMD_TRIGGER_SCAN: - info->can_scan = TRUE; - break; - case NL80211_CMD_CONNECT: - case NL80211_CMD_AUTHENTICATE: - /* Only devices that support CONNECT or AUTH actually support - * 802.11, unlike say ipw2x00 (up to at least kernel 3.4) which - * has minimal info support, but no actual command support. - * This check mirrors what wpa_supplicant does to determine - * whether or not to use the nl80211 driver. - */ - info->supported = TRUE; - break; - default: - break; - } - } - } - - /* Find number of supported frequencies */ - info->num_freqs = 0; - - nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { - if (nla_parse_nested_arr (tb_band, - nl_band, - NULL) < 0) - return NL_SKIP; - - nla_for_each_nested (nl_freq, - tb_band[NL80211_BAND_ATTR_FREQS], - rem_freq) { - if (nla_parse_nested_arr (tb_freq, - nl_freq, - freq_policy) < 0) - continue; - - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - - info->num_freqs++; - } - } - - /* Read supported frequencies */ - info->freqs = g_malloc0 (sizeof (guint32) * info->num_freqs); - - freq_idx = 0; - nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { - if (nla_parse_nested_arr (tb_band, - nl_band, - NULL) < 0) - return NL_SKIP; - - nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], - rem_freq) { - if (nla_parse_nested_arr (tb_freq, - nl_freq, - freq_policy) < 0) - continue; - - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - - info->freqs[freq_idx] = nla_get_u32 (tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); - - info->caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID; - - if (info->freqs[freq_idx] > 2400 && info->freqs[freq_idx] < 2500) - info->caps |= NM_WIFI_DEVICE_CAP_FREQ_2GHZ; - if (info->freqs[freq_idx] > 4900 && info->freqs[freq_idx] < 6000) - info->caps |= NM_WIFI_DEVICE_CAP_FREQ_5GHZ; - - freq_idx++; - } - } - - /* Read security/encryption support */ - if (tb[NL80211_ATTR_CIPHER_SUITES]) { - guint32 *ciphers = nla_data (tb[NL80211_ATTR_CIPHER_SUITES]); - guint i, num; - - num = nla_len (tb[NL80211_ATTR_CIPHER_SUITES]) / sizeof (guint32); - for (i = 0; i < num; i++) { - switch (ciphers[i]) { - case WLAN_CIPHER_SUITE_WEP40: - info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40; - break; - case WLAN_CIPHER_SUITE_WEP104: - info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP104; - break; - case WLAN_CIPHER_SUITE_TKIP: - info->caps |= (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | - NM_WIFI_DEVICE_CAP_WPA); - break; - case WLAN_CIPHER_SUITE_CCMP: - info->caps |= (NM_WIFI_DEVICE_CAP_CIPHER_CCMP | - NM_WIFI_DEVICE_CAP_RSN); - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - case WLAN_CIPHER_SUITE_GCMP: - case WLAN_CIPHER_SUITE_SMS4: - break; - default: - _LOGD ("don't know the meaning of NL80211_ATTR_CIPHER_SUITE %#8.8x.", - ciphers[i]); - break; - } - } - } - - if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) { - struct nlattr *nl_mode; - int i; - - nla_for_each_nested (nl_mode, tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) { - switch (nla_type (nl_mode)) { - case NL80211_IFTYPE_AP: info->caps |= NM_WIFI_DEVICE_CAP_AP; break; - case NL80211_IFTYPE_ADHOC: info->caps |= NM_WIFI_DEVICE_CAP_ADHOC; break; - case NL80211_IFTYPE_MESH_POINT: info->caps |= NM_WIFI_DEVICE_CAP_MESH; break; - } - } - } - - if (tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]) - info->can_wowlan = TRUE; - - if (tb[NL80211_ATTR_SUPPORT_IBSS_RSN]) - info->caps |= NM_WIFI_DEVICE_CAP_IBSS_RSN; - - info->success = TRUE; - - return NL_SKIP; + if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) + return NL_SKIP; + + if (tb[NL80211_ATTR_WIPHY] == NULL || tb[NL80211_ATTR_WIPHY_BANDS] == NULL) + return NL_SKIP; + + info->phy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); + + if (tb[NL80211_ATTR_WIPHY_FREQ]) + info->freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); + else + info->freq = 0; + + if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) { + info->can_scan_ssid = nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) > 0; + } else { + /* old kernel that only had mac80211, so assume it can */ + info->can_scan_ssid = TRUE; + } + + if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { + struct nlattr *nl_cmd; + int i; + + nla_for_each_nested (nl_cmd, tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { + switch (nla_get_u32(nl_cmd)) { + case NL80211_CMD_TRIGGER_SCAN: + info->can_scan = TRUE; + break; + case NL80211_CMD_CONNECT: + case NL80211_CMD_AUTHENTICATE: + /* Only devices that support CONNECT or AUTH actually support + * 802.11, unlike say ipw2x00 (up to at least kernel 3.4) which + * has minimal info support, but no actual command support. + * This check mirrors what wpa_supplicant does to determine + * whether or not to use the nl80211 driver. + */ + info->supported = TRUE; + break; + default: + break; + } + } + } + + /* Find number of supported frequencies */ + info->num_freqs = 0; + + nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { + if (nla_parse_nested_arr(tb_band, nl_band, NULL) < 0) + return NL_SKIP; + + nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { + if (nla_parse_nested_arr(tb_freq, nl_freq, freq_policy) < 0) + continue; + + if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) + continue; + + info->num_freqs++; + } + } + + /* Read supported frequencies */ + info->freqs = g_malloc0(sizeof(guint32) * info->num_freqs); + + freq_idx = 0; + nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) { + if (nla_parse_nested_arr(tb_band, nl_band, NULL) < 0) + return NL_SKIP; + + nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { + if (nla_parse_nested_arr(tb_freq, nl_freq, freq_policy) < 0) + continue; + + if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) + continue; + + info->freqs[freq_idx] = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); + + info->caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID; + + if (info->freqs[freq_idx] > 2400 && info->freqs[freq_idx] < 2500) + info->caps |= NM_WIFI_DEVICE_CAP_FREQ_2GHZ; + if (info->freqs[freq_idx] > 4900 && info->freqs[freq_idx] < 6000) + info->caps |= NM_WIFI_DEVICE_CAP_FREQ_5GHZ; + + freq_idx++; + } + } + + /* Read security/encryption support */ + if (tb[NL80211_ATTR_CIPHER_SUITES]) { + guint32 *ciphers = nla_data(tb[NL80211_ATTR_CIPHER_SUITES]); + guint i, num; + + num = nla_len(tb[NL80211_ATTR_CIPHER_SUITES]) / sizeof(guint32); + for (i = 0; i < num; i++) { + switch (ciphers[i]) { + case WLAN_CIPHER_SUITE_WEP40: + info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + info->caps |= (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_WPA); + break; + case WLAN_CIPHER_SUITE_CCMP: + info->caps |= (NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN); + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_SMS4: + break; + default: + _LOGD("don't know the meaning of NL80211_ATTR_CIPHER_SUITE %#8.8x.", ciphers[i]); + break; + } + } + } + + if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) { + struct nlattr *nl_mode; + int i; + + nla_for_each_nested (nl_mode, tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) { + switch (nla_type(nl_mode)) { + case NL80211_IFTYPE_AP: + info->caps |= NM_WIFI_DEVICE_CAP_AP; + break; + case NL80211_IFTYPE_ADHOC: + info->caps |= NM_WIFI_DEVICE_CAP_ADHOC; + break; + case NL80211_IFTYPE_MESH_POINT: + info->caps |= NM_WIFI_DEVICE_CAP_MESH; + break; + } + } + } + + if (tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]) + info->can_wowlan = TRUE; + + if (tb[NL80211_ATTR_SUPPORT_IBSS_RSN]) + info->caps |= NM_WIFI_DEVICE_CAP_IBSS_RSN; + + info->success = TRUE; + + return NL_SKIP; } static guint32 -wifi_nl80211_get_mesh_channel (NMWifiUtils *data) +wifi_nl80211_get_mesh_channel(NMWifiUtils *data) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nl80211_device_info device_info = { .self = self }; - int i; - - msg = nl80211_alloc_msg (self, NL80211_CMD_GET_WIPHY, 0); - - if (nl80211_send_and_recv (self, msg, nl80211_wiphy_info_handler, - &device_info) < 0) { - _LOGW ("NL80211_CMD_GET_WIPHY request failed"); - return 0; - } - - for (i = 0; i < self->num_freqs; i++) { - if (device_info.freq == self->freqs[i]) - return i + 1; - } - return 0; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nl80211_device_info device_info = {.self = self}; + int i; + + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WIPHY, 0); + + if (nl80211_send_and_recv(self, msg, nl80211_wiphy_info_handler, &device_info) < 0) { + _LOGW("NL80211_CMD_GET_WIPHY request failed"); + return 0; + } + + for (i = 0; i < self->num_freqs; i++) { + if (device_info.freq == self->freqs[i]) + return i + 1; + } + return 0; } static gboolean -wifi_nl80211_set_mesh_channel (NMWifiUtils *data, guint32 channel) +wifi_nl80211_set_mesh_channel(NMWifiUtils *data, guint32 channel) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; - if (channel > self->num_freqs) - return FALSE; + if (channel > self->num_freqs) + return FALSE; - msg = nl80211_alloc_msg (self, NL80211_CMD_SET_WIPHY, 0); - NLA_PUT_U32 (msg, NL80211_ATTR_WIPHY_FREQ, self->freqs[channel - 1]); - err = nl80211_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + msg = nl80211_alloc_msg(self, NL80211_CMD_SET_WIPHY, 0); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, self->freqs[channel - 1]); + err = nl80211_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static gboolean -wifi_nl80211_set_mesh_ssid (NMWifiUtils *data, const guint8 *ssid, gsize len) +wifi_nl80211_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len) { - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; - msg = nl80211_alloc_msg (self, NL80211_CMD_SET_INTERFACE, 0); - NLA_PUT (msg, NL80211_ATTR_MESH_ID, len, ssid); - err = nl80211_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + msg = nl80211_alloc_msg(self, NL80211_CMD_SET_INTERFACE, 0); + NLA_PUT(msg, NL80211_ATTR_MESH_ID, len, ssid); + err = nl80211_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } static void -nm_wifi_utils_nl80211_init (NMWifiUtilsNl80211 *self) -{ -} +nm_wifi_utils_nl80211_init(NMWifiUtilsNl80211 *self) +{} static void -nm_wifi_utils_nl80211_class_init (NMWifiUtilsNl80211Class *klass) +nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMWifiUtilsClass *wifi_utils_class = NM_WIFI_UTILS_CLASS (klass); - - object_class->dispose = dispose; - - wifi_utils_class->get_mode = wifi_nl80211_get_mode; - wifi_utils_class->set_mode = wifi_nl80211_set_mode; - wifi_utils_class->set_powersave = wifi_nl80211_set_powersave; - wifi_utils_class->get_wake_on_wlan = wifi_nl80211_get_wake_on_wlan, - wifi_utils_class->set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan, - wifi_utils_class->get_freq = wifi_nl80211_get_freq; - wifi_utils_class->find_freq = wifi_nl80211_find_freq; - wifi_utils_class->get_bssid = wifi_nl80211_get_bssid; - wifi_utils_class->get_rate = wifi_nl80211_get_rate; - wifi_utils_class->get_qual = wifi_nl80211_get_qual; - wifi_utils_class->indicate_addressing_running = wifi_nl80211_indicate_addressing_running; - wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel; - wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; - wifi_utils_class->set_mesh_ssid = wifi_nl80211_set_mesh_ssid; + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMWifiUtilsClass *wifi_utils_class = NM_WIFI_UTILS_CLASS(klass); + + object_class->dispose = dispose; + + wifi_utils_class->get_mode = wifi_nl80211_get_mode; + wifi_utils_class->set_mode = wifi_nl80211_set_mode; + wifi_utils_class->set_powersave = wifi_nl80211_set_powersave; + wifi_utils_class->get_wake_on_wlan = wifi_nl80211_get_wake_on_wlan, + wifi_utils_class->set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan, + wifi_utils_class->get_freq = wifi_nl80211_get_freq; + wifi_utils_class->find_freq = wifi_nl80211_find_freq; + wifi_utils_class->get_bssid = wifi_nl80211_get_bssid; + wifi_utils_class->get_rate = wifi_nl80211_get_rate; + wifi_utils_class->get_qual = wifi_nl80211_get_qual; + wifi_utils_class->indicate_addressing_running = wifi_nl80211_indicate_addressing_running; + wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel; + wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; + wifi_utils_class->set_mesh_ssid = wifi_nl80211_set_mesh_ssid; } NMWifiUtils * -nm_wifi_utils_nl80211_new (int ifindex, struct nl_sock *genl) +nm_wifi_utils_nl80211_new(int ifindex, struct nl_sock *genl) { - gs_unref_object NMWifiUtilsNl80211 *self = NULL; - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nl80211_device_info device_info = { }; - - if (!genl) - return NULL; - - self = g_object_new (NM_TYPE_WIFI_UTILS_NL80211, NULL); - - self->parent.ifindex = ifindex; - self->nl_sock = genl; - - self->id = genl_ctrl_resolve (self->nl_sock, "nl80211"); - if (self->id < 0) { - _LOGD ("genl_ctrl_resolve: failed to resolve \"nl80211\""); - return NULL; - } - - self->phy = -1; - - msg = nl80211_alloc_msg (self, NL80211_CMD_GET_WIPHY, 0); - - device_info.self = self; - if (nl80211_send_and_recv (self, msg, nl80211_wiphy_info_handler, - &device_info) < 0) { - _LOGD ("NL80211_CMD_GET_WIPHY request failed"); - return NULL; - } - - if (!device_info.success) { - _LOGD ("NL80211_CMD_GET_WIPHY request indicated failure"); - return NULL; - } - - if (!device_info.supported) { - _LOGD ("driver does not fully support nl80211, falling back to WEXT"); - return NULL; - } - - if (!device_info.can_scan_ssid) { - _LOGE ("driver does not support SSID scans"); - return NULL; - } - - if (device_info.num_freqs == 0 || device_info.freqs == NULL) { - _LOGE ("driver reports no supported frequencies"); - return NULL; - } - - if (device_info.caps == 0) { - _LOGE ("driver doesn't report support of any encryption"); - return NULL; - } - - self->phy = device_info.phy; - self->freqs = device_info.freqs; - self->num_freqs = device_info.num_freqs; - self->parent.caps = device_info.caps; - self->can_wowlan = device_info.can_wowlan; - - _LOGD ("using nl80211 for Wi-Fi device control"); - return (NMWifiUtils *) g_steal_pointer (&self); + gs_unref_object NMWifiUtilsNl80211 *self = NULL; + nm_auto_nlmsg struct nl_msg * msg = NULL; + struct nl80211_device_info device_info = {}; + + if (!genl) + return NULL; + + self = g_object_new(NM_TYPE_WIFI_UTILS_NL80211, NULL); + + self->parent.ifindex = ifindex; + self->nl_sock = genl; + + self->id = genl_ctrl_resolve(self->nl_sock, "nl80211"); + if (self->id < 0) { + _LOGD("genl_ctrl_resolve: failed to resolve \"nl80211\""); + return NULL; + } + + self->phy = -1; + + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_WIPHY, 0); + + device_info.self = self; + if (nl80211_send_and_recv(self, msg, nl80211_wiphy_info_handler, &device_info) < 0) { + _LOGD("NL80211_CMD_GET_WIPHY request failed"); + return NULL; + } + + if (!device_info.success) { + _LOGD("NL80211_CMD_GET_WIPHY request indicated failure"); + return NULL; + } + + if (!device_info.supported) { + _LOGD("driver does not fully support nl80211, falling back to WEXT"); + return NULL; + } + + if (!device_info.can_scan_ssid) { + _LOGE("driver does not support SSID scans"); + return NULL; + } + + if (device_info.num_freqs == 0 || device_info.freqs == NULL) { + _LOGE("driver reports no supported frequencies"); + return NULL; + } + + if (device_info.caps == 0) { + _LOGE("driver doesn't report support of any encryption"); + return NULL; + } + + self->phy = device_info.phy; + self->freqs = device_info.freqs; + self->num_freqs = device_info.num_freqs; + self->parent.caps = device_info.caps; + self->can_wowlan = device_info.can_wowlan; + + _LOGD("using nl80211 for Wi-Fi device control"); + return (NMWifiUtils *) g_steal_pointer(&self); } diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.h b/src/platform/wifi/nm-wifi-utils-nl80211.h index 45876534..59fc1acc 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.h +++ b/src/platform/wifi/nm-wifi-utils-nl80211.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2011 Intel Corporation. All rights reserved. * Copyright (C) 2018 Red Hat, Inc. @@ -10,15 +10,20 @@ #include "nm-wifi-utils.h" #include "platform/nm-netlink.h" -#define NM_TYPE_WIFI_UTILS_NL80211 (nm_wifi_utils_nl80211_get_type ()) -#define NM_WIFI_UTILS_NL80211(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211)) -#define NM_WIFI_UTILS_NL80211_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211Class)) -#define NM_IS_WIFI_UTILS_NL80211(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIFI_UTILS_NL80211)) -#define NM_IS_WIFI_UTILS_NL80211_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIFI_UTILS_NL80211)) -#define NM_WIFI_UTILS_NL80211_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211Class)) +#define NM_TYPE_WIFI_UTILS_NL80211 (nm_wifi_utils_nl80211_get_type()) +#define NM_WIFI_UTILS_NL80211(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211)) +#define NM_WIFI_UTILS_NL80211_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211Class)) +#define NM_IS_WIFI_UTILS_NL80211(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WIFI_UTILS_NL80211)) +#define NM_IS_WIFI_UTILS_NL80211_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WIFI_UTILS_NL80211)) +#define NM_WIFI_UTILS_NL80211_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WIFI_UTILS_NL80211, NMWifiUtilsNl80211Class)) -GType nm_wifi_utils_nl80211_get_type (void); +GType nm_wifi_utils_nl80211_get_type(void); -NMWifiUtils *nm_wifi_utils_nl80211_new (int ifindex, struct nl_sock *genl); +NMWifiUtils *nm_wifi_utils_nl80211_new(int ifindex, struct nl_sock *genl); -#endif /* __WIFI_UTILS_NL80211_H__ */ +#endif /* __WIFI_UTILS_NL80211_H__ */ diff --git a/src/platform/wifi/nm-wifi-utils-private.h b/src/platform/wifi/nm-wifi-utils-private.h index 53816744..1a5303a6 100644 --- a/src/platform/wifi/nm-wifi-utils-private.h +++ b/src/platform/wifi/nm-wifi-utils-private.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ @@ -10,55 +10,55 @@ #include "nm-wifi-utils.h" typedef struct { - GObjectClass parent; + GObjectClass parent; - NM80211Mode (*get_mode) (NMWifiUtils *data); + NM80211Mode (*get_mode)(NMWifiUtils *data); - gboolean (*set_mode) (NMWifiUtils *data, const NM80211Mode mode); + gboolean (*set_mode)(NMWifiUtils *data, const NM80211Mode mode); - /* Set power saving mode on an interface */ - gboolean (*set_powersave) (NMWifiUtils *data, guint32 powersave); + /* Set power saving mode on an interface */ + gboolean (*set_powersave)(NMWifiUtils *data, guint32 powersave); - /* Get WakeOnWLAN configuration on an interface */ - NMSettingWirelessWakeOnWLan (*get_wake_on_wlan) (NMWifiUtils *data); + /* Get WakeOnWLAN configuration on an interface */ + NMSettingWirelessWakeOnWLan (*get_wake_on_wlan)(NMWifiUtils *data); - /* Set WakeOnWLAN mode on an interface */ - gboolean (*set_wake_on_wlan) (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl); + /* Set WakeOnWLAN mode on an interface */ + gboolean (*set_wake_on_wlan)(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl); - /* Return current frequency in MHz (really associated BSS frequency) */ - guint32 (*get_freq) (NMWifiUtils *data); + /* Return current frequency in MHz (really associated BSS frequency) */ + guint32 (*get_freq)(NMWifiUtils *data); - /* Return first supported frequency in the zero-terminated list */ - guint32 (*find_freq) (NMWifiUtils *data, const guint32 *freqs); + /* Return first supported frequency in the zero-terminated list */ + guint32 (*find_freq)(NMWifiUtils *data, const guint32 *freqs); - /* Return current bitrate in Kbps */ - guint32 (*get_rate) (NMWifiUtils *data); + /* Return current bitrate in Kbps */ + guint32 (*get_rate)(NMWifiUtils *data); - gboolean (*get_bssid) (NMWifiUtils *data, guint8 *out_bssid); + gboolean (*get_bssid)(NMWifiUtils *data, guint8 *out_bssid); - /* Return a signal strength percentage 0 - 100% for the current BSSID; - * return -1 on errors or if not associated. - */ - int (*get_qual) (NMWifiUtils *data); + /* Return a signal strength percentage 0 - 100% for the current BSSID; + * return -1 on errors or if not associated. + */ + int (*get_qual)(NMWifiUtils *data); - /* OLPC Mesh-only functions */ + /* OLPC Mesh-only functions */ - guint32 (*get_mesh_channel) (NMWifiUtils *data); + guint32 (*get_mesh_channel)(NMWifiUtils *data); - /* channel == 0 means "auto channel" */ - gboolean (*set_mesh_channel) (NMWifiUtils *data, guint32 channel); + /* channel == 0 means "auto channel" */ + gboolean (*set_mesh_channel)(NMWifiUtils *data, guint32 channel); - /* ssid == NULL means "auto SSID" */ - gboolean (*set_mesh_ssid) (NMWifiUtils *data, const guint8 *ssid, gsize len); + /* ssid == NULL means "auto SSID" */ + gboolean (*set_mesh_ssid)(NMWifiUtils *data, const guint8 *ssid, gsize len); - gboolean (*indicate_addressing_running) (NMWifiUtils *data, gboolean running); + gboolean (*indicate_addressing_running)(NMWifiUtils *data, gboolean running); } NMWifiUtilsClass; struct NMWifiUtils { - GObject parent; + GObject parent; - int ifindex; - NMDeviceWifiCapabilities caps; + int ifindex; + NMDeviceWifiCapabilities caps; }; -#endif /* __WIFI_UTILS_PRIVATE_H__ */ +#endif /* __WIFI_UTILS_PRIVATE_H__ */ diff --git a/src/platform/wifi/nm-wifi-utils-wext.c b/src/platform/wifi/nm-wifi-utils-wext.c index 68924a35..8299415d 100644 --- a/src/platform/wifi/nm-wifi-utils-wext.c +++ b/src/platform/wifi/nm-wifi-utils-wext.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -14,7 +14,7 @@ /* Hacks necessary to #include wireless.h; yay for WEXT */ #ifndef __user -#define __user + #define __user #endif #include <sys/types.h> #include <linux/types.h> @@ -27,752 +27,779 @@ #include "nm-core-internal.h" typedef struct { - NMWifiUtils parent; - int fd; - struct iw_quality max_qual; - gint8 num_freqs; - guint32 freqs[IW_MAX_FREQUENCIES]; + NMWifiUtils parent; + int fd; + struct iw_quality max_qual; + gint8 num_freqs; + guint32 freqs[IW_MAX_FREQUENCIES]; } NMWifiUtilsWext; typedef struct { - NMWifiUtilsClass parent; + NMWifiUtilsClass parent; } NMWifiUtilsWextClass; -G_DEFINE_TYPE (NMWifiUtilsWext, nm_wifi_utils_wext, NM_TYPE_WIFI_UTILS) +G_DEFINE_TYPE(NMWifiUtilsWext, nm_wifi_utils_wext, NM_TYPE_WIFI_UTILS) /* Until a new wireless-tools comes out that has the defs and the structure, * need to copy them here. */ /* Scan capability flags - in (struct iw_range *)->scan_capa */ -#define NM_IW_SCAN_CAPA_NONE 0x00 -#define NM_IW_SCAN_CAPA_ESSID 0x01 - -struct iw_range_with_scan_capa -{ - guint32 throughput; - guint32 min_nwid; - guint32 max_nwid; - guint16 old_num_channels; - guint8 old_num_frequency; - - guint8 scan_capa; - /* don't need the rest... */ +#define NM_IW_SCAN_CAPA_NONE 0x00 +#define NM_IW_SCAN_CAPA_ESSID 0x01 + +struct iw_range_with_scan_capa { + guint32 throughput; + guint32 min_nwid; + guint32 max_nwid; + guint16 old_num_channels; + guint8 old_num_frequency; + + guint8 scan_capa; + /* don't need the rest... */ }; -#define _NMLOG_PREFIX_NAME "wifi-wext" -#define _NMLOG(level, domain, ...) \ - G_STMT_START { \ - nm_log ((level), (domain), NULL, NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } G_STMT_END +#define _NMLOG_PREFIX_NAME "wifi-wext" +#define _NMLOG(level, domain, ...) \ + G_STMT_START \ + { \ + nm_log((level), \ + (domain), \ + NULL, \ + NULL, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END static guint32 -iw_freq_to_uint32 (const struct iw_freq *freq) +iw_freq_to_uint32(const struct iw_freq *freq) { - if (freq->e == 0) { - /* Some drivers report channel not frequency. Convert to a - * frequency; but this assumes that the device is in b/g mode. - */ - if ((freq->m >= 1) && (freq->m <= 13)) - return 2407 + (5 * freq->m); - else if (freq->m == 14) - return 2484; - } - return (guint32) ((((double) freq->m) * nm_utils_exp10 (freq->e)) / 1000000.0); + if (freq->e == 0) { + /* Some drivers report channel not frequency. Convert to a + * frequency; but this assumes that the device is in b/g mode. + */ + if ((freq->m >= 1) && (freq->m <= 13)) + return 2407 + (5 * freq->m); + else if (freq->m == 14) + return 2484; + } + return (guint32)((((double) freq->m) * nm_utils_exp10(freq->e)) / 1000000.0); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMWifiUtilsWext *wext = NM_WIFI_UTILS_WEXT (object); + NMWifiUtilsWext *wext = NM_WIFI_UTILS_WEXT(object); - wext->fd = nm_close (wext->fd); + wext->fd = nm_close(wext->fd); } static gboolean -get_ifname (int ifindex, char *buffer, const char *op) +get_ifname(int ifindex, char *buffer, const char *op) { - int errsv; - - if (!nmp_utils_if_indextoname (ifindex, buffer)) { - errsv = errno; - _LOGW (LOGD_PLATFORM | LOGD_WIFI, - "error getting interface name for ifindex %d, operation '%s': %s (%d)", - ifindex, op, nm_strerror_native (errsv), errsv); - return FALSE; - } - - return TRUE; + int errsv; + + if (!nmp_utils_if_indextoname(ifindex, buffer)) { + errsv = errno; + _LOGW(LOGD_PLATFORM | LOGD_WIFI, + "error getting interface name for ifindex %d, operation '%s': %s (%d)", + ifindex, + op, + nm_strerror_native(errsv), + errsv); + return FALSE; + } + + return TRUE; } static NM80211Mode -wifi_wext_get_mode_ifname (NMWifiUtils *data, const char *ifname) +wifi_wext_get_mode_ifname(NMWifiUtils *data, const char *ifname) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - int errsv; - - memset (&wrq, 0, sizeof (struct iwreq)); - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - - if (ioctl (wext->fd, SIOCGIWMODE, &wrq) < 0) { - errsv = errno; - if (errsv != ENODEV) { - _LOGW (LOGD_PLATFORM | LOGD_WIFI, - "(%s): error %d getting card mode", - ifname, errsv); - } - return NM_802_11_MODE_UNKNOWN; - } - - switch (wrq.u.mode) { - case IW_MODE_ADHOC: - return NM_802_11_MODE_ADHOC; - case IW_MODE_MASTER: - return NM_802_11_MODE_AP; - case IW_MODE_INFRA: - case IW_MODE_AUTO: /* hack for WEXT devices reporting IW_MODE_AUTO */ - return NM_802_11_MODE_INFRA; - default: - break; - } - return NM_802_11_MODE_UNKNOWN; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + int errsv; + + memset(&wrq, 0, sizeof(struct iwreq)); + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + + if (ioctl(wext->fd, SIOCGIWMODE, &wrq) < 0) { + errsv = errno; + if (errsv != ENODEV) { + _LOGW(LOGD_PLATFORM | LOGD_WIFI, "(%s): error %d getting card mode", ifname, errsv); + } + return NM_802_11_MODE_UNKNOWN; + } + + switch (wrq.u.mode) { + case IW_MODE_ADHOC: + return NM_802_11_MODE_ADHOC; + case IW_MODE_MASTER: + return NM_802_11_MODE_AP; + case IW_MODE_INFRA: + case IW_MODE_AUTO: /* hack for WEXT devices reporting IW_MODE_AUTO */ + return NM_802_11_MODE_INFRA; + default: + break; + } + return NM_802_11_MODE_UNKNOWN; } static NM80211Mode -wifi_wext_get_mode (NMWifiUtils *data) +wifi_wext_get_mode(NMWifiUtils *data) { - char ifname[IFNAMSIZ]; + char ifname[IFNAMSIZ]; - if (!get_ifname (data->ifindex, ifname, "get-mode")) - return FALSE; + if (!get_ifname(data->ifindex, ifname, "get-mode")) + return FALSE; - return wifi_wext_get_mode_ifname (data, ifname); + return wifi_wext_get_mode_ifname(data, ifname); } static gboolean -wifi_wext_set_mode (NMWifiUtils *data, const NM80211Mode mode) +wifi_wext_set_mode(NMWifiUtils *data, const NM80211Mode mode) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname (data->ifindex, ifname, "set-mode")) - return FALSE; - - if (wifi_wext_get_mode_ifname (data, ifname) == mode) - return TRUE; - - memset (&wrq, 0, sizeof (struct iwreq)); - switch (mode) { - case NM_802_11_MODE_ADHOC: - wrq.u.mode = IW_MODE_ADHOC; - break; - case NM_802_11_MODE_AP: - wrq.u.mode = IW_MODE_MASTER; - break; - case NM_802_11_MODE_INFRA: - wrq.u.mode = IW_MODE_INFRA; - break; - default: - g_warn_if_reached (); - return FALSE; - } - - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - if (ioctl (wext->fd, SIOCSIWMODE, &wrq) < 0) { - if (errno != ENODEV) { - _LOGE (LOGD_PLATFORM | LOGD_WIFI, - "(%s): error setting mode %d", - ifname, mode); - } - return FALSE; - } - - return TRUE; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + char ifname[IFNAMSIZ]; + + if (!get_ifname(data->ifindex, ifname, "set-mode")) + return FALSE; + + if (wifi_wext_get_mode_ifname(data, ifname) == mode) + return TRUE; + + memset(&wrq, 0, sizeof(struct iwreq)); + switch (mode) { + case NM_802_11_MODE_ADHOC: + wrq.u.mode = IW_MODE_ADHOC; + break; + case NM_802_11_MODE_AP: + wrq.u.mode = IW_MODE_MASTER; + break; + case NM_802_11_MODE_INFRA: + wrq.u.mode = IW_MODE_INFRA; + break; + default: + g_warn_if_reached(); + return FALSE; + } + + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + if (ioctl(wext->fd, SIOCSIWMODE, &wrq) < 0) { + if (errno != ENODEV) { + _LOGE(LOGD_PLATFORM | LOGD_WIFI, "(%s): error setting mode %d", ifname, mode); + } + return FALSE; + } + + return TRUE; } static gboolean -wifi_wext_set_powersave (NMWifiUtils *data, guint32 powersave) +wifi_wext_set_powersave(NMWifiUtils *data, guint32 powersave) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname (data->ifindex, ifname, "set-powersave")) - return FALSE; - - memset (&wrq, 0, sizeof (struct iwreq)); - if (powersave == 1) { - wrq.u.power.flags = IW_POWER_ALL_R; - } else - wrq.u.power.disabled = 1; - - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - if (ioctl (wext->fd, SIOCSIWPOWER, &wrq) < 0) { - if (errno != ENODEV) { - _LOGE (LOGD_PLATFORM | LOGD_WIFI, - "(%s): error setting powersave %" G_GUINT32_FORMAT, - ifname, powersave); - } - return FALSE; - } - - return TRUE; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + char ifname[IFNAMSIZ]; + + if (!get_ifname(data->ifindex, ifname, "set-powersave")) + return FALSE; + + memset(&wrq, 0, sizeof(struct iwreq)); + if (powersave == 1) { + wrq.u.power.flags = IW_POWER_ALL_R; + } else + wrq.u.power.disabled = 1; + + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + if (ioctl(wext->fd, SIOCSIWPOWER, &wrq) < 0) { + if (errno != ENODEV) { + _LOGE(LOGD_PLATFORM | LOGD_WIFI, + "(%s): error setting powersave %" G_GUINT32_FORMAT, + ifname, + powersave); + } + return FALSE; + } + + return TRUE; } static guint32 -wifi_wext_get_freq (NMWifiUtils *data) +wifi_wext_get_freq(NMWifiUtils *data) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname (data->ifindex, ifname, "get-freq")) - return FALSE; - - memset (&wrq, 0, sizeof (struct iwreq)); - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - if (ioctl (wext->fd, SIOCGIWFREQ, &wrq) < 0) { - _LOGW (LOGD_PLATFORM | LOGD_WIFI, - "(%s): error getting frequency: %s", - ifname, nm_strerror_native (errno)); - return 0; - } - - return iw_freq_to_uint32 (&wrq.u.freq); + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + char ifname[IFNAMSIZ]; + + if (!get_ifname(data->ifindex, ifname, "get-freq")) + return FALSE; + + memset(&wrq, 0, sizeof(struct iwreq)); + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + if (ioctl(wext->fd, SIOCGIWFREQ, &wrq) < 0) { + _LOGW(LOGD_PLATFORM | LOGD_WIFI, + "(%s): error getting frequency: %s", + ifname, + nm_strerror_native(errno)); + return 0; + } + + return iw_freq_to_uint32(&wrq.u.freq); } static guint32 -wifi_wext_find_freq (NMWifiUtils *data, const guint32 *freqs) +wifi_wext_find_freq(NMWifiUtils *data, const guint32 *freqs) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - int i; - - for (i = 0; i < wext->num_freqs; i++) { - while (*freqs) { - if (wext->freqs[i] == *freqs) - return *freqs; - freqs++; - } - } - return 0; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + int i; + + for (i = 0; i < wext->num_freqs; i++) { + while (*freqs) { + if (wext->freqs[i] == *freqs) + return *freqs; + freqs++; + } + } + return 0; } static gboolean -wifi_wext_get_bssid (NMWifiUtils *data, guint8 *out_bssid) +wifi_wext_get_bssid(NMWifiUtils *data, guint8 *out_bssid) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname (data->ifindex, ifname, "get-bssid")) - return FALSE; - - memset (&wrq, 0, sizeof (wrq)); - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - if (ioctl (wext->fd, SIOCGIWAP, &wrq) < 0) { - _LOGW (LOGD_PLATFORM | LOGD_WIFI, - "(%s): error getting associated BSSID: %s", - ifname, nm_strerror_native (errno)); - return FALSE; - } - memcpy (out_bssid, &(wrq.u.ap_addr.sa_data), ETH_ALEN); - return TRUE; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + char ifname[IFNAMSIZ]; + + if (!get_ifname(data->ifindex, ifname, "get-bssid")) + return FALSE; + + memset(&wrq, 0, sizeof(wrq)); + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + if (ioctl(wext->fd, SIOCGIWAP, &wrq) < 0) { + _LOGW(LOGD_PLATFORM | LOGD_WIFI, + "(%s): error getting associated BSSID: %s", + ifname, + nm_strerror_native(errno)); + return FALSE; + } + memcpy(out_bssid, &(wrq.u.ap_addr.sa_data), ETH_ALEN); + return TRUE; } static guint32 -wifi_wext_get_rate (NMWifiUtils *data) +wifi_wext_get_rate(NMWifiUtils *data) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - int err; - char ifname[IFNAMSIZ]; - - if (!get_ifname (data->ifindex, ifname, "get-rate")) - return FALSE; - - memset (&wrq, 0, sizeof (wrq)); - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - err = ioctl (wext->fd, SIOCGIWRATE, &wrq); - return ((err == 0) ? wrq.u.bitrate.value / 1000 : 0); + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + int err; + char ifname[IFNAMSIZ]; + + if (!get_ifname(data->ifindex, ifname, "get-rate")) + return FALSE; + + memset(&wrq, 0, sizeof(wrq)); + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + err = ioctl(wext->fd, SIOCGIWRATE, &wrq); + return ((err == 0) ? wrq.u.bitrate.value / 1000 : 0); } static int -wext_qual_to_percent (const struct iw_quality *qual, - const struct iw_quality *max_qual) +wext_qual_to_percent(const struct iw_quality *qual, const struct iw_quality *max_qual) { - int percent = -1; - int level_percent = -1; - - g_return_val_if_fail (qual != NULL, -1); - g_return_val_if_fail (max_qual != NULL, -1); - - /* Magically convert the many different WEXT quality representations to a percentage */ - - _LOGD (LOGD_WIFI, - "QL: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X ** MAX: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X", - (__s8) qual->qual, qual->qual, qual->qual, - (__s8) qual->level, qual->level, qual->level, - (__s8) qual->noise, qual->noise, qual->noise, - qual->updated, - (__s8) max_qual->qual, max_qual->qual, max_qual->qual, - (__s8) max_qual->level, max_qual->level, max_qual->level, - (__s8) max_qual->noise, max_qual->noise, max_qual->noise, - max_qual->updated); - - /* Try using the card's idea of the signal quality first as long as it tells us what the max quality is. - * Drivers that fill in quality values MUST treat them as percentages, ie the "Link Quality" MUST be - * bounded by 0 and max_qual->qual, and MUST change in a linear fashion. Within those bounds, drivers - * are free to use whatever they want to calculate "Link Quality". - */ - if ((max_qual->qual != 0) && !(max_qual->updated & IW_QUAL_QUAL_INVALID) && !(qual->updated & IW_QUAL_QUAL_INVALID)) - percent = (int)(100 * ((double)qual->qual / (double)max_qual->qual)); - - /* If the driver doesn't specify a complete and valid quality, we have two options: - * - * 1) dBm: driver must specify max_qual->level = 0, and have valid values for - * qual->level and (qual->noise OR max_qual->noise) - * 2) raw RSSI: driver must specify max_qual->level > 0, and have valid values for - * qual->level and max_qual->level - * - * This is the WEXT spec. If this interpretation is wrong, I'll fix it. Otherwise, - * If drivers don't conform to it, they are wrong and need to be fixed. - */ - - if ( (max_qual->level == 0) && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level == 0 */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID) /* Must have valid qual->level */ - && ( ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) /* Must have valid max_qual->noise */ - || ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID))) /* OR valid qual->noise */ - ) { - /* Absolute power values (dBm) */ - - /* Reasonable fallbacks for dumb drivers that don't specify either level. */ - #define FALLBACK_NOISE_FLOOR_DBM -90 - #define FALLBACK_SIGNAL_MAX_DBM -20 - int max_level = FALLBACK_SIGNAL_MAX_DBM; - int noise = FALLBACK_NOISE_FLOOR_DBM; - int level = qual->level - 0x100; - - level = CLAMP (level, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); - - if ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID)) - noise = qual->noise - 0x100; - else if ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) - noise = max_qual->noise - 0x100; - noise = CLAMP (noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM - 1); - - /* A sort of signal-to-noise ratio calculation */ - level_percent = (int) (100 - 70 * (((double)max_level - (double)level) / - ((double)max_level - (double)noise))); - _LOGD (LOGD_WIFI, "QL1: level_percent is %d. max_level %d, level %d, noise_floor %d.", - level_percent, max_level, level, noise); - } else if ( (max_qual->level != 0) - && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level as upper bound */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID)) { - /* Relative power values (RSSI) */ - - int level = qual->level; - - /* Signal level is relavtive (0 -> max_qual->level) */ - level = CLAMP (level, 0, max_qual->level); - level_percent = (int)(100 * ((double)level / (double)max_qual->level)); - _LOGD (LOGD_WIFI, "QL2: level_percent is %d. max_level %d, level %d.", - level_percent, max_qual->level, level); - } else if (percent == -1) { - _LOGD (LOGD_WIFI, "QL: Could not get quality %% value from driver. Driver is probably buggy."); - } - - /* If the quality percent was 0 or doesn't exist, then try to use signal levels instead */ - if ((percent < 1) && (level_percent >= 0)) - percent = level_percent; - - _LOGD (LOGD_WIFI, "QL: Final quality percent is %d (%d).", - percent, CLAMP (percent, 0, 100)); - return (CLAMP (percent, 0, 100)); + int percent = -1; + int level_percent = -1; + + g_return_val_if_fail(qual != NULL, -1); + g_return_val_if_fail(max_qual != NULL, -1); + + /* Magically convert the many different WEXT quality representations to a percentage */ + + _LOGD(LOGD_WIFI, + "QL: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X ** MAX: qual " + "%d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X", + (__s8) qual->qual, + qual->qual, + qual->qual, + (__s8) qual->level, + qual->level, + qual->level, + (__s8) qual->noise, + qual->noise, + qual->noise, + qual->updated, + (__s8) max_qual->qual, + max_qual->qual, + max_qual->qual, + (__s8) max_qual->level, + max_qual->level, + max_qual->level, + (__s8) max_qual->noise, + max_qual->noise, + max_qual->noise, + max_qual->updated); + + /* Try using the card's idea of the signal quality first as long as it tells us what the max quality is. + * Drivers that fill in quality values MUST treat them as percentages, ie the "Link Quality" MUST be + * bounded by 0 and max_qual->qual, and MUST change in a linear fashion. Within those bounds, drivers + * are free to use whatever they want to calculate "Link Quality". + */ + if ((max_qual->qual != 0) && !(max_qual->updated & IW_QUAL_QUAL_INVALID) + && !(qual->updated & IW_QUAL_QUAL_INVALID)) + percent = (int) (100 * ((double) qual->qual / (double) max_qual->qual)); + + /* If the driver doesn't specify a complete and valid quality, we have two options: + * + * 1) dBm: driver must specify max_qual->level = 0, and have valid values for + * qual->level and (qual->noise OR max_qual->noise) + * 2) raw RSSI: driver must specify max_qual->level > 0, and have valid values for + * qual->level and max_qual->level + * + * This is the WEXT spec. If this interpretation is wrong, I'll fix it. Otherwise, + * If drivers don't conform to it, they are wrong and need to be fixed. + */ + + if ((max_qual->level == 0) + && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level == 0 */ + && !(qual->updated & IW_QUAL_LEVEL_INVALID) /* Must have valid qual->level */ + && (((max_qual->noise > 0) + && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) /* Must have valid max_qual->noise */ + || ((qual->noise > 0) + && !(qual->updated & IW_QUAL_NOISE_INVALID))) /* OR valid qual->noise */ + ) { +/* Absolute power values (dBm) */ + +/* Reasonable fallbacks for dumb drivers that don't specify either level. */ +#define FALLBACK_NOISE_FLOOR_DBM -90 +#define FALLBACK_SIGNAL_MAX_DBM -20 + int max_level = FALLBACK_SIGNAL_MAX_DBM; + int noise = FALLBACK_NOISE_FLOOR_DBM; + int level = qual->level - 0x100; + + level = CLAMP(level, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); + + if ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID)) + noise = qual->noise - 0x100; + else if ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) + noise = max_qual->noise - 0x100; + noise = CLAMP(noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM - 1); + + /* A sort of signal-to-noise ratio calculation */ + level_percent = (int) (100 + - 70 + * (((double) max_level - (double) level) + / ((double) max_level - (double) noise))); + _LOGD(LOGD_WIFI, + "QL1: level_percent is %d. max_level %d, level %d, noise_floor %d.", + level_percent, + max_level, + level, + noise); + } else if ((max_qual->level != 0) + && !(max_qual->updated + & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level as upper bound */ + && !(qual->updated & IW_QUAL_LEVEL_INVALID)) { + /* Relative power values (RSSI) */ + + int level = qual->level; + + /* Signal level is relavtive (0 -> max_qual->level) */ + level = CLAMP(level, 0, max_qual->level); + level_percent = (int) (100 * ((double) level / (double) max_qual->level)); + _LOGD(LOGD_WIFI, + "QL2: level_percent is %d. max_level %d, level %d.", + level_percent, + max_qual->level, + level); + } else if (percent == -1) { + _LOGD(LOGD_WIFI, + "QL: Could not get quality %% value from driver. Driver is probably buggy."); + } + + /* If the quality percent was 0 or doesn't exist, then try to use signal levels instead */ + if ((percent < 1) && (level_percent >= 0)) + percent = level_percent; + + _LOGD(LOGD_WIFI, "QL: Final quality percent is %d (%d).", percent, CLAMP(percent, 0, 100)); + return (CLAMP(percent, 0, 100)); } static int -wifi_wext_get_qual (NMWifiUtils *data) +wifi_wext_get_qual(NMWifiUtils *data) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - struct iw_statistics stats; - char ifname[IFNAMSIZ]; - - if (!get_ifname (data->ifindex, ifname, "get-qual")) - return FALSE; - - memset (&stats, 0, sizeof (stats)); - wrq.u.data.pointer = &stats; - wrq.u.data.length = sizeof (stats); - wrq.u.data.flags = 1; /* Clear updated flag */ - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - - if (ioctl (wext->fd, SIOCGIWSTATS, &wrq) < 0) { - _LOGW (LOGD_PLATFORM | LOGD_WIFI, - "(%s): error getting signal strength: %s", - ifname, nm_strerror_native (errno)); - return -1; - } - - return wext_qual_to_percent (&stats.qual, &wext->max_qual); + NMWifiUtilsWext * wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + struct iw_statistics stats; + char ifname[IFNAMSIZ]; + + if (!get_ifname(data->ifindex, ifname, "get-qual")) + return FALSE; + + memset(&stats, 0, sizeof(stats)); + wrq.u.data.pointer = &stats; + wrq.u.data.length = sizeof(stats); + wrq.u.data.flags = 1; /* Clear updated flag */ + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + + if (ioctl(wext->fd, SIOCGIWSTATS, &wrq) < 0) { + _LOGW(LOGD_PLATFORM | LOGD_WIFI, + "(%s): error getting signal strength: %s", + ifname, + nm_strerror_native(errno)); + return -1; + } + + return wext_qual_to_percent(&stats.qual, &wext->max_qual); } /*****************************************************************************/ /* OLPC Mesh-only functions */ static guint32 -wifi_wext_get_mesh_channel (NMWifiUtils *data) +wifi_wext_get_mesh_channel(NMWifiUtils *data) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - guint32 freq; - int i; - - freq = nm_wifi_utils_get_freq (data); - for (i = 0; i < wext->num_freqs; i++) { - if (freq == wext->freqs[i]) - return i + 1; - } - return 0; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + guint32 freq; + int i; + + freq = nm_wifi_utils_get_freq(data); + for (i = 0; i < wext->num_freqs; i++) { + if (freq == wext->freqs[i]) + return i + 1; + } + return 0; } static gboolean -wifi_wext_set_mesh_channel (NMWifiUtils *data, guint32 channel) +wifi_wext_set_mesh_channel(NMWifiUtils *data, guint32 channel) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char ifname[IFNAMSIZ]; - - if (!get_ifname (data->ifindex, ifname, "set-mesh-channel")) - return FALSE; - - memset (&wrq, 0, sizeof (struct iwreq)); - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - - if (channel > 0) { - wrq.u.freq.flags = IW_FREQ_FIXED; - wrq.u.freq.e = 0; - wrq.u.freq.m = channel; - } - - if (ioctl (wext->fd, SIOCSIWFREQ, &wrq) < 0) { - _LOGE (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, - "(%s): error setting channel to %d: %s", - ifname, channel, nm_strerror_native (errno)); - return FALSE; - } - - return TRUE; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + char ifname[IFNAMSIZ]; + + if (!get_ifname(data->ifindex, ifname, "set-mesh-channel")) + return FALSE; + + memset(&wrq, 0, sizeof(struct iwreq)); + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + + if (channel > 0) { + wrq.u.freq.flags = IW_FREQ_FIXED; + wrq.u.freq.e = 0; + wrq.u.freq.m = channel; + } + + if (ioctl(wext->fd, SIOCSIWFREQ, &wrq) < 0) { + _LOGE(LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, + "(%s): error setting channel to %d: %s", + ifname, + channel, + nm_strerror_native(errno)); + return FALSE; + } + + return TRUE; } static gboolean -wifi_wext_set_mesh_ssid (NMWifiUtils *data, const guint8 *ssid, gsize len) +wifi_wext_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len) { - NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; - struct iwreq wrq; - char buf[IW_ESSID_MAX_SIZE + 1]; - char ifname[IFNAMSIZ]; - int errsv; - - if (!get_ifname (data->ifindex, ifname, "set-mesh-ssid")) - return FALSE; - - memset (buf, 0, sizeof (buf)); - memcpy (buf, ssid, MIN (sizeof (buf) - 1, len)); - - wrq.u.essid.pointer = (caddr_t) buf; - wrq.u.essid.length = len; - wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ - - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - if (ioctl (wext->fd, SIOCSIWESSID, &wrq) == 0) - return TRUE; - - errsv = errno; - if (errsv != ENODEV) { - gs_free char *ssid_str = NULL; - - _LOGE (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, - "(%s): error setting SSID to %s: %s", - ifname, - (ssid_str = _nm_utils_ssid_to_string_arr (ssid, len)), - nm_strerror_native (errsv)); - } - - return FALSE; + NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; + struct iwreq wrq; + char buf[IW_ESSID_MAX_SIZE + 1]; + char ifname[IFNAMSIZ]; + int errsv; + + if (!get_ifname(data->ifindex, ifname, "set-mesh-ssid")) + return FALSE; + + memset(buf, 0, sizeof(buf)); + memcpy(buf, ssid, MIN(sizeof(buf) - 1, len)); + + wrq.u.essid.pointer = (caddr_t) buf; + wrq.u.essid.length = len; + wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ + + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + if (ioctl(wext->fd, SIOCSIWESSID, &wrq) == 0) + return TRUE; + + errsv = errno; + if (errsv != ENODEV) { + gs_free char *ssid_str = NULL; + + _LOGE(LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC, + "(%s): error setting SSID to %s: %s", + ifname, + (ssid_str = _nm_utils_ssid_to_string_arr(ssid, len)), + nm_strerror_native(errsv)); + } + + return FALSE; } /*****************************************************************************/ static gboolean -wext_can_scan_ifname (NMWifiUtilsWext *wext, const char *ifname) +wext_can_scan_ifname(NMWifiUtilsWext *wext, const char *ifname) { - struct iwreq wrq; - - memset (&wrq, 0, sizeof (struct iwreq)); - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - if (ioctl (wext->fd, SIOCSIWSCAN, &wrq) < 0) { - if (errno == EOPNOTSUPP) - return FALSE; - } - return TRUE; + struct iwreq wrq; + + memset(&wrq, 0, sizeof(struct iwreq)); + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + if (ioctl(wext->fd, SIOCSIWSCAN, &wrq) < 0) { + if (errno == EOPNOTSUPP) + return FALSE; + } + return TRUE; } static gboolean -wext_get_range_ifname (NMWifiUtilsWext *wext, - const char *ifname, - struct iw_range *range, - guint32 *response_len) +wext_get_range_ifname(NMWifiUtilsWext *wext, + const char * ifname, + struct iw_range *range, + guint32 * response_len) { - int i = 26; - gboolean success = FALSE; - struct iwreq wrq; - int errsv; - - memset (&wrq, 0, sizeof (struct iwreq)); - nm_utils_ifname_cpy (wrq.ifr_name, ifname); - wrq.u.data.pointer = (caddr_t) range; - wrq.u.data.length = sizeof (struct iw_range); - - /* Need to give some drivers time to recover after suspend/resume - * (ex ipw3945 takes a few seconds to talk to its regulatory daemon; - * see rh bz#362421) - */ - while (i-- > 0) { - if (ioctl (wext->fd, SIOCGIWRANGE, &wrq) == 0) { - if (response_len) - *response_len = wrq.u.data.length; - success = TRUE; - break; - } else { - errsv = errno; - if (errsv != EAGAIN) { - _LOGE (LOGD_PLATFORM | LOGD_WIFI, - "(%s): couldn't get driver range information (%d).", - ifname, errsv); - break; - } - } - - g_usleep (G_USEC_PER_SEC / 4); - } - - if (i <= 0) { - _LOGW (LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver took too long to respond to IWRANGE query.", - ifname); - } - - return success; + int i = 26; + gboolean success = FALSE; + struct iwreq wrq; + int errsv; + + memset(&wrq, 0, sizeof(struct iwreq)); + nm_utils_ifname_cpy(wrq.ifr_name, ifname); + wrq.u.data.pointer = (caddr_t) range; + wrq.u.data.length = sizeof(struct iw_range); + + /* Need to give some drivers time to recover after suspend/resume + * (ex ipw3945 takes a few seconds to talk to its regulatory daemon; + * see rh bz#362421) + */ + while (i-- > 0) { + if (ioctl(wext->fd, SIOCGIWRANGE, &wrq) == 0) { + if (response_len) + *response_len = wrq.u.data.length; + success = TRUE; + break; + } else { + errsv = errno; + if (errsv != EAGAIN) { + _LOGE(LOGD_PLATFORM | LOGD_WIFI, + "(%s): couldn't get driver range information (%d).", + ifname, + errsv); + break; + } + } + + g_usleep(G_USEC_PER_SEC / 4); + } + + if (i <= 0) { + _LOGW(LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver took too long to respond to IWRANGE query.", + ifname); + } + + return success; } -#define WPA_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | \ - NM_WIFI_DEVICE_CAP_CIPHER_CCMP | \ - NM_WIFI_DEVICE_CAP_WPA | \ - NM_WIFI_DEVICE_CAP_RSN) +#define WPA_CAPS \ + (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_WPA \ + | NM_WIFI_DEVICE_CAP_RSN) static guint32 -wext_get_caps (NMWifiUtilsWext *wext, const char *ifname, struct iw_range *range) +wext_get_caps(NMWifiUtilsWext *wext, const char *ifname, struct iw_range *range) { - guint32 caps = NM_WIFI_DEVICE_CAP_NONE; - - g_return_val_if_fail (wext != NULL, NM_WIFI_DEVICE_CAP_NONE); - g_return_val_if_fail (range != NULL, NM_WIFI_DEVICE_CAP_NONE); - - /* All drivers should support WEP by default */ - caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104; - - if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) - caps |= NM_WIFI_DEVICE_CAP_CIPHER_TKIP; - - if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) - caps |= NM_WIFI_DEVICE_CAP_CIPHER_CCMP; - - if (range->enc_capa & IW_ENC_CAPA_WPA) - caps |= NM_WIFI_DEVICE_CAP_WPA; - - if (range->enc_capa & IW_ENC_CAPA_WPA2) - caps |= NM_WIFI_DEVICE_CAP_RSN; - - /* Check for cipher support but not WPA support */ - if ( (caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) - && !(caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN))) { - _LOGW (LOGD_WIFI, - "%s: device supports WPA ciphers but not WPA protocol; WPA unavailable.", - ifname); - caps &= ~WPA_CAPS; - } - - /* Check for WPA support but not cipher support */ - if ( (caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN)) - && !(caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP))) { - _LOGW (LOGD_WIFI, - "%s: device supports WPA protocol but not WPA ciphers; WPA unavailable.", - ifname); - caps &= ~WPA_CAPS; - } - - /* There's no way to detect Ad-Hoc/AP mode support with WEXT - * (other than actually trying to do it), so just assume that - * Ad-Hoc is supported and AP isn't. - */ - caps |= NM_WIFI_DEVICE_CAP_ADHOC; - - return caps; + guint32 caps = NM_WIFI_DEVICE_CAP_NONE; + + g_return_val_if_fail(wext != NULL, NM_WIFI_DEVICE_CAP_NONE); + g_return_val_if_fail(range != NULL, NM_WIFI_DEVICE_CAP_NONE); + + /* All drivers should support WEP by default */ + caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104; + + if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) + caps |= NM_WIFI_DEVICE_CAP_CIPHER_TKIP; + + if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) + caps |= NM_WIFI_DEVICE_CAP_CIPHER_CCMP; + + if (range->enc_capa & IW_ENC_CAPA_WPA) + caps |= NM_WIFI_DEVICE_CAP_WPA; + + if (range->enc_capa & IW_ENC_CAPA_WPA2) + caps |= NM_WIFI_DEVICE_CAP_RSN; + + /* Check for cipher support but not WPA support */ + if ((caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + && !(caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN))) { + _LOGW(LOGD_WIFI, + "%s: device supports WPA ciphers but not WPA protocol; WPA unavailable.", + ifname); + caps &= ~WPA_CAPS; + } + + /* Check for WPA support but not cipher support */ + if ((caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN)) + && !(caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP))) { + _LOGW(LOGD_WIFI, + "%s: device supports WPA protocol but not WPA ciphers; WPA unavailable.", + ifname); + caps &= ~WPA_CAPS; + } + + /* There's no way to detect Ad-Hoc/AP mode support with WEXT + * (other than actually trying to do it), so just assume that + * Ad-Hoc is supported and AP isn't. + */ + caps |= NM_WIFI_DEVICE_CAP_ADHOC; + + return caps; } /*****************************************************************************/ static void -nm_wifi_utils_wext_init (NMWifiUtilsWext *self) -{ -} +nm_wifi_utils_wext_init(NMWifiUtilsWext *self) +{} static void -nm_wifi_utils_wext_class_init (NMWifiUtilsWextClass *klass) +nm_wifi_utils_wext_class_init(NMWifiUtilsWextClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMWifiUtilsClass *wifi_utils_class = NM_WIFI_UTILS_CLASS (klass); - - object_class->dispose = dispose; - - wifi_utils_class->get_mode = wifi_wext_get_mode; - wifi_utils_class->set_mode = wifi_wext_set_mode; - wifi_utils_class->set_powersave = wifi_wext_set_powersave; - wifi_utils_class->get_freq = wifi_wext_get_freq; - wifi_utils_class->find_freq = wifi_wext_find_freq; - wifi_utils_class->get_bssid = wifi_wext_get_bssid; - wifi_utils_class->get_rate = wifi_wext_get_rate; - wifi_utils_class->get_qual = wifi_wext_get_qual; - wifi_utils_class->get_mesh_channel = wifi_wext_get_mesh_channel; - wifi_utils_class->set_mesh_channel = wifi_wext_set_mesh_channel; - wifi_utils_class->set_mesh_ssid = wifi_wext_set_mesh_ssid; + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMWifiUtilsClass *wifi_utils_class = NM_WIFI_UTILS_CLASS(klass); + + object_class->dispose = dispose; + + wifi_utils_class->get_mode = wifi_wext_get_mode; + wifi_utils_class->set_mode = wifi_wext_set_mode; + wifi_utils_class->set_powersave = wifi_wext_set_powersave; + wifi_utils_class->get_freq = wifi_wext_get_freq; + wifi_utils_class->find_freq = wifi_wext_find_freq; + wifi_utils_class->get_bssid = wifi_wext_get_bssid; + wifi_utils_class->get_rate = wifi_wext_get_rate; + wifi_utils_class->get_qual = wifi_wext_get_qual; + wifi_utils_class->get_mesh_channel = wifi_wext_get_mesh_channel; + wifi_utils_class->set_mesh_channel = wifi_wext_set_mesh_channel; + wifi_utils_class->set_mesh_ssid = wifi_wext_set_mesh_ssid; } NMWifiUtils * -nm_wifi_utils_wext_new (int ifindex, gboolean check_scan) +nm_wifi_utils_wext_new(int ifindex, gboolean check_scan) { - NMWifiUtilsWext *wext; - struct iw_range range; - guint32 response_len = 0; - struct iw_range_with_scan_capa *scan_capa_range; - int i; - gboolean freq_valid = FALSE, has_5ghz = FALSE, has_2ghz = FALSE; - char ifname[IFNAMSIZ]; - - if (!nmp_utils_if_indextoname (ifindex, ifname)) { - _LOGW (LOGD_PLATFORM | LOGD_WIFI, - "can't determine interface name for ifindex %d", ifindex); - return NULL; - } - - wext = g_object_new (NM_TYPE_WIFI_UTILS_WEXT, NULL); - - wext->parent.ifindex = ifindex; - wext->fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (wext->fd < 0) - goto error; - - memset (&range, 0, sizeof (struct iw_range)); - if (wext_get_range_ifname (wext, ifname, &range, &response_len) == FALSE) { - _LOGI (LOGD_PLATFORM | LOGD_WIFI, "(%s): driver WEXT range request failed", - ifname); - goto error; - } - - if ((response_len < 300) || (range.we_version_compiled < 21)) { - _LOGI (LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver WEXT version too old (got %d, expected >= 21)", - ifname, - range.we_version_compiled); - goto error; - } - - wext->max_qual.qual = range.max_qual.qual; - wext->max_qual.level = range.max_qual.level; - wext->max_qual.noise = range.max_qual.noise; - wext->max_qual.updated = range.max_qual.updated; - - wext->num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES); - for (i = 0; i < wext->num_freqs; i++) { - wext->freqs[i] = iw_freq_to_uint32 (&range.freq[i]); - freq_valid = TRUE; - if (wext->freqs[i] > 2400 && wext->freqs[i] < 2500) - has_2ghz = TRUE; - else if (wext->freqs[i] > 4900 && wext->freqs[i] < 6000) - has_5ghz = TRUE; - } - - /* Check for scanning capability; cards that can't scan are not supported */ - if (check_scan && (wext_can_scan_ifname (wext, ifname) == FALSE)) { - _LOGI (LOGD_PLATFORM | LOGD_WIFI, - "(%s): drivers that cannot scan are unsupported", - ifname); - goto error; - } - - /* Check for the ability to scan specific SSIDs. Until the scan_capa - * field gets added to wireless-tools, need to work around that by casting - * to the custom structure. - */ - scan_capa_range = (struct iw_range_with_scan_capa *) ⦥ - if (scan_capa_range->scan_capa & NM_IW_SCAN_CAPA_ESSID) { - _LOGI (LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver supports SSID scans (scan_capa 0x%02X).", - ifname, - scan_capa_range->scan_capa); - } else { - _LOGI (LOGD_PLATFORM | LOGD_WIFI, - "(%s): driver does not support SSID scans (scan_capa 0x%02X).", - ifname, - scan_capa_range->scan_capa); - } - - wext->parent.caps = wext_get_caps (wext, ifname, &range); - if (freq_valid) - wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID; - if (has_2ghz) - wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_2GHZ; - if (has_5ghz) - wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_5GHZ; - - _LOGI (LOGD_PLATFORM | LOGD_WIFI, - "(%s): using WEXT for Wi-Fi device control", - ifname); - - return (NMWifiUtils *) wext; + NMWifiUtilsWext * wext; + struct iw_range range; + guint32 response_len = 0; + struct iw_range_with_scan_capa *scan_capa_range; + int i; + gboolean freq_valid = FALSE, has_5ghz = FALSE, has_2ghz = FALSE; + char ifname[IFNAMSIZ]; + + if (!nmp_utils_if_indextoname(ifindex, ifname)) { + _LOGW(LOGD_PLATFORM | LOGD_WIFI, "can't determine interface name for ifindex %d", ifindex); + return NULL; + } + + wext = g_object_new(NM_TYPE_WIFI_UTILS_WEXT, NULL); + + wext->parent.ifindex = ifindex; + wext->fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (wext->fd < 0) + goto error; + + memset(&range, 0, sizeof(struct iw_range)); + if (wext_get_range_ifname(wext, ifname, &range, &response_len) == FALSE) { + _LOGI(LOGD_PLATFORM | LOGD_WIFI, "(%s): driver WEXT range request failed", ifname); + goto error; + } + + if ((response_len < 300) || (range.we_version_compiled < 21)) { + _LOGI(LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver WEXT version too old (got %d, expected >= 21)", + ifname, + range.we_version_compiled); + goto error; + } + + wext->max_qual.qual = range.max_qual.qual; + wext->max_qual.level = range.max_qual.level; + wext->max_qual.noise = range.max_qual.noise; + wext->max_qual.updated = range.max_qual.updated; + + wext->num_freqs = MIN(range.num_frequency, IW_MAX_FREQUENCIES); + for (i = 0; i < wext->num_freqs; i++) { + wext->freqs[i] = iw_freq_to_uint32(&range.freq[i]); + freq_valid = TRUE; + if (wext->freqs[i] > 2400 && wext->freqs[i] < 2500) + has_2ghz = TRUE; + else if (wext->freqs[i] > 4900 && wext->freqs[i] < 6000) + has_5ghz = TRUE; + } + + /* Check for scanning capability; cards that can't scan are not supported */ + if (check_scan && (wext_can_scan_ifname(wext, ifname) == FALSE)) { + _LOGI(LOGD_PLATFORM | LOGD_WIFI, "(%s): drivers that cannot scan are unsupported", ifname); + goto error; + } + + /* Check for the ability to scan specific SSIDs. Until the scan_capa + * field gets added to wireless-tools, need to work around that by casting + * to the custom structure. + */ + scan_capa_range = (struct iw_range_with_scan_capa *) ⦥ + if (scan_capa_range->scan_capa & NM_IW_SCAN_CAPA_ESSID) { + _LOGI(LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver supports SSID scans (scan_capa 0x%02X).", + ifname, + scan_capa_range->scan_capa); + } else { + _LOGI(LOGD_PLATFORM | LOGD_WIFI, + "(%s): driver does not support SSID scans (scan_capa 0x%02X).", + ifname, + scan_capa_range->scan_capa); + } + + wext->parent.caps = wext_get_caps(wext, ifname, &range); + if (freq_valid) + wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID; + if (has_2ghz) + wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_2GHZ; + if (has_5ghz) + wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_5GHZ; + + _LOGI(LOGD_PLATFORM | LOGD_WIFI, "(%s): using WEXT for Wi-Fi device control", ifname); + + return (NMWifiUtils *) wext; error: - g_object_unref (wext); - return NULL; + g_object_unref(wext); + return NULL; } gboolean -nm_wifi_utils_wext_is_wifi (const char *iface) +nm_wifi_utils_wext_is_wifi(const char *iface) { - int fd; - struct iwreq iwr; - gboolean is_wifi = FALSE; - - /* performing an ioctl on a non-existing name may cause the automatic - * loading of kernel modules, which should be avoided. - * - * Usually, we should thus make sure that an interface with this name - * exists. - * - * Note that wifi_wext_is_wifi() has only one caller which just verified - * that an interface with this name exists. - */ - - fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (fd >= 0) { - nm_utils_ifname_cpy (iwr.ifr_ifrn.ifrn_name, iface); - if (ioctl (fd, SIOCGIWNAME, &iwr) == 0) - is_wifi = TRUE; - nm_close (fd); - } - return is_wifi; + int fd; + struct iwreq iwr; + gboolean is_wifi = FALSE; + + /* performing an ioctl on a non-existing name may cause the automatic + * loading of kernel modules, which should be avoided. + * + * Usually, we should thus make sure that an interface with this name + * exists. + * + * Note that wifi_wext_is_wifi() has only one caller which just verified + * that an interface with this name exists. + */ + + fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd >= 0) { + nm_utils_ifname_cpy(iwr.ifr_ifrn.ifrn_name, iface); + if (ioctl(fd, SIOCGIWNAME, &iwr) == 0) + is_wifi = TRUE; + nm_close(fd); + } + return is_wifi; } diff --git a/src/platform/wifi/nm-wifi-utils-wext.h b/src/platform/wifi/nm-wifi-utils-wext.h index ce76f68d..210b87e5 100644 --- a/src/platform/wifi/nm-wifi-utils-wext.h +++ b/src/platform/wifi/nm-wifi-utils-wext.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ @@ -8,17 +8,21 @@ #include "nm-wifi-utils.h" -#define NM_TYPE_WIFI_UTILS_WEXT (nm_wifi_utils_wext_get_type ()) -#define NM_WIFI_UTILS_WEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWext)) -#define NM_WIFI_UTILS_WEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWextClass)) -#define NM_IS_WIFI_UTILS_WEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIFI_UTILS_WEXT)) -#define NM_IS_WIFI_UTILS_WEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIFI_UTILS_WEXT)) -#define NM_WIFI_UTILS_WEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWextClass)) +#define NM_TYPE_WIFI_UTILS_WEXT (nm_wifi_utils_wext_get_type()) +#define NM_WIFI_UTILS_WEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWext)) +#define NM_WIFI_UTILS_WEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWextClass)) +#define NM_IS_WIFI_UTILS_WEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WIFI_UTILS_WEXT)) +#define NM_IS_WIFI_UTILS_WEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WIFI_UTILS_WEXT)) +#define NM_WIFI_UTILS_WEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WIFI_UTILS_WEXT, NMWifiUtilsWextClass)) -GType nm_wifi_utils_wext_get_type (void); +GType nm_wifi_utils_wext_get_type(void); -NMWifiUtils *nm_wifi_utils_wext_new (int ifindex, gboolean check_scan); +NMWifiUtils *nm_wifi_utils_wext_new(int ifindex, gboolean check_scan); -gboolean nm_wifi_utils_wext_is_wifi (const char *iface); +gboolean nm_wifi_utils_wext_is_wifi(const char *iface); -#endif /* __WIFI_UTILS_WEXT_H__ */ +#endif /* __WIFI_UTILS_WEXT_H__ */ diff --git a/src/platform/wifi/nm-wifi-utils.c b/src/platform/wifi/nm-wifi-utils.c index 39ce9b09..3f9d3a48 100644 --- a/src/platform/wifi/nm-wifi-utils.c +++ b/src/platform/wifi/nm-wifi-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -15,211 +15,210 @@ #include "nm-wifi-utils-private.h" #include "nm-wifi-utils-nl80211.h" #if HAVE_WEXT -#include "nm-wifi-utils-wext.h" + #include "nm-wifi-utils-wext.h" #endif #include "nm-core-utils.h" #include "platform/nm-platform-utils.h" -G_DEFINE_ABSTRACT_TYPE (NMWifiUtils, nm_wifi_utils, G_TYPE_OBJECT) +G_DEFINE_ABSTRACT_TYPE(NMWifiUtils, nm_wifi_utils, G_TYPE_OBJECT) /*****************************************************************************/ static void -nm_wifi_utils_init (NMWifiUtils *self) -{ -} +nm_wifi_utils_init(NMWifiUtils *self) +{} static void -nm_wifi_utils_class_init (NMWifiUtilsClass *klass) -{ -} +nm_wifi_utils_class_init(NMWifiUtilsClass *klass) +{} NMWifiUtils * -nm_wifi_utils_new (int ifindex, struct nl_sock *genl, gboolean check_scan) +nm_wifi_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan) { - NMWifiUtils *ret; + NMWifiUtils *ret; - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail(ifindex > 0, NULL); - ret = nm_wifi_utils_nl80211_new (ifindex, genl); + ret = nm_wifi_utils_nl80211_new(ifindex, genl); #if HAVE_WEXT - if (ret == NULL) - ret = nm_wifi_utils_wext_new (ifindex, check_scan); + if (ret == NULL) + ret = nm_wifi_utils_wext_new(ifindex, check_scan); #endif - return ret; + return ret; } NMDeviceWifiCapabilities -nm_wifi_utils_get_caps (NMWifiUtils *data) +nm_wifi_utils_get_caps(NMWifiUtils *data) { - g_return_val_if_fail (data != NULL, NM_WIFI_DEVICE_CAP_NONE); + g_return_val_if_fail(data != NULL, NM_WIFI_DEVICE_CAP_NONE); - return data->caps; + return data->caps; } NM80211Mode -nm_wifi_utils_get_mode (NMWifiUtils *data) +nm_wifi_utils_get_mode(NMWifiUtils *data) { - g_return_val_if_fail (data != NULL, NM_802_11_MODE_UNKNOWN); - return NM_WIFI_UTILS_GET_CLASS (data)->get_mode (data); + g_return_val_if_fail(data != NULL, NM_802_11_MODE_UNKNOWN); + return NM_WIFI_UTILS_GET_CLASS(data)->get_mode(data); } gboolean -nm_wifi_utils_set_mode (NMWifiUtils *data, const NM80211Mode mode) +nm_wifi_utils_set_mode(NMWifiUtils *data, const NM80211Mode mode) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail ( (mode == NM_802_11_MODE_INFRA) - || (mode == NM_802_11_MODE_AP) - || (mode == NM_802_11_MODE_ADHOC) - || (mode == NM_802_11_MODE_MESH), FALSE); + g_return_val_if_fail(data != NULL, FALSE); + g_return_val_if_fail((mode == NM_802_11_MODE_INFRA) || (mode == NM_802_11_MODE_AP) + || (mode == NM_802_11_MODE_ADHOC) || (mode == NM_802_11_MODE_MESH), + FALSE); - klass = NM_WIFI_UTILS_GET_CLASS (data); + klass = NM_WIFI_UTILS_GET_CLASS(data); - /* nl80211 probably doesn't need this */ - return klass->set_mode ? klass->set_mode (data, mode) : TRUE; + /* nl80211 probably doesn't need this */ + return klass->set_mode ? klass->set_mode(data, mode) : TRUE; } gboolean -nm_wifi_utils_set_powersave (NMWifiUtils *data, guint32 powersave) +nm_wifi_utils_set_powersave(NMWifiUtils *data, guint32 powersave) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail(data != NULL, FALSE); - klass = NM_WIFI_UTILS_GET_CLASS (data); - return klass->set_powersave ? klass->set_powersave (data, powersave) : TRUE; + klass = NM_WIFI_UTILS_GET_CLASS(data); + return klass->set_powersave ? klass->set_powersave(data, powersave) : TRUE; } NMSettingWirelessWakeOnWLan -nm_wifi_utils_get_wake_on_wlan (NMWifiUtils *data) +nm_wifi_utils_get_wake_on_wlan(NMWifiUtils *data) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE); + g_return_val_if_fail(data != NULL, NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE); - klass = NM_WIFI_UTILS_GET_CLASS (data); + klass = NM_WIFI_UTILS_GET_CLASS(data); - return klass->get_wake_on_wlan ? klass->get_wake_on_wlan (data) : NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; + return klass->get_wake_on_wlan ? klass->get_wake_on_wlan(data) + : NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE; } gboolean -nm_wifi_utils_set_wake_on_wlan (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl) +nm_wifi_utils_set_wake_on_wlan(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail(data != NULL, FALSE); - klass = NM_WIFI_UTILS_GET_CLASS (data); - return klass->set_wake_on_wlan ? klass->set_wake_on_wlan (data, wowl) : FALSE; + klass = NM_WIFI_UTILS_GET_CLASS(data); + return klass->set_wake_on_wlan ? klass->set_wake_on_wlan(data, wowl) : FALSE; } guint32 -nm_wifi_utils_get_freq (NMWifiUtils *data) +nm_wifi_utils_get_freq(NMWifiUtils *data) { - g_return_val_if_fail (data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS (data)->get_freq (data); + g_return_val_if_fail(data != NULL, 0); + return NM_WIFI_UTILS_GET_CLASS(data)->get_freq(data); } guint32 -nm_wifi_utils_find_freq (NMWifiUtils *data, const guint32 *freqs) +nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs) { - g_return_val_if_fail (data != NULL, 0); - g_return_val_if_fail (freqs != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS (data)->find_freq (data, freqs); + g_return_val_if_fail(data != NULL, 0); + g_return_val_if_fail(freqs != NULL, 0); + return NM_WIFI_UTILS_GET_CLASS(data)->find_freq(data, freqs); } gboolean -nm_wifi_utils_get_bssid (NMWifiUtils *data, guint8 *out_bssid) +nm_wifi_utils_get_bssid(NMWifiUtils *data, guint8 *out_bssid) { - g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (out_bssid != NULL, FALSE); + g_return_val_if_fail(data != NULL, FALSE); + g_return_val_if_fail(out_bssid != NULL, FALSE); - memset (out_bssid, 0, ETH_ALEN); - return NM_WIFI_UTILS_GET_CLASS (data)->get_bssid (data, out_bssid); + memset(out_bssid, 0, ETH_ALEN); + return NM_WIFI_UTILS_GET_CLASS(data)->get_bssid(data, out_bssid); } guint32 -nm_wifi_utils_get_rate (NMWifiUtils *data) +nm_wifi_utils_get_rate(NMWifiUtils *data) { - g_return_val_if_fail (data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS (data)->get_rate (data); + g_return_val_if_fail(data != NULL, 0); + return NM_WIFI_UTILS_GET_CLASS(data)->get_rate(data); } int -nm_wifi_utils_get_qual (NMWifiUtils *data) +nm_wifi_utils_get_qual(NMWifiUtils *data) { - g_return_val_if_fail (data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS (data)->get_qual (data); + g_return_val_if_fail(data != NULL, 0); + return NM_WIFI_UTILS_GET_CLASS(data)->get_qual(data); } gboolean -nm_wifi_utils_is_wifi (int dirfd, const char *ifname) +nm_wifi_utils_is_wifi(int dirfd, const char *ifname) { - g_return_val_if_fail (dirfd >= 0, FALSE); + g_return_val_if_fail(dirfd >= 0, FALSE); - if (faccessat (dirfd, "phy80211", F_OK, 0) == 0) - return TRUE; + if (faccessat(dirfd, "phy80211", F_OK, 0) == 0) + return TRUE; #if HAVE_WEXT - if (nm_wifi_utils_wext_is_wifi (ifname)) - return TRUE; + if (nm_wifi_utils_wext_is_wifi(ifname)) + return TRUE; #endif - return FALSE; + return FALSE; } /* OLPC Mesh-only functions */ guint32 -nm_wifi_utils_get_mesh_channel (NMWifiUtils *data) +nm_wifi_utils_get_mesh_channel(NMWifiUtils *data) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail(data != NULL, FALSE); - klass = NM_WIFI_UTILS_GET_CLASS (data); - g_return_val_if_fail (klass->get_mesh_channel != NULL, FALSE); + klass = NM_WIFI_UTILS_GET_CLASS(data); + g_return_val_if_fail(klass->get_mesh_channel != NULL, FALSE); - return klass->get_mesh_channel (data); + return klass->get_mesh_channel(data); } gboolean -nm_wifi_utils_set_mesh_channel (NMWifiUtils *data, guint32 channel) +nm_wifi_utils_set_mesh_channel(NMWifiUtils *data, guint32 channel) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (channel <= 13, FALSE); + g_return_val_if_fail(data != NULL, FALSE); + g_return_val_if_fail(channel <= 13, FALSE); - klass = NM_WIFI_UTILS_GET_CLASS (data); - g_return_val_if_fail (klass->set_mesh_channel != NULL, FALSE); + klass = NM_WIFI_UTILS_GET_CLASS(data); + g_return_val_if_fail(klass->set_mesh_channel != NULL, FALSE); - return klass->set_mesh_channel (data, channel); + return klass->set_mesh_channel(data, channel); } gboolean -nm_wifi_utils_set_mesh_ssid (NMWifiUtils *data, const guint8 *ssid, gsize len) +nm_wifi_utils_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail(data != NULL, FALSE); - klass = NM_WIFI_UTILS_GET_CLASS (data); - g_return_val_if_fail (klass->set_mesh_ssid != NULL, FALSE); + klass = NM_WIFI_UTILS_GET_CLASS(data); + g_return_val_if_fail(klass->set_mesh_ssid != NULL, FALSE); - return klass->set_mesh_ssid (data, ssid, len); + return klass->set_mesh_ssid(data, ssid, len); } gboolean -nm_wifi_utils_indicate_addressing_running (NMWifiUtils *data, gboolean running) +nm_wifi_utils_indicate_addressing_running(NMWifiUtils *data, gboolean running) { - NMWifiUtilsClass *klass; + NMWifiUtilsClass *klass; - g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail(data != NULL, FALSE); - klass = NM_WIFI_UTILS_GET_CLASS (data); - return klass->indicate_addressing_running ? klass->indicate_addressing_running (data, running) : FALSE; + klass = NM_WIFI_UTILS_GET_CLASS(data); + return klass->indicate_addressing_running ? klass->indicate_addressing_running(data, running) + : FALSE; } diff --git a/src/platform/wifi/nm-wifi-utils.h b/src/platform/wifi/nm-wifi-utils.h index bc0d88c8..d1df2fb8 100644 --- a/src/platform/wifi/nm-wifi-utils.h +++ b/src/platform/wifi/nm-wifi-utils.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -15,55 +15,57 @@ typedef struct NMWifiUtils NMWifiUtils; -#define NM_TYPE_WIFI_UTILS (nm_wifi_utils_get_type ()) -#define NM_WIFI_UTILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_UTILS, NMWifiUtils)) -#define NM_WIFI_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIFI_UTILS, NMWifiUtilsClass)) -#define NM_IS_WIFI_UTILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIFI_UTILS)) -#define NM_IS_WIFI_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIFI_UTILS)) -#define NM_WIFI_UTILS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIFI_UTILS, NMWifiUtilsClass)) +#define NM_TYPE_WIFI_UTILS (nm_wifi_utils_get_type()) +#define NM_WIFI_UTILS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIFI_UTILS, NMWifiUtils)) +#define NM_WIFI_UTILS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WIFI_UTILS, NMWifiUtilsClass)) +#define NM_IS_WIFI_UTILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WIFI_UTILS)) +#define NM_IS_WIFI_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WIFI_UTILS)) +#define NM_WIFI_UTILS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WIFI_UTILS, NMWifiUtilsClass)) -GType nm_wifi_utils_get_type (void); +GType nm_wifi_utils_get_type(void); -gboolean nm_wifi_utils_is_wifi (int dirfd, const char *ifname); +gboolean nm_wifi_utils_is_wifi(int dirfd, const char *ifname); -NMWifiUtils *nm_wifi_utils_new (int ifindex, struct nl_sock *genl, gboolean check_scan); +NMWifiUtils *nm_wifi_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan); -NMDeviceWifiCapabilities nm_wifi_utils_get_caps (NMWifiUtils *data); +NMDeviceWifiCapabilities nm_wifi_utils_get_caps(NMWifiUtils *data); -NM80211Mode nm_wifi_utils_get_mode (NMWifiUtils *data); +NM80211Mode nm_wifi_utils_get_mode(NMWifiUtils *data); -gboolean nm_wifi_utils_set_mode (NMWifiUtils *data, const NM80211Mode mode); +gboolean nm_wifi_utils_set_mode(NMWifiUtils *data, const NM80211Mode mode); /* Returns frequency in MHz */ -guint32 nm_wifi_utils_get_freq (NMWifiUtils *data); +guint32 nm_wifi_utils_get_freq(NMWifiUtils *data); /* Return the first supported frequency in the zero-terminated list. * Frequencies are specified in MHz. */ -guint32 nm_wifi_utils_find_freq (NMWifiUtils *data, const guint32 *freqs); +guint32 nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs); /* out_bssid must be ETH_ALEN bytes */ -gboolean nm_wifi_utils_get_bssid (NMWifiUtils *data, guint8 *out_bssid); +gboolean nm_wifi_utils_get_bssid(NMWifiUtils *data, guint8 *out_bssid); /* Returns current bitrate in Kbps */ -guint32 nm_wifi_utils_get_rate (NMWifiUtils *data); +guint32 nm_wifi_utils_get_rate(NMWifiUtils *data); /* Returns quality 0 - 100% on success, or -1 on error */ -int nm_wifi_utils_get_qual (NMWifiUtils *data); +int nm_wifi_utils_get_qual(NMWifiUtils *data); /* Tells the driver DHCP or SLAAC is running */ -gboolean nm_wifi_utils_indicate_addressing_running (NMWifiUtils *data, gboolean running); +gboolean nm_wifi_utils_indicate_addressing_running(NMWifiUtils *data, gboolean running); -gboolean nm_wifi_utils_set_powersave (NMWifiUtils *data, guint32 powersave); +gboolean nm_wifi_utils_set_powersave(NMWifiUtils *data, guint32 powersave); -NMSettingWirelessWakeOnWLan nm_wifi_utils_get_wake_on_wlan (NMWifiUtils *data); +NMSettingWirelessWakeOnWLan nm_wifi_utils_get_wake_on_wlan(NMWifiUtils *data); -gboolean nm_wifi_utils_set_wake_on_wlan (NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl); +gboolean nm_wifi_utils_set_wake_on_wlan(NMWifiUtils *data, NMSettingWirelessWakeOnWLan wowl); /* OLPC Mesh-only functions */ -guint32 nm_wifi_utils_get_mesh_channel (NMWifiUtils *data); +guint32 nm_wifi_utils_get_mesh_channel(NMWifiUtils *data); -gboolean nm_wifi_utils_set_mesh_channel (NMWifiUtils *data, guint32 channel); +gboolean nm_wifi_utils_set_mesh_channel(NMWifiUtils *data, guint32 channel); -gboolean nm_wifi_utils_set_mesh_ssid (NMWifiUtils *data, const guint8 *ssid, gsize len); +gboolean nm_wifi_utils_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len); -#endif /* __WIFI_UTILS_H__ */ +#endif /* __WIFI_UTILS_H__ */ diff --git a/src/platform/wpan/nm-wpan-utils.c b/src/platform/wpan/nm-wpan-utils.c index 231e6e2c..6f651414 100644 --- a/src/platform/wpan/nm-wpan-utils.c +++ b/src/platform/wpan/nm-wpan-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2018 Red Hat, Inc. */ @@ -14,275 +14,273 @@ #include "platform/nm-platform-utils.h" #define _NMLOG_PREFIX_NAME "wpan-nl802154" -#define _NMLOG(level, domain, ...) \ - G_STMT_START { \ - char _ifname_buf[IFNAMSIZ]; \ - const char *_ifname = self ? nmp_utils_if_indextoname (self->ifindex, _ifname_buf) : NULL; \ - \ - nm_log ((level), (domain), _ifname ?: NULL, NULL, \ - "%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - NM_PRINT_FMT_QUOTED (_ifname, " (", _ifname, ")", "") \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } G_STMT_END +#define _NMLOG(level, domain, ...) \ + G_STMT_START \ + { \ + char _ifname_buf[IFNAMSIZ]; \ + const char *_ifname = self ? nmp_utils_if_indextoname(self->ifindex, _ifname_buf) : NULL; \ + \ + nm_log((level), \ + (domain), \ + _ifname ?: NULL, \ + NULL, \ + "%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + NM_PRINT_FMT_QUOTED(_ifname, " (", _ifname, ")", "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END /*****************************************************************************/ struct NMWpanUtils { - GObject parent; - int ifindex; - struct nl_sock *nl_sock; - int id; + GObject parent; + int ifindex; + struct nl_sock *nl_sock; + int id; }; typedef struct { - GObjectClass parent; + GObjectClass parent; } NMWpanUtilsClass; -G_DEFINE_TYPE (NMWpanUtils, nm_wpan_utils, G_TYPE_OBJECT) +G_DEFINE_TYPE(NMWpanUtils, nm_wpan_utils, G_TYPE_OBJECT) /*****************************************************************************/ static int -ack_handler (struct nl_msg *msg, void *arg) +ack_handler(struct nl_msg *msg, void *arg) { - int *done = arg; - *done = 1; - return NL_STOP; + int *done = arg; + *done = 1; + return NL_STOP; } static int -finish_handler (struct nl_msg *msg, void *arg) +finish_handler(struct nl_msg *msg, void *arg) { - int *done = arg; - *done = 1; - return NL_SKIP; + int *done = arg; + *done = 1; + return NL_SKIP; } static int -error_handler (struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) +error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { - int *done = arg; - *done = err->error; - return NL_SKIP; + int *done = arg; + *done = err->error; + return NL_SKIP; } static struct nl_msg * -_nl802154_alloc_msg (int id, int ifindex, guint32 cmd, guint32 flags) +_nl802154_alloc_msg(int id, int ifindex, guint32 cmd, guint32 flags) { - nm_auto_nlmsg struct nl_msg *msg = NULL; + nm_auto_nlmsg struct nl_msg *msg = NULL; - msg = nlmsg_alloc (); - genlmsg_put (msg, 0, 0, id, 0, flags, cmd, 0); - NLA_PUT_U32 (msg, NL802154_ATTR_IFINDEX, ifindex); - return g_steal_pointer (&msg); + msg = nlmsg_alloc(); + genlmsg_put(msg, 0, 0, id, 0, flags, cmd, 0); + NLA_PUT_U32(msg, NL802154_ATTR_IFINDEX, ifindex); + return g_steal_pointer(&msg); nla_put_failure: - g_return_val_if_reached (NULL); + g_return_val_if_reached(NULL); } static struct nl_msg * -nl802154_alloc_msg (NMWpanUtils *self, guint32 cmd, guint32 flags) +nl802154_alloc_msg(NMWpanUtils *self, guint32 cmd, guint32 flags) { - return _nl802154_alloc_msg (self->id, self->ifindex, cmd, flags); + return _nl802154_alloc_msg(self->id, self->ifindex, cmd, flags); } static int -nl802154_send_and_recv (NMWpanUtils *self, - struct nl_msg *msg, - int (*valid_handler) (struct nl_msg *, void *), - void *valid_data) +nl802154_send_and_recv(NMWpanUtils * self, + struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) { - int err; - int done = 0; - const struct nl_cb cb = { - .err_cb = error_handler, - .err_arg = &done, - .finish_cb = finish_handler, - .finish_arg = &done, - .ack_cb = ack_handler, - .ack_arg = &done, - .valid_cb = valid_handler, - .valid_arg = valid_data, - }; - - g_return_val_if_fail (msg != NULL, -ENOMEM); - - err = nl_send_auto (self->nl_sock, msg); - if (err < 0) - return err; - - /* Loop until one of our NL callbacks says we're done; on success - * done will be 1, on error it will be < 0. - */ - while (!done) { - err = nl_recvmsgs (self->nl_sock, &cb); - if (err < 0 && err != -EAGAIN) { - _LOGW (LOGD_PLATFORM, "nl_recvmsgs() error: (%d) %s", - err, nm_strerror (err)); - break; - } - } - - if (err >= 0 && done < 0) - err = done; - return err; + int err; + int done = 0; + const struct nl_cb cb = { + .err_cb = error_handler, + .err_arg = &done, + .finish_cb = finish_handler, + .finish_arg = &done, + .ack_cb = ack_handler, + .ack_arg = &done, + .valid_cb = valid_handler, + .valid_arg = valid_data, + }; + + g_return_val_if_fail(msg != NULL, -ENOMEM); + + err = nl_send_auto(self->nl_sock, msg); + if (err < 0) + return err; + + /* Loop until one of our NL callbacks says we're done; on success + * done will be 1, on error it will be < 0. + */ + while (!done) { + err = nl_recvmsgs(self->nl_sock, &cb); + if (err < 0 && err != -EAGAIN) { + _LOGW(LOGD_PLATFORM, "nl_recvmsgs() error: (%d) %s", err, nm_strerror(err)); + break; + } + } + + if (err >= 0 && done < 0) + err = done; + return err; } struct nl802154_interface { - guint16 pan_id; - guint16 short_addr; + guint16 pan_id; + guint16 short_addr; - gboolean valid; + gboolean valid; }; static int -nl802154_get_interface_handler (struct nl_msg *msg, void *arg) +nl802154_get_interface_handler(struct nl_msg *msg, void *arg) { - static const struct nla_policy nl802154_policy[] = { - [NL802154_ATTR_PAN_ID] = { .type = NLA_U16 }, - [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16 }, - }; - struct nlattr *tb[G_N_ELEMENTS (nl802154_policy)]; - struct nl802154_interface *info = arg; - struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); + static const struct nla_policy nl802154_policy[] = { + [NL802154_ATTR_PAN_ID] = {.type = NLA_U16}, + [NL802154_ATTR_SHORT_ADDR] = {.type = NLA_U16}, + }; + struct nlattr * tb[G_N_ELEMENTS(nl802154_policy)]; + struct nl802154_interface *info = arg; + struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); - if (nla_parse_arr (tb, - genlmsg_attrdata (gnlh, 0), - genlmsg_attrlen (gnlh, 0), - nl802154_policy) < 0) - return NL_SKIP; + if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nl802154_policy) < 0) + return NL_SKIP; - if (tb[NL802154_ATTR_PAN_ID]) - info->pan_id = le16toh (nla_get_u16 (tb[NL802154_ATTR_PAN_ID])); + if (tb[NL802154_ATTR_PAN_ID]) + info->pan_id = le16toh(nla_get_u16(tb[NL802154_ATTR_PAN_ID])); - if (tb[NL802154_ATTR_SHORT_ADDR]) - info->short_addr = le16toh (nla_get_u16 (tb[NL802154_ATTR_SHORT_ADDR])); + if (tb[NL802154_ATTR_SHORT_ADDR]) + info->short_addr = le16toh(nla_get_u16(tb[NL802154_ATTR_SHORT_ADDR])); - info->valid = TRUE; + info->valid = TRUE; - return NL_SKIP; + return NL_SKIP; } static void -nl802154_get_interface (NMWpanUtils *self, - struct nl802154_interface *interface) +nl802154_get_interface(NMWpanUtils *self, struct nl802154_interface *interface) { - nm_auto_nlmsg struct nl_msg *msg = NULL; + nm_auto_nlmsg struct nl_msg *msg = NULL; - memset (interface, 0, sizeof (*interface)); + memset(interface, 0, sizeof(*interface)); - msg = nl802154_alloc_msg (self, NL802154_CMD_GET_INTERFACE, 0); + msg = nl802154_alloc_msg(self, NL802154_CMD_GET_INTERFACE, 0); - nl802154_send_and_recv (self, msg, nl802154_get_interface_handler, interface); + nl802154_send_and_recv(self, msg, nl802154_get_interface_handler, interface); } /*****************************************************************************/ guint16 -nm_wpan_utils_get_pan_id (NMWpanUtils *self) +nm_wpan_utils_get_pan_id(NMWpanUtils *self) { - struct nl802154_interface interface; + struct nl802154_interface interface; - nl802154_get_interface (self, &interface); + nl802154_get_interface(self, &interface); - return interface.pan_id; + return interface.pan_id; } gboolean -nm_wpan_utils_set_pan_id (NMWpanUtils *self, guint16 pan_id) +nm_wpan_utils_set_pan_id(NMWpanUtils *self, guint16 pan_id) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; - g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail(self != NULL, FALSE); - msg = nl802154_alloc_msg (self, NL802154_CMD_SET_PAN_ID, 0); - NLA_PUT_U16 (msg, NL802154_ATTR_PAN_ID, htole16 (pan_id)); - err = nl802154_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + msg = nl802154_alloc_msg(self, NL802154_CMD_SET_PAN_ID, 0); + NLA_PUT_U16(msg, NL802154_ATTR_PAN_ID, htole16(pan_id)); + err = nl802154_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } guint16 -nm_wpan_utils_get_short_addr (NMWpanUtils *self) +nm_wpan_utils_get_short_addr(NMWpanUtils *self) { - struct nl802154_interface interface; + struct nl802154_interface interface; - nl802154_get_interface (self, &interface); + nl802154_get_interface(self, &interface); - return interface.short_addr; + return interface.short_addr; } gboolean -nm_wpan_utils_set_short_addr (NMWpanUtils *self, guint16 short_addr) +nm_wpan_utils_set_short_addr(NMWpanUtils *self, guint16 short_addr) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; - g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail(self != NULL, FALSE); - msg = nl802154_alloc_msg (self, NL802154_CMD_SET_SHORT_ADDR, 0); - NLA_PUT_U16 (msg, NL802154_ATTR_SHORT_ADDR, htole16 (short_addr)); - err = nl802154_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + msg = nl802154_alloc_msg(self, NL802154_CMD_SET_SHORT_ADDR, 0); + NLA_PUT_U16(msg, NL802154_ATTR_SHORT_ADDR, htole16(short_addr)); + err = nl802154_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } gboolean -nm_wpan_utils_set_channel (NMWpanUtils *self, guint8 page, guint8 channel) +nm_wpan_utils_set_channel(NMWpanUtils *self, guint8 page, guint8 channel) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; + nm_auto_nlmsg struct nl_msg *msg = NULL; + int err; - g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail(self != NULL, FALSE); - msg = nl802154_alloc_msg (self, NL802154_CMD_SET_CHANNEL, 0); - NLA_PUT_U8 (msg, NL802154_ATTR_PAGE, page); - NLA_PUT_U8 (msg, NL802154_ATTR_CHANNEL, channel); - err = nl802154_send_and_recv (self, msg, NULL, NULL); - return err >= 0; + msg = nl802154_alloc_msg(self, NL802154_CMD_SET_CHANNEL, 0); + NLA_PUT_U8(msg, NL802154_ATTR_PAGE, page); + NLA_PUT_U8(msg, NL802154_ATTR_CHANNEL, channel); + err = nl802154_send_and_recv(self, msg, NULL, NULL); + return err >= 0; nla_put_failure: - g_return_val_if_reached (FALSE); + g_return_val_if_reached(FALSE); } /*****************************************************************************/ static void -nm_wpan_utils_init (NMWpanUtils *self) -{ -} +nm_wpan_utils_init(NMWpanUtils *self) +{} static void -nm_wpan_utils_class_init (NMWpanUtilsClass *klass) -{ -} +nm_wpan_utils_class_init(NMWpanUtilsClass *klass) +{} NMWpanUtils * -nm_wpan_utils_new (int ifindex, struct nl_sock *genl, gboolean check_scan) +nm_wpan_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan) { - NMWpanUtils *self; + NMWpanUtils *self; - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail(ifindex > 0, NULL); - if (!genl) - return NULL; + if (!genl) + return NULL; - self = g_object_new (NM_TYPE_WPAN_UTILS, NULL); - self->ifindex = ifindex; - self->nl_sock = genl; - self->id = genl_ctrl_resolve (genl, "nl802154"); + self = g_object_new(NM_TYPE_WPAN_UTILS, NULL); + self->ifindex = ifindex; + self->nl_sock = genl; + self->id = genl_ctrl_resolve(genl, "nl802154"); - if (self->id < 0) { - _LOGD (LOGD_PLATFORM, "genl_ctrl_resolve: failed to resolve \"nl802154\""); - g_object_unref (self); - return NULL; - } + if (self->id < 0) { + _LOGD(LOGD_PLATFORM, "genl_ctrl_resolve: failed to resolve \"nl802154\""); + g_object_unref(self); + return NULL; + } - return self; + return self; } diff --git a/src/platform/wpan/nm-wpan-utils.h b/src/platform/wpan/nm-wpan-utils.h index deafeb97..b30c89a6 100644 --- a/src/platform/wpan/nm-wpan-utils.h +++ b/src/platform/wpan/nm-wpan-utils.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2018 Red Hat, Inc. */ @@ -13,23 +13,25 @@ typedef struct NMWpanUtils NMWpanUtils; -#define NM_TYPE_WPAN_UTILS (nm_wpan_utils_get_type ()) -#define NM_WPAN_UTILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WPAN_UTILS, NMWpanUtils)) -#define NM_WPAN_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WPAN_UTILS, NMWpanUtilsClass)) -#define NM_IS_WPAN_UTILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WPAN_UTILS)) -#define NM_IS_WPAN_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WPAN_UTILS)) -#define NM_WPAN_UTILS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WPAN_UTILS, NMWpanUtilsClass)) +#define NM_TYPE_WPAN_UTILS (nm_wpan_utils_get_type()) +#define NM_WPAN_UTILS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WPAN_UTILS, NMWpanUtils)) +#define NM_WPAN_UTILS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_WPAN_UTILS, NMWpanUtilsClass)) +#define NM_IS_WPAN_UTILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_WPAN_UTILS)) +#define NM_IS_WPAN_UTILS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_WPAN_UTILS)) +#define NM_WPAN_UTILS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_WPAN_UTILS, NMWpanUtilsClass)) -GType nm_wpan_utils_get_type (void); +GType nm_wpan_utils_get_type(void); -NMWpanUtils *nm_wpan_utils_new (int ifindex, struct nl_sock *genl, gboolean check_scan); +NMWpanUtils *nm_wpan_utils_new(int ifindex, struct nl_sock *genl, gboolean check_scan); -guint16 nm_wpan_utils_get_pan_id (NMWpanUtils *self); -gboolean nm_wpan_utils_set_pan_id (NMWpanUtils *self, guint16 pan_id); +guint16 nm_wpan_utils_get_pan_id(NMWpanUtils *self); +gboolean nm_wpan_utils_set_pan_id(NMWpanUtils *self, guint16 pan_id); -guint16 nm_wpan_utils_get_short_addr (NMWpanUtils *self); -gboolean nm_wpan_utils_set_short_addr (NMWpanUtils *self, guint16 short_addr); +guint16 nm_wpan_utils_get_short_addr(NMWpanUtils *self); +gboolean nm_wpan_utils_set_short_addr(NMWpanUtils *self, guint16 short_addr); -gboolean nm_wpan_utils_set_channel (NMWpanUtils *self, guint8 page, guint8 channel); +gboolean nm_wpan_utils_set_channel(NMWpanUtils *self, guint8 page, guint8 channel); -#endif /* __WPAN_UTILS_H__ */ +#endif /* __WPAN_UTILS_H__ */ |