/** * Add a link to a bond (enslave) * @arg sock netlink socket * @arg master ifindex of bonding master * @arg slave ifindex of slave link to add to bond * * This function is identical to rtnl_link_bond_enslave() except that * it takes interface indices instead of rtnl_link objcets. * * @see rtnl_link_bond_enslave() * * @return 0 on success or a negative error code. */ int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, int slave) { struct rtnl_link *link; int err; if (!(link = rtnl_link_alloc())) return -NLE_NOMEM; if ((err = rtnl_link_set_type(link, "bond")) < 0) goto errout; rtnl_link_set_ifindex(link, slave); rtnl_link_set_master(link, master); if ((err = rtnl_link_change(sock, link, link, 0)) < 0) goto errout; rtnl_link_put(link); /* * Due to the kernel not signaling whether this opertion is * supported or not, we will retrieve the attribute to see if the * request was successful. If the master assigned remains unchanged * we will return NLE_OPNOTSUPP to allow performing backwards * compatibility of some sort. */ if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) return err; if (rtnl_link_get_master(link) != master) err = -NLE_OPNOTSUPP; errout: rtnl_link_put(link); return err; }
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 (self != NULL, FALSE); 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 */ }
/** * Query NETLINK for ethernet configuration * * @param ethinf Pointer to an available struct etherinfo element. The 'device' member * must contain a valid string to the device to query for information * @param nlc Pointer to the libnl handle, which is used for the query against NETLINK * @param query What to query for. Must be NLQRY_LINK or NLQRY_ADDR. * * @return Returns 1 on success, otherwise 0. */ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query) { struct nl_cache *link_cache; struct nl_cache *addr_cache; struct rtnl_addr *addr; struct rtnl_link *link; struct etherinfo *ethinf = NULL; int ret = 0; if( !data || !data->ethinfo ) { return 0; } ethinf = data->ethinfo; /* Open a NETLINK connection on-the-fly */ if( !open_netlink(data) ) { PyErr_Format(PyExc_RuntimeError, "Could not open a NETLINK connection for %s", ethinf->device); return 0; } /* Find the interface index we're looking up. * As we don't expect it to change, we're reusing a "cached" * interface index if we have that */ if( ethinf->index < 0 ) { link_cache = rtnl_link_alloc_cache(*data->nlc); ethinf->index = rtnl_link_name2i(link_cache, ethinf->device); if( ethinf->index < 0 ) { return 0; } nl_cache_free(link_cache); } /* Query the for requested info vai NETLINK */ switch( query ) { case NLQRY_LINK: /* Extract MAC/hardware address of the interface */ link_cache = rtnl_link_alloc_cache(*data->nlc); link = rtnl_link_alloc(); rtnl_link_set_ifindex(link, ethinf->index); nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf); rtnl_link_put(link); nl_cache_free(link_cache); ret = 1; break; case NLQRY_ADDR: /* Extract IP address information */ addr_cache = rtnl_addr_alloc_cache(*data->nlc); addr = rtnl_addr_alloc(); rtnl_addr_set_ifindex(addr, ethinf->index); /* Make sure we don't have any old IPv6 addresses saved */ if( ethinf->ipv6_addresses ) { free_ipv6addresses(ethinf->ipv6_addresses); ethinf->ipv6_addresses = NULL; } /* Retrieve all address information */ nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf); rtnl_addr_put(addr); nl_cache_free(addr_cache); ret = 1; break; default: ret = 0; } return ret; }