From 18fa10cc45c47a631a8c989aedd953c08e79a7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20=C5=A0imerda?= Date: Wed, 23 Jan 2013 08:47:22 +0100 Subject: [PATCH] cleanup: remove obsolete link-related functions Use nm-platform instead. --- src/nm-netlink-monitor.c | 300 --------- src/nm-netlink-monitor.h | 13 - src/nm-system.c | 1259 -------------------------------------- src/nm-system.h | 61 +- 4 files changed, 1 insertion(+), 1632 deletions(-) diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c index 5ad686f19..6853c2e56 100644 --- a/src/nm-netlink-monitor.c +++ b/src/nm-netlink-monitor.c @@ -65,9 +65,6 @@ typedef struct { /* Sync/blocking request/response connection */ struct nl_sock *nlh_sync; - struct nl_cache * link_cache; - - guint request_status_id; GHashTable *subscriptions; } NMNetlinkMonitorPrivate; @@ -147,46 +144,6 @@ log_error_limited (NMNetlinkMonitor *monitor, guint32 code, const char *fmt, ... /****************************************************************/ -static void -link_msg_handler (struct nl_object *obj, void *arg) -{ - NMNetlinkMonitor *self = NM_NETLINK_MONITOR (arg); - struct rtnl_link *filter; - struct rtnl_link *link_obj; - guint flags; - guint ifidx; - - filter = rtnl_link_alloc (); - if (!filter) { - log_error_limited (self, NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, - _("error processing netlink message: %s"), - nl_geterror (ENOMEM)); - return; - } - - /* Ensure it's a link object */ - if (nl_object_match_filter (obj, OBJ_CAST (filter)) == 0) { - rtnl_link_put (filter); - return; - } - - link_obj = (struct rtnl_link *) obj; - flags = rtnl_link_get_flags (link_obj); - ifidx = rtnl_link_get_ifindex (link_obj); - - nm_log_dbg (LOGD_HW, "netlink link message: iface idx %d flags 0x%X", ifidx, flags); - - /* IFF_LOWER_UP is the indicator of carrier status since kernel commit - * b00055aacdb172c05067612278ba27265fcd05ce in 2.6.17. - */ - if (flags & IFF_LOWER_UP) - g_signal_emit (self, signals[CARRIER_ON], 0, ifidx); - else - g_signal_emit (self, signals[CARRIER_OFF], 0, ifidx); - - rtnl_link_put (filter); -} - static int event_msg_recv (struct nl_msg *msg, void *arg) { @@ -241,9 +198,6 @@ event_msg_ready (struct nl_msg *msg, void *arg) /* Let clients handle generic messages */ g_signal_emit (self, signals[NOTIFICATION], 0, msg); - /* Parse carrier messages */ - nl_msg_parse (msg, &link_msg_handler, self); - return NL_OK; } @@ -411,11 +365,6 @@ static gboolean sync_connection_setup (NMNetlinkMonitor *self, GError **error) { NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); -#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND - struct nl_cache *addr_cache; -#endif - int err; - /* Set up the event listener connection */ priv->nlh_sync = nl_socket_alloc (); if (!priv->nlh_sync) { @@ -429,37 +378,8 @@ sync_connection_setup (NMNetlinkMonitor *self, GError **error) if (!nlh_setup (priv->nlh_sync, NULL, self, error)) goto error; -#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND - /* Work around apparent libnl bug; rtnl_addr requires that all - * addresses have the "peer" attribute set in order to be compared - * for equality, but this attribute is not normally set. As a - * result, most addresses will not compare as equal even to - * themselves, busting caching. - */ - rtnl_addr_alloc_cache (priv->nlh_sync, &addr_cache); - g_warn_if_fail (addr_cache != NULL); - nl_cache_get_ops (addr_cache)->co_obj_ops->oo_id_attrs &= ~0x80; - nl_cache_free (addr_cache); -#endif - - err = rtnl_link_alloc_cache (priv->nlh_sync, AF_UNSPEC, &priv->link_cache); - if (err < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE, - _("unable to allocate netlink link cache for monitoring link status: %s"), - nl_geterror (err)); - goto error; - } - nl_cache_mngt_provide (priv->link_cache); - return TRUE; - error: - if (priv->link_cache) { - nl_cache_free (priv->link_cache); - priv->link_cache = NULL; - } - if (priv->nlh_sync) { nl_socket_free (priv->nlh_sync); priv->nlh_sync = NULL; @@ -570,130 +490,6 @@ nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *self, GError **error) return TRUE; } -static gboolean -deferred_emit_carrier_state (gpointer user_data) -{ - NMNetlinkMonitor *self = NM_NETLINK_MONITOR (user_data); - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - int err; - - priv->request_status_id = 0; - - /* Update the link cache with latest state, and if there are no errors - * emit the link states for all the interfaces in the cache. - */ - err = nl_cache_refill (priv->nlh_sync, priv->link_cache); - if (err < 0) - nm_log_err (LOGD_HW, "error updating link cache: %s", nl_geterror (err)); - else - nl_cache_foreach_filter (priv->link_cache, NULL, link_msg_handler, self); - - return FALSE; -} - -void -nm_netlink_monitor_request_status (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - /* Schedule the carrier state emission */ - if (!priv->request_status_id) - priv->request_status_id = g_idle_add (deferred_emit_carrier_state, self); -} - -typedef struct { - NMNetlinkMonitor *self; - struct rtnl_link *filter; - GError *error; - guint32 flags; -} GetFlagsInfo; - -static void -get_flags_sync_cb (struct nl_object *obj, void *arg) -{ - GetFlagsInfo *info = arg; - - /* Ensure this cache item matches our filter */ - if (nl_object_match_filter (obj, OBJ_CAST (info->filter)) != 0) - info->flags = rtnl_link_get_flags ((struct rtnl_link *) obj); -} - -gboolean -nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self, - guint32 ifindex, - guint32 *ifflags, - GError **error) -{ - NMNetlinkMonitorPrivate *priv; - GetFlagsInfo info; - struct rtnl_link *filter; - int err; - - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - g_return_val_if_fail (ifflags != NULL, FALSE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - /* Update the link cache with the latest information */ - err = nl_cache_refill (priv->nlh_sync, priv->link_cache); - if (err < 0) { - g_set_error (error, - NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, - _("error updating link cache: %s"), - nl_geterror (err)); - return FALSE; - } - - /* HACK: Apparently to get it working we have to refill the cache twice; - * otherwise some kernels (or maybe libnl?) only send a few of the - * interfaces in the refill request. - */ - if (nl_cache_refill (priv->nlh_sync, priv->link_cache)) { - g_set_error (error, - NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, - _("error updating link cache: %s"), - nl_geterror (err)); - return FALSE; - } - - /* Set up the filter */ - filter = rtnl_link_alloc (); - if (!filter) { - g_set_error (error, - NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, - _("error processing netlink message: %s"), - nl_geterror (err)); - return FALSE; - } - rtnl_link_set_ifindex (filter, ifindex); - - memset (&info, 0, sizeof (info)); - info.self = self; - info.filter = filter; - info.error = NULL; - nl_cache_foreach_filter (priv->link_cache, NULL, get_flags_sync_cb, &info); - - rtnl_link_put (filter); - - if (info.error) { - if (error) - *error = info.error; - else - g_error_free (info.error); - return FALSE; - } else - *ifflags = info.flags; - - return TRUE; /* success */ -} - /***************************************************************/ struct nl_sock * @@ -708,76 +504,6 @@ nm_netlink_get_default_handle (void) return nlh; } -int -nm_netlink_iface_to_index (const char *iface) -{ - NMNetlinkMonitor *self; - NMNetlinkMonitorPrivate *priv; - int idx; - - g_return_val_if_fail (iface != NULL, -1); - - self = nm_netlink_monitor_get (); - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - nl_cache_refill (priv->nlh_sync, priv->link_cache); - idx = rtnl_link_name2i (priv->link_cache, iface); - - return idx; -} - -/** - * nm_netlink_index_to_iface: - * @idx: kernel interface index - * - * Returns: the device name corresponding to the kernel interface index; caller - * owns returned value and must free it when it is no longer required - **/ -#define MAX_IFACE_LEN 33 -char * -nm_netlink_index_to_iface (int idx) -{ - NMNetlinkMonitor *self; - NMNetlinkMonitorPrivate *priv; - char *buf = NULL; - - g_return_val_if_fail (idx >= 0, NULL); - - self = nm_netlink_monitor_get (); - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - buf = g_malloc0 (MAX_IFACE_LEN); - g_assert (buf); - - nl_cache_refill (priv->nlh_sync, priv->link_cache); - if (!rtnl_link_i2name (priv->link_cache, idx, buf, MAX_IFACE_LEN - 1)) { - nm_log_warn (LOGD_HW, "(%d) failed to find interface name for index", idx); - g_free (buf); - buf = NULL; - } - - return buf; -} - -struct rtnl_link * -nm_netlink_index_to_rtnl_link (int idx) -{ - NMNetlinkMonitor *self; - NMNetlinkMonitorPrivate *priv; - struct rtnl_link *ret = NULL; - - if (idx <= 0) - return NULL; - - self = nm_netlink_monitor_get (); - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - nl_cache_refill (priv->nlh_sync, priv->link_cache); - ret = rtnl_link_get (priv->link_cache, idx); - - return ret; -} - /***************************************************************/ NMNetlinkMonitor * @@ -792,8 +518,6 @@ nm_netlink_monitor_get (void) if (open_connection (singleton, &error)) { attach (singleton); - /* Request initial status of cards */ - nm_netlink_monitor_request_status (singleton); } else { nm_log_warn (LOGD_HW, "Failed to connect to netlink: (%d) %s", error ? error->code : 0, @@ -821,17 +545,9 @@ finalize (GObject *object) { NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (object); - if (priv->request_status_id) - g_source_remove (priv->request_status_id); - if (priv->io_channel) close_connection (NM_NETLINK_MONITOR (object)); - if (priv->link_cache) { - nl_cache_free (priv->link_cache); - priv->link_cache = NULL; - } - if (priv->nlh_event) { nl_socket_free (priv->nlh_event); priv->nlh_event = NULL; @@ -865,22 +581,6 @@ nm_netlink_monitor_class_init (NMNetlinkMonitorClass *monitor_class) G_STRUCT_OFFSET (NMNetlinkMonitorClass, notification), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - - signals[CARRIER_ON] = - g_signal_new ("carrier-on", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkMonitorClass, carrier_on), - NULL, NULL, g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); - - signals[CARRIER_OFF] = - g_signal_new ("carrier-off", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkMonitorClass, carrier_off), - NULL, NULL, g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); } GQuark diff --git a/src/nm-netlink-monitor.h b/src/nm-netlink-monitor.h index d0dbb5c7c..7295616b9 100644 --- a/src/nm-netlink-monitor.h +++ b/src/nm-netlink-monitor.h @@ -25,7 +25,6 @@ #include #include -#include #define NM_TYPE_NETLINK_MONITOR (nm_netlink_monitor_get_type ()) #define NM_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitor)) @@ -55,8 +54,6 @@ typedef struct { /* Signals */ void (*notification) (NMNetlinkMonitor *monitor, struct nl_msg *msg); - void (*carrier_on) (NMNetlinkMonitor *monitor, int index); - void (*carrier_off) (NMNetlinkMonitor *monitor, int index); } NMNetlinkMonitorClass; @@ -73,17 +70,7 @@ gboolean nm_netlink_monitor_subscribe (NMNetlinkMonitor *monitor gboolean nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *monitor, GError **error); -void nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor); - -gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor, - guint32 ifindex, - guint32 *ifflags, - GError **error); - /* Generic utility functions */ -int nm_netlink_iface_to_index (const char *iface); -char * nm_netlink_index_to_iface (int idx); -struct rtnl_link *nm_netlink_index_to_rtnl_link (int idx); struct nl_sock * nm_netlink_get_default_handle (void); #endif /* NM_NETLINK_MONITOR_H */ diff --git a/src/nm-system.c b/src/nm-system.c index 968847bb7..a8b7a291d 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -63,11 +63,6 @@ #include #include -#if !HAVE_VLAN_FLAG_LOOSE_BINDING -/* Older kernels don't have this flag */ -#define VLAN_FLAG_LOOSE_BINDING 0x04 -#endif - static void nm_system_device_set_priority (int ifindex, NMIP4Config *config, int priority); @@ -692,245 +687,6 @@ nm_system_apply_ip6_config (int ifindex, return TRUE; } -/** - * nm_system_iface_set_up: - * @ifindex: interface index - * @up: %TRUE to bring interface up, or %FALSE to take it down - * @no_firmware: on return, %TRUE if the operation may have failed due to - * missing firmware - * - * Bring the interface up or take it down. - * - * Returns: %TRUE on success, %FALSE on failure - **/ -gboolean -nm_system_iface_set_up (int ifindex, - gboolean up, - gboolean *no_firmware) -{ - struct rtnl_link *request = NULL, *old = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - if (no_firmware) - g_return_val_if_fail (*no_firmware == FALSE, FALSE); - - if (!(request = rtnl_link_alloc ())) - return FALSE; - - if (up) - rtnl_link_set_flags (request, IFF_UP); - else - rtnl_link_unset_flags (request, IFF_UP); - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, request, 0); - if (err == 0) { - success = TRUE; - } else { - if ((err == -NLE_OBJ_NOTFOUND) && no_firmware && up) - *no_firmware = TRUE; - } - } - } - - rtnl_link_put (old); - rtnl_link_put (request); - return success; -} - -guint32 -nm_system_iface_get_flags (int ifindex) -{ - struct rtnl_link *l; - guint32 flags; - - g_return_val_if_fail (ifindex > 0, FALSE); - - l = nm_netlink_index_to_rtnl_link (ifindex); - if (l == NULL) { - char *iface = nm_netlink_index_to_iface (ifindex); - - g_warn_if_fail (iface != NULL); - nm_log_err (LOGD_HW, "(%s): failed to get interface link object", - iface ? iface : "unknown"); - g_free (iface); - return FALSE; - } - - flags = rtnl_link_get_flags (l); - rtnl_link_put (l); - - return flags; -} - -/** - * nm_system_iface_is_up: - * @ifindex: interface index - * - * Returns: %TRUE if the interface is up, %FALSE if it was down or the check - * failed. - **/ -gboolean -nm_system_iface_is_up (int ifindex) -{ - return nm_system_iface_get_flags (ifindex) & IFF_UP; -} - -/** - * nm_system_iface_set_mtu: - * @ifindex: interface index - * @mtu: the new MTU - * - * Returns: %TRUE if the request was successful, %FALSE if it failed - **/ -gboolean -nm_system_iface_set_mtu (int ifindex, guint32 mtu) -{ - struct rtnl_link *old; - struct rtnl_link *new; - gboolean success = FALSE; - struct nl_sock *nlh; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (mtu > 0, FALSE); - - new = rtnl_link_alloc (); - if (!new) - return FALSE; - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - rtnl_link_set_mtu (new, mtu); - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, new, 0); - if (err == 0) - success = TRUE; - else { - char *iface = nm_netlink_index_to_iface (ifindex); - - nm_log_warn (LOGD_HW, "(%s): failed to change interface MTU", - iface ? iface : "unknown"); - g_free (iface); - } - } - rtnl_link_put (old); - } - rtnl_link_put (new); - - return success; -} - -/** - * nm_system_iface_set_mac: - * @ifindex: interface index - * @mac: new MAC address - * - * Attempts to change the interface's MAC address to the requested value, - * ie MAC spoofing or cloning. - * - * Returns: %TRUE if the request succeeded, %FALSE if it failed. - **/ -gboolean -nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac) -{ - struct rtnl_link *old, *new; - gboolean success = FALSE; - struct nl_sock *nlh; - char *iface; - struct nl_addr *addr = NULL; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (mac != NULL, FALSE); - - new = rtnl_link_alloc (); - if (!new) - return FALSE; - - iface = nm_netlink_index_to_iface (ifindex); - if (!iface) - goto out; - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - addr = nl_addr_build (AF_LLC, (void *) mac, ETH_ALEN); - if (!addr) { - nm_log_err (LOGD_HW, "(%s): failed to allocate memory for MAC address change", iface); - rtnl_link_put (old); - rtnl_link_put (new); - return FALSE; - } - rtnl_link_set_addr (new, addr); - nl_addr_put (addr); - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, new, 0); - if (err == 0) - success = TRUE; - else - nm_log_warn (LOGD_HW, "(%s): failed to change interface MAC address", iface); - } - rtnl_link_put (old); - } - -out: - rtnl_link_put (new); - g_free (iface); - return success; -} - -/** - * nm_system_iface_set_arp: - * @ifindex: interface index - * @enable: %TRUE to enable ARP, or %FALSE to disable - * - * Sets a flag to indicate that ARP should or should not be used on the - * interface. Point-to-point or IPv4 /32 interfaces often require that ARP - * be disabled. - * - * Returns: %TRUE on success, %FALSE on failure - **/ -gboolean -nm_system_iface_set_arp (int ifindex, gboolean enable) -{ - struct rtnl_link *request = NULL, *old = NULL; - struct nl_sock *nlh; - gboolean success = FALSE; - int err; - - g_return_val_if_fail (ifindex > 0, FALSE); - - if (!(request = rtnl_link_alloc ())) - return FALSE; - - if (enable) - rtnl_link_unset_flags (request, IFF_NOARP); - else - rtnl_link_set_flags (request, IFF_NOARP); - - old = nm_netlink_index_to_rtnl_link (ifindex); - if (old) { - nlh = nm_netlink_get_default_handle (); - if (nlh) { - err = rtnl_link_change (nlh, old, request, 0); - if (err == 0) - success = TRUE; - } - } - - rtnl_link_put (old); - rtnl_link_put (request); - return success; -} - static struct rtnl_route * add_ip4_route_to_gateway (int ifindex, guint32 gw, guint32 mss) { @@ -1565,1018 +1321,3 @@ nm_system_apply_bonding_config (const char *iface, NMSettingBond *s_bond) return TRUE; } - -/** - * nm_system_add_bonding_master: - * @iface: the interface name for the new bond master - * - * Adds a virtual bonding device if it does not exist yet. - * - * Returns: %TRUE on success, %FALSE on failure - */ -gboolean -nm_system_add_bonding_master (const char *iface) -{ - struct nl_sock *sock; - int err; - - g_return_val_if_fail (iface != NULL, FALSE); - - /* 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)) - nm_spawn_process ("modprobe bonding max_bonds=0"); - - sock = nm_netlink_get_default_handle (); - - /* Existing bonding devices with matching name will be reused */ - err = rtnl_link_bond_add (sock, iface, NULL); - if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error %d returned from " - "rtnl_link_bond_add(): %s", - iface, err, nl_geterror (err)); - return FALSE; - } - return TRUE; -} - -static gboolean -nm_system_bond_compat_enslave (const char *master_iface, const char *slave_iface) -{ - struct ifreq ifr; - int fd; - gboolean ret = FALSE; - - memset (&ifr, 0, sizeof (ifr)); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return FALSE; - } - - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - strncpy (ifr.ifr_slave, slave_iface, IFNAMSIZ); - - if (ioctl (fd, SIOCBONDENSLAVE, &ifr) < 0 && - ioctl (fd, BOND_ENSLAVE_OLD, &ifr) < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error enslaving %s: %d (%s)", - master_iface, slave_iface, errno, strerror (errno)); - } else - ret = TRUE; - - close (fd); - - return ret; -} - -/** - * nm_system_bond_enslave: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Enslaves the 'slave' to 'master. This function targets implementing a - * generic interface to attaching all kinds of slaves to masters. Currently - * only bonding is properly supported due to the backwards compatibility - * function being bonding specific. - * - * The slave device needs to be down as a prerequisite. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bond_enslave (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface) -{ - struct nl_sock *sock; - int err; - - g_return_val_if_fail (master_ifindex > 0, FALSE); - g_return_val_if_fail (master_iface != NULL, FALSE); - g_return_val_if_fail (slave_ifindex > 0, FALSE); - g_return_val_if_fail (slave_iface != NULL, FALSE); - - sock = nm_netlink_get_default_handle (); - - if (!(nm_system_iface_get_flags (master_ifindex) & IFF_MASTER)) { - nm_log_err (LOGD_DEVICE, "(%s): interface is not a master", master_iface); - return FALSE; - } - - g_assert (!nm_system_iface_is_up (slave_ifindex)); - - if (nm_system_iface_get_flags (slave_ifindex) & IFF_SLAVE) { - struct rtnl_link *l; - int existing_master = -1; - - /* Get the ifindex of the existing master device */ - l = nm_netlink_index_to_rtnl_link (slave_ifindex); - g_warn_if_fail (l != NULL); - if (l) { - existing_master = rtnl_link_get_master (l); - rtnl_link_put (l); - } - - if (existing_master > 0) { - /* Fail if the device is already a slave of a different master */ - if (existing_master != master_ifindex) { - nm_log_err (LOGD_DEVICE, "(%s): already a slave of a different master", - slave_iface); - return FALSE; - } - - nm_log_dbg (LOGD_DEVICE, "(%s): %s is already enslaved", - master_iface, slave_iface); - return TRUE; - } - } - - err = rtnl_link_bond_enslave_ifindex (sock, master_ifindex, slave_ifindex); - if (err == -NLE_OPNOTSUPP) - return nm_system_bond_compat_enslave (master_iface, slave_iface); - - if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error enslaving %s: %d (%s)", - master_iface, slave_iface, err, nl_geterror (err)); - return FALSE; - } - - return TRUE; -} - -static gboolean -nm_system_bond_compat_release (const char *master_iface, const char *slave_iface) -{ - struct ifreq ifr; - int fd; - gboolean ret = FALSE; - - memset (&ifr, 0, sizeof (ifr)); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return FALSE; - } - - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - strncpy (ifr.ifr_slave, slave_iface, IFNAMSIZ); - - if (ioctl (fd, SIOCBONDRELEASE, &ifr) < 0 && - ioctl (fd, BOND_RELEASE_OLD, &ifr) < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error releasing slave %s: %d (%s)", - master_iface, slave_iface, errno, strerror (errno)); - } else - ret = TRUE; - - close (fd); - return ret; -} - -/** - * nm_system_bond_release: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Releases the 'slave' which is attached to 'master. This function targets - * implementing a generic interface to releasing all kinds of slaves. Currently - * only bonding is properly supported due to the backwards compatibility - * function being bonding specific. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bond_release (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface) -{ - struct nl_sock *sock; - int err; - - g_return_val_if_fail (master_ifindex > 0, FALSE); - g_return_val_if_fail (master_iface != NULL, FALSE); - g_return_val_if_fail (slave_ifindex > 0, FALSE); - g_return_val_if_fail (slave_iface != NULL, FALSE); - - sock = nm_netlink_get_default_handle (); - - /* Only release if this is actually a slave */ - if (!(nm_system_iface_get_flags (slave_ifindex) & IFF_SLAVE)) - return TRUE; - - err = rtnl_link_bond_release_ifindex (sock, slave_ifindex); - if (err == -NLE_OPNOTSUPP) - return nm_system_bond_compat_release (master_iface, slave_iface); - else if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): error releasing slave %s: %d (%s)", - master_iface, slave_iface, err, nl_geterror (err)); - return FALSE; - } - - return TRUE; -} - -/** - * nm_system_compat_get_iface_type: - * @ifindex: interface index - * @name: name of interface - * - * Lookup the type of an interface. At least one of @ifindex or @name must - * be provided. - * - * Returns: Interface type (NM_IFACE_TYPE_*) or NM_IFACE_TYPE_UNSPEC. - **/ -static int -nm_system_compat_get_iface_type (int ifindex, const char *name) -{ - int res = NM_IFACE_TYPE_UNSPEC; - char *ifname = NULL, *path = NULL; - struct vlan_ioctl_args ifv; - struct ifreq ifr; - struct ifbond ifb; - struct stat st; - int fd; - - g_return_val_if_fail (ifindex > 0 || name, NM_IFACE_TYPE_UNSPEC); - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - goto out; - } - - if (!name) { - g_assert (ifindex > 0); - ifname = nm_netlink_index_to_iface (ifindex); - } - - /* Check VLAN */ - memset (&ifv, 0, sizeof (ifv)); - ifv.cmd = GET_VLAN_VID_CMD; - strncpy (ifv.device1, ifname ? ifname : name, sizeof (ifv.device1) - 1); - if (ioctl (fd, SIOCGIFVLAN, &ifv) == 0) { - res = NM_IFACE_TYPE_VLAN; - goto out; - } - - /* and bond */ - memset (&ifr, 0, sizeof (ifr)); - strncpy (ifr.ifr_name, ifname ? ifname : name, sizeof (ifr.ifr_name) - 1); - memset (&ifb, 0, sizeof (ifb)); - ifr.ifr_data = (caddr_t) &ifb; - if (ioctl (fd, SIOCBONDINFOQUERY, &ifr) == 0) { - res = NM_IFACE_TYPE_BOND; - goto out; - } - - /* and bridge */ - path = g_strdup_printf ("/sys/class/net/%s/bridge", ifname ? ifname : name); - if ((stat (path, &st) == 0) && S_ISDIR (st.st_mode)) { - res = NM_IFACE_TYPE_BRIDGE; - goto out; - } - -out: - g_free (path); - close (fd); - g_free (ifname); - return res; -} - -/** - * nm_system_get_iface_type: - * @ifindex: interface index - * @name: name of interface - * - * Lookup the type of an interface. At least one of @ifindex or @name must - * be provided. - * - * Returns: Interface type (NM_IFACE_TYPE_*) or NM_IFACE_TYPE_UNSPEC. - **/ -int -nm_system_get_iface_type (int ifindex, const char *name) -{ - struct rtnl_link *result; - struct nl_sock *nlh; - char *type; - int res = NM_IFACE_TYPE_UNSPEC; - int err; - - g_return_val_if_fail (ifindex > 0 || name, NM_IFACE_TYPE_UNSPEC); - - nlh = nm_netlink_get_default_handle (); - if (!nlh) - goto out; - - /* Prefer interface indexes to names */ - err = rtnl_link_get_kernel (nlh, ifindex, ifindex <= 0 ? name : NULL, &result); - if (err < 0) { - if (err == -NLE_OPNOTSUPP) - res = nm_system_compat_get_iface_type (ifindex, name); - goto out; - } - - type = rtnl_link_get_type (result); - - if (!g_strcmp0 (type, "bond")) - res = NM_IFACE_TYPE_BOND; - else if (!g_strcmp0 (type, "vlan")) - res = NM_IFACE_TYPE_VLAN; - else if (!g_strcmp0 (type, "bridge")) - res = NM_IFACE_TYPE_BRIDGE; - else if (!g_strcmp0 (type, "dummy")) - res = NM_IFACE_TYPE_DUMMY; - - rtnl_link_put (result); -out: - return res; -} - -/** - * nm_system_get_iface_vlan_info: - * @ifindex: the VLAN interface index - * @out_parent_ifindex: on success, the interface index of the parent interface of - * @iface - * @out_vlan_id: on success, the VLAN ID of @iface - * - * Gets the VLAN parent interface name and VLAN ID. - * - * Returns: %TRUE if the interface is a VLAN device and no error occurred; - * %FALSE if the interface was not a VLAN interface or an error occurred - **/ -gboolean -nm_system_get_iface_vlan_info (int ifindex, - int *out_parent_ifindex, - int *out_vlan_id) -{ - struct nl_sock *nlh; - struct rtnl_link *lk; - struct nl_cache *cache = NULL; - gboolean success = FALSE; - int ret; - - if (nm_system_get_iface_type (ifindex, NULL) != NM_IFACE_TYPE_VLAN) - return FALSE; - - nlh = nm_netlink_get_default_handle (); - if (!nlh) - return FALSE; - - ret = rtnl_link_alloc_cache (nlh, AF_UNSPEC, &cache); - g_return_val_if_fail (ret == 0, FALSE); - g_return_val_if_fail (cache != NULL, FALSE); - - lk = rtnl_link_get (cache, ifindex); - if (lk) { - if (out_parent_ifindex) - *out_parent_ifindex = rtnl_link_get_link (lk); - if (out_vlan_id) - *out_vlan_id = rtnl_link_vlan_get_id (lk); - - rtnl_link_put (lk); - success = TRUE; - } - - nl_cache_free (cache); - return success; -} - -static gboolean -nm_system_iface_compat_set_name (const char *old_name, const char *new_name) -{ - int fd; - struct ifreq ifr; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&ifr, 0, sizeof (struct ifreq)); - strncpy (ifr.ifr_name, old_name, sizeof (ifr.ifr_name)); - strncpy (ifr.ifr_newname, new_name, sizeof (ifr.ifr_newname)); - - if (ioctl (fd, SIOCSIFNAME, &ifr) < 0) { - nm_log_err (LOGD_DEVICE, "cann't change %s with %s.", old_name, new_name); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_set_vlan_name_type (int name_type) -{ - int fd; - struct vlan_ioctl_args if_request; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - if_request.cmd = SET_VLAN_NAME_TYPE_CMD; - if_request.u.name_type = name_type; - - if (ioctl (fd, SIOCSIFVLAN, &if_request) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't set name type."); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_add_vlan_device (const char *master, int vid) -{ - int fd; - struct vlan_ioctl_args if_request; - - g_return_val_if_fail (master, FALSE); - g_return_val_if_fail (vid < 4096, FALSE); - - /* - * use VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD as default, - * we will overwrite it with rtnl_link_set_name() later. - */ - if (!nm_system_iface_compat_set_vlan_name_type (VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD)) - return FALSE; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - g_strlcpy (if_request.device1, master, sizeof (if_request.device1)); - if_request.cmd = ADD_VLAN_CMD; - if_request.u.VID = vid; - - if (ioctl (fd, SIOCSIFVLAN, &if_request) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't add vlan device %s vid %d: %d.", master, vid, errno); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_rem_vlan_device (const char *iface) -{ - int fd; - struct vlan_ioctl_args if_request; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -1; - } - - memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - g_strlcpy (if_request.device1, iface, sizeof (if_request.device1)); - if_request.cmd = DEL_VLAN_CMD; - - if (ioctl (fd, SIOCSIFVLAN, &if_request) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't rem vlan device %s.", iface); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static gboolean -nm_system_iface_compat_add_vlan (NMConnection *connection, - const char *iface, - int master_ifindex) -{ - NMSettingVlan *s_vlan; - int vlan_id; - guint32 vlan_flags = 0; - guint32 num, i, from, to; - int ifindex; - struct rtnl_link *new_link = NULL; - char *master = nm_netlink_index_to_iface (master_ifindex); - int itype; - gboolean created = FALSE; - - s_vlan = nm_connection_get_setting_vlan (connection); - g_return_val_if_fail (s_vlan, FALSE); - - vlan_id = nm_setting_vlan_get_id (s_vlan); - - if (!iface) { - iface = nm_connection_get_virtual_iface_name (connection); - g_return_val_if_fail (iface != NULL, FALSE); - } - - itype = nm_system_get_iface_type (-1, iface); - if (itype == NM_IFACE_TYPE_UNSPEC) { - char *name; - - /* Create the VLAN interface. Use VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD as - * default and change the name later via nm_system_iface_compat_set_name(). - * The old ioctl-based VLAN kernel API has no ability to directly return - * the new interface's name or index, so we have to create it with a - * known name and do the rename dance instead. - */ - if (!nm_system_iface_compat_add_vlan_device (master, vlan_id)) - return FALSE; - - /* And rename it to what the connection wants */ - name = nm_utils_new_vlan_name (master, vlan_id); - if (strcmp (name, iface) != 0) { - if (!nm_system_iface_compat_set_name (name, iface)) { - nm_system_iface_compat_rem_vlan_device (name); - g_free (name); - return FALSE; - } - } - g_free (name); - created = TRUE; - } else if (itype != NM_IFACE_TYPE_VLAN) { - nm_log_err (LOGD_DEVICE, "(%s): already exists but is not a VLAN interface.", iface); - return FALSE; - } else { - int tmp_vlan_id = -1, tmp_master_ifindex = -1; - - /* VLAN interface with this name already exists. Be a bit paranoid and - * double-check the VLAN ID and parent ifindex. - */ - ifindex = nm_netlink_iface_to_index (iface); - if (ifindex <= 0) - return FALSE; - - if (!nm_system_get_iface_vlan_info (ifindex, &tmp_master_ifindex, &tmp_vlan_id)) { - nm_log_err (LOGD_DEVICE, "(%s): failed to get VLAN interface info.", iface); - return FALSE; - } - - if (tmp_master_ifindex != master_ifindex) { - nm_log_err (LOGD_DEVICE, "(%s): master ifindex (%d) does match expected (%d).", - iface, tmp_master_ifindex, master_ifindex); - return FALSE; - } - - if (tmp_vlan_id != vlan_id) { - nm_log_err (LOGD_DEVICE, "(%s): VLAN ID %d does match expected ID %d.", - iface, tmp_vlan_id, vlan_id); - return FALSE; - } - - nm_log_dbg (LOGD_DEVICE, "(%s): found existing VLAN interface.", iface); - } - - ifindex = nm_netlink_iface_to_index (iface); - if (ifindex <= 0) - goto error; - - new_link = nm_netlink_index_to_rtnl_link (ifindex); - if (!new_link) - goto error; - - /* vconfig set_flag */ - vlan_flags = nm_setting_vlan_get_flags (s_vlan); - if (vlan_flags) { - if (rtnl_link_vlan_set_flags (new_link, vlan_flags)) - goto error_new_link; - } - - /* vconfig set_ingress_map */ - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to)) { - if (rtnl_link_vlan_set_ingress_map (new_link, from, to)) - goto error_new_link; - } - } - - /* vconfig set_egress_map */ - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) { - if (rtnl_link_vlan_set_egress_map (new_link, from, to)) - goto error_new_link; - } - } - - rtnl_link_put (new_link); - return TRUE; - -error_new_link: - rtnl_link_put (new_link); - /* fall through */ - -error: - if (created) - nm_system_iface_compat_rem_vlan_device (iface); - return FALSE; -} - -/** - * nm_system_add_vlan_iface: - * @connection: the #NMConnection that describes the VLAN interface - * @iface: the interface name of the new VLAN interface - * @parent_ifindex: the interface index of the new VLAN interface's master - * interface - * - * Add a VLAN device named @iface and specified in @connection. - * - * Returns: %TRUE on success, %FALSE on failure - */ -gboolean -nm_system_add_vlan_iface (NMConnection *connection, - const char *iface, - int parent_ifindex) -{ - NMSettingVlan *s_vlan; - int ret = -1; - struct rtnl_link *new_link = NULL; - struct nl_sock *nlh = NULL; - guint32 vlan_id = 0; - guint32 vlan_flags = 0; - guint32 num, i, from, to; - - g_return_val_if_fail (parent_ifindex > 0, FALSE); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - s_vlan = nm_connection_get_setting_vlan (connection); - g_return_val_if_fail (s_vlan, FALSE); - - vlan_id = nm_setting_vlan_get_id (s_vlan); - - if (!iface) { - iface = nm_connection_get_virtual_iface_name (connection); - g_return_val_if_fail (iface != NULL, FALSE); - } - - new_link = rtnl_link_alloc (); - if (!new_link) { - g_warn_if_fail (new_link != NULL); - goto out; - } - - ret = rtnl_link_set_type (new_link, "vlan"); - if (ret == -NLE_OPNOTSUPP) { - /* - * There is no linbl3, try ioctl. - */ - ret = -1; - if (nm_system_iface_compat_add_vlan (connection, iface, parent_ifindex)) - ret = 0; - goto out; - } - - rtnl_link_set_link (new_link, parent_ifindex); - rtnl_link_set_name (new_link, iface); - rtnl_link_vlan_set_id (new_link, vlan_id); - - vlan_flags = nm_setting_vlan_get_flags (s_vlan); - if (vlan_flags) { - guint kernel_flags = 0; - - if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS) - kernel_flags |= VLAN_FLAG_REORDER_HDR; - if (vlan_flags & NM_VLAN_FLAG_GVRP) - kernel_flags |= VLAN_FLAG_GVRP; - if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING) - kernel_flags |= VLAN_FLAG_LOOSE_BINDING; - - rtnl_link_vlan_set_flags (new_link, kernel_flags); - } - - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to)) - rtnl_link_vlan_set_ingress_map (new_link, (int) from, (int) to); - } - - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) - rtnl_link_vlan_set_egress_map (new_link, (int) from, (int) to); - } - - ret = rtnl_link_add (nlh, new_link, NLM_F_CREATE); - -out: - if (new_link) - rtnl_link_put (new_link); - return (ret == 0); -} - -/** - * nm_system_del_vlan_iface: - * @iface: the interface name - * - * Delete a VLAN interface specified by @iface. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_del_vlan_iface (const char *iface) -{ - int ret = 0; - struct nl_sock *nlh = NULL; - struct nl_cache *cache = NULL; - struct rtnl_link *new_link = NULL; - int itype; - - g_return_val_if_fail (iface != NULL, FALSE); - - itype = nm_system_get_iface_type (-1, iface); - g_return_val_if_fail (itype == NM_IFACE_TYPE_VLAN, FALSE); - - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); - - ret = rtnl_link_alloc_cache (nlh, AF_UNSPEC, &cache); - g_return_val_if_fail (ret == 0, FALSE); - g_return_val_if_fail (cache != NULL, FALSE); - - new_link = rtnl_link_get_by_name (cache, iface); - if (new_link) { - ret = rtnl_link_delete (nlh, new_link); - if (ret == -NLE_OPNOTSUPP) { - /* - * There is no linbl3, try ioctl. - */ - ret = -1; - if (nm_system_iface_compat_rem_vlan_device (iface)) - ret = 0; - } - } - - rtnl_link_put (new_link); - nl_cache_free (cache); - return (ret == 0) ? TRUE : FALSE; -} - -static int -_bridge_create_compat (const char *iface) -{ - int ret = 0, fd; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - if (ioctl (fd, SIOCBRADDBR, iface) < 0) - ret = -errno; - - close (fd); - return ret; -} - -/** - * nm_system_create_bridge: - * @iface: Name bridging device to create - * @out_exists: on return, %TRUE if the bridge already exists - * - * Creates a new bridging device in the kernel. If a bridging device with - * the specified name already exists, it is reused and no error is returned, - * but @out_exists is set to %TRUE. - * - * Returns: %TRUE on success, %FALSE on error. - */ -gboolean -nm_system_create_bridge (const char *iface, gboolean *out_exists) -{ - int err; - - /* FIXME: use netlink */ - err = _bridge_create_compat (iface); - if (err < 0 && err != -EEXIST) { - nm_log_err (LOGD_DEVICE, "(%s): error while adding bridge: %s", - iface, strerror (-err)); - return FALSE; - } - if (out_exists && err == -EEXIST) - *out_exists = TRUE; - return TRUE; -} - -static int -_bridge_del_compat (const char *iface) -{ - int ret = 0, fd; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - if (ioctl (fd, SIOCBRDELBR, iface) < 0) - ret = -errno; - - close (fd); - return ret; -} - -/** - * nm_system_del_bridge: - * @iface: Name of bridging device to delete - * - * Deletes the specified bridging device in the kernel. - * - * Returns: %TRUE on success, %FALSE on error. - */ -gboolean -nm_system_del_bridge (const char *iface) -{ - int err; - - /* FIXME: use netlink */ - err = _bridge_del_compat (iface); - if (err < 0 && err != -ENXIO) { - nm_log_err (LOGD_DEVICE, "(%s): error while deleting bridge: %s ", - iface, strerror (-err)); - return FALSE; - } - return TRUE; -} - -static int -_bridge_attach_compat (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - int ret = 0, fd; - struct ifreq ifr; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - memset (&ifr, 0, sizeof (ifr)); - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - ifr.ifr_ifindex = slave_ifindex; - if (ioctl (fd, SIOCBRADDIF, &ifr) < 0) - ret = -errno; - - close (fd); - return ret; -} - -static int -_bridge_detach_compat (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - int ret = 0, fd; - struct ifreq ifr; - - if ((fd = socket (AF_LOCAL, SOCK_STREAM, 0)) < 0) { - nm_log_err (LOGD_DEVICE, "couldn't open control socket."); - return -EBADF; - } - - memset (&ifr, 0, sizeof(ifr)); - strncpy (ifr.ifr_name, master_iface, IFNAMSIZ); - ifr.ifr_ifindex = slave_ifindex; - if (ioctl (fd, SIOCBRDELIF, &ifr) < 0) - ret = -errno; - - close (fd); - return ret; -} - -/** - * nm_system_bridge_attach: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Attaches interface 'slave' to bridge 'master' - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bridge_attach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - char *mif = NULL, *sif = NULL; - int err = -1; - - g_return_val_if_fail (master_ifindex >= 0, FALSE); - g_return_val_if_fail (slave_ifindex >= 0, FALSE); - - if (!master_iface) { - mif = nm_netlink_index_to_iface (master_ifindex); - if (mif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", master_ifindex); - goto out; - } - } - - if (!slave_ifindex) { - sif = nm_netlink_index_to_iface (slave_ifindex); - if (sif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", slave_ifindex); - goto out; - } - } - - /* FIXME: long term plan is to use netlink for this */ - err = _bridge_attach_compat (master_ifindex, - mif ? mif : master_iface, - slave_ifindex, - sif ? sif : slave_iface); - if (err < 0) { - if (err == -EBUSY) { - /* Interface already attached to the given bridge */ - err = 0; - } else { - nm_log_err (LOGD_DEVICE, "(%s): failed to attach slave %s: %s", - master_iface, slave_iface, strerror (-err)); - } - } - -out: - g_free (sif); - g_free (mif); - return err == 0 ? TRUE : FALSE; -} - -/** - * nm_system_bridge_detach: - * @master_ifindex: master device interface index - * @master_iface: master device interface name - * @slave_ifindex: slave device interface index - * @slave_iface: slave device interface name - * - * Detaches the interface 'slave' from the bridge 'master'. - * - * Returns: %TRUE on success, or %FALSE - */ -gboolean -nm_system_bridge_detach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface) -{ - char *mif = NULL, *sif = NULL; - int err = -1; - - g_return_val_if_fail (master_ifindex >= 0, FALSE); - g_return_val_if_fail (slave_ifindex >= 0, FALSE); - - if (!master_iface) { - mif = nm_netlink_index_to_iface (master_ifindex); - if (mif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", master_ifindex); - goto out; - } - } - - if (!slave_ifindex) { - sif = nm_netlink_index_to_iface (slave_ifindex); - if (sif == NULL) { - nm_log_err (LOGD_DEVICE, "interface name lookup failed for index %d", slave_ifindex); - goto out; - } - } - - /* FIXME: long term plan is to use netlink for this */ - err = _bridge_detach_compat (master_ifindex, - mif ? mif : master_iface, - slave_ifindex, - sif ? sif : slave_iface); - /* Kernel doesn't return an error detaching an already-detached interface */ - if (err < 0) { - nm_log_err (LOGD_DEVICE, "(%s): failed to detach slave %s: %s", - master_iface, slave_iface, strerror (-err)); - } - -out: - g_free (mif); - g_free (sif); - return err == 0 ? TRUE : FALSE; -} diff --git a/src/nm-system.h b/src/nm-system.h index 632786d3d..b2cee7a9e 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -22,16 +22,12 @@ #ifndef NETWORK_MANAGER_SYSTEM_H #define NETWORK_MANAGER_SYSTEM_H -#include +#include #include -#include - -#include #include "nm-device.h" #include "nm-ip4-config.h" #include "nm-setting-bond.h" -#include "nm-setting-vlan.h" gboolean nm_system_iface_flush_routes (int ifindex, int family); @@ -83,61 +79,6 @@ gboolean nm_system_apply_ip6_config (int ifindex, int priority, NMIP6ConfigCompareFlags flags); -gboolean nm_system_iface_set_up (int ifindex, - gboolean up, - gboolean *no_firmware); - -guint32 nm_system_iface_get_flags (int ifindex); -gboolean nm_system_iface_is_up (int ifindex); - -gboolean nm_system_iface_set_mtu (int ifindex, guint32 mtu); - -gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac); - -gboolean nm_system_iface_set_arp (int ifindex, gboolean arp); - gboolean nm_system_apply_bonding_config (const char *iface, NMSettingBond *s_bond); -gboolean nm_system_add_bonding_master (const char *iface); - -gboolean nm_system_bond_enslave (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface); -gboolean nm_system_bond_release (gint master_ifindex, - const char *master_iface, - gint slave_ifindex, - const char *slave_iface); - -enum { - NM_IFACE_TYPE_UNSPEC = 0, - NM_IFACE_TYPE_BOND, - NM_IFACE_TYPE_VLAN, - NM_IFACE_TYPE_BRIDGE, - NM_IFACE_TYPE_DUMMY -}; - -int nm_system_get_iface_type (int ifindex, const char *name); - -gboolean nm_system_get_iface_vlan_info (int ifindex, - int *out_parent_ifindex, - int *out_vlan_id); - -gboolean nm_system_add_vlan_iface (NMConnection *connection, - const char *iface, - int parent_ifindex); -gboolean nm_system_del_vlan_iface (const char *iface); - -gboolean nm_system_create_bridge (const char *iface, gboolean *out_exists); -gboolean nm_system_del_bridge (const char *iface); - -gboolean nm_system_bridge_attach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface); -gboolean nm_system_bridge_detach (int master_ifindex, - const char *master_iface, - int slave_ifindex, - const char *slave_iface); - #endif