TError TNlClass::Load(const TNl &nl) { struct nl_cache *cache; struct rtnl_class *tclass; int ret = rtnl_class_alloc_cache(nl.GetSock(), Index, &cache); if (ret < 0) return nl.Error(ret, "Cannot allocate class cache"); tclass = rtnl_class_get(cache, Index, Handle); if (!tclass) { nl_cache_free(cache); return TError(EError::Unknown, "Can't find tc class"); } Kind = rtnl_tc_get_kind(TC_CAST(tclass)); if (Kind == "htb") { Prio = rtnl_htb_get_prio(tclass); Rate = rtnl_htb_get_rate(tclass); Ceil = rtnl_htb_get_ceil(tclass); } if (Kind == "hfsc") { struct tc_service_curve sc; if (!rtnl_class_hfsc_get_fsc(tclass, &sc)) Rate = sc.m2; if (!rtnl_class_hfsc_get_usc(tclass, &sc)) Ceil = sc.m2; } rtnl_class_put(tclass); nl_cache_free(cache); return TError::Success(); }
/* * Get the first AF_INET address on 'link'. Returns 0 if successful. Caller * must release reference to *addr. */ static int get_link_inet_addr(struct nl_sock *sk, struct rtnl_link *link, struct nl_addr **addr) { struct nl_cache *addr_cache; int err; err = rtnl_addr_alloc_cache(sk, &addr_cache); if (err < 0) { warnx("rtnl_addr_alloc_cache() failed: %s", nl_geterror(err)); return 1; } /* Retrieve the first AF_INET address on the requested interface. */ struct rtnl_addr *filter; filter = rtnl_addr_alloc(); assert(filter); rtnl_addr_set_ifindex(filter, rtnl_link_get_ifindex(link)); rtnl_addr_set_family(filter, AF_INET); *addr = NULL; nl_cache_foreach_filter(addr_cache, (struct nl_object *)filter, match_first_addr, addr); if (*addr == NULL) { warnx("No AF_INET address found on veth"); rtnl_addr_put(filter); nl_cache_free(addr_cache); return 1; } rtnl_addr_put(filter); nl_cache_free(addr_cache); return 0; }
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) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, _("unable to allocate netlink handle for monitoring link status: %s"), nl_geterror (ENOMEM)); goto 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; } return FALSE; }
int main(int argc, char *argv[]) { struct nl_handle *nlh; struct nl_cache *link_cache, *addr_cache; struct rtnl_addr *addr; struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_BRIEF }; int err = 1; if (nltool_init(argc, argv) < 0) return -1; nlh = nltool_alloc_handle(); if (!nlh) return -1; addr = rtnl_addr_alloc(); if (!addr) goto errout; if (argc < 2 || !strcmp(argv[1], "-h")) print_usage(); if (nltool_connect(nlh, NETLINK_ROUTE) < 0) goto errout_free; link_cache = nltool_alloc_link_cache(nlh); if (!link_cache) goto errout_close; addr_cache = nltool_alloc_addr_cache(nlh); if (!addr_cache) goto errout_link_cache; params.dp_type = nltool_parse_dumptype(argv[1]); if (params.dp_type < 0) goto errout_addr_cache; get_filter(addr, argc, argv, 2, link_cache); nl_cache_dump_filter(addr_cache, ¶ms, (struct nl_object *) addr); err = 0; errout_addr_cache: nl_cache_free(addr_cache); errout_link_cache: nl_cache_free(link_cache); errout_close: nl_close(nlh); errout_free: rtnl_addr_put(addr); errout: return err; }
const std::list<vaddress> NetLinkManager::getAddressList(const vinterface &interface, const vaddress::Family f) { ibrcommon::MutexLock l(_call_mutex); if (_refresh_cache) { nl_cache_free(_addr_cache); nl_cache_free(_link_cache); _link_cache = rtnl_link_alloc_cache(_handle); if (_link_cache == NULL) { throw ibrcommon::vsocket_exception("netlink cache allocation failed"); } _addr_cache = rtnl_addr_alloc_cache(_handle); if (_addr_cache == NULL) { nl_cache_free(_link_cache); throw ibrcommon::vsocket_exception("netlink cache allocation failed"); } // mark the cache as refreshed _refresh_cache = false; } std::list<vaddress> addresses; struct rtnl_addr *filter = rtnl_addr_alloc(); const std::string i = interface.toString(); rtnl_addr_set_ifindex(filter, rtnl_link_name2i(_link_cache, i.c_str())); if (f == vaddress::VADDRESS_UNSPEC) { rtnl_addr_set_family(filter, AF_INET6); nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter, add_addr_to_list, &addresses); rtnl_addr_set_family(filter, AF_INET); nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter, add_addr_to_list, &addresses); } else { rtnl_addr_set_family(filter, f); nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter, add_addr_to_list, &addresses); } rtnl_addr_put(filter); return addresses; }
NetLinkManager::~NetLinkManager() { stop(); join(); // destroy the socket for the netlink interface delete _sock; nl_close(_handle); nl_cache_free(_addr_cache); nl_cache_free(_link_cache); nl_handle_destroy(_handle); }
bool devEthernet::hasLink() { if ( ! _netlinkSocket ) { MOD_ERROR("hasLink() called on uninitialized netlink socket."); return false; } nl_cache* cache; if ( rtnl_link_alloc_cache (_netlinkSocket, AF_UNSPEC, &cache) ) { MOD_ERROR("hasLink() rtnl_link_alloc_cache error: %s", nl_geterror(errno)); return false; } rtnl_link* link = rtnl_link_get(cache, index()); if ( ! link ) { MOD_ERROR("hasLink() rtnl_link_get error: %s", nl_geterror(errno)); nl_cache_free(cache); return false; } // First, check that interface is able to send uint8_t operState = rtnl_link_get_operstate(link); #ifdef DEFINE_DEBUG char buf[100]; rtnl_link_operstate2str (operState, buf, 100); MOD_DEBUG("operState is 0x%x (%s).", operState, buf); #endif bool ret = false; // Next make sure there's a carrier #ifndef IFF_LOWER_UP const int IFF_LOWER_UP = 0x10000; #endif #ifndef IFF_DORMANT const int IFF_DORMANT = 0x20000; #endif if ( operState == OperUp) { unsigned int flags = rtnl_link_get_flags (link); ret = ( ((flags & IFF_LOWER_UP) == IFF_LOWER_UP) && ((flags & IFF_DORMANT) != IFF_DORMANT) ); } rtnl_link_put(link); nl_cache_free(cache); return ret; }
netlink_wrapper::~netlink_wrapper() { nl_logdbg( "---> netlink_route_listener DTOR"); nl_cache_mngr_free(m_mngr); nl_cache_free(m_cache_link); nl_cache_free(m_cache_neigh); nl_cache_free(m_cache_route); nl_handle_destroy(m_handle); subject_map_iter iter = m_subjects_map.begin(); while (iter != m_subjects_map.end()) { delete iter->second; iter = iter++; } nl_logdbg( "<--- netlink_route_listener DTOR"); }
static bool nl80211_init() { int err; sock = nl_socket_alloc(); if (!sock) { fprintf(stderr, "failed to allocate netlink socket\n"); goto out; } err = genl_connect(sock); if (err) { nl_perror(err, "failed to make generic netlink connection"); goto out; } err = genl_ctrl_alloc_cache(sock, &cache); if (err) { nl_perror(err, "failed to allocate netlink controller cache"); goto out; } family = genl_ctrl_search_by_name(cache, NL80211_GENL_NAME); if (!family) { fprintf(stderr, "failed to find nl80211\n"); goto out; } return true; out: genl_family_put(family); nl_cache_free(cache); nl_socket_free(sock); return false; }
static void print_link(struct nl_object *obj, void *arg) { struct rtnl_link *link = (struct rtnl_link *) obj; struct rtnl_qdisc *qdisc; ifindex = rtnl_link_get_ifindex(link); dump_params.dp_prefix = 0; nl_object_dump(obj, &dump_params); class_cache = rtnl_class_alloc_cache(nl_handle, ifindex); if (!class_cache) return; qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); if (qdisc) { print_qdisc((struct nl_object *) qdisc, (void *) 2); rtnl_qdisc_put(qdisc); } qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0); if (qdisc) { print_qdisc((struct nl_object *) qdisc, (void *) 2); rtnl_qdisc_put(qdisc); } qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS); if (qdisc) { print_qdisc((struct nl_object *) qdisc, (void *) 2); rtnl_qdisc_put(qdisc); } nl_cache_free(class_cache); }
int sysnet_interface_set_mtu(VPNInterface *i, unsigned int mtu) { int err; struct nl_cache *link_cache; struct nl_sock *sock; struct rtnl_link *link; struct rtnl_link *new_link; sock = nl_socket_alloc(); nl_connect(sock, NETLINK_ROUTE); rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache); link = rtnl_link_get_by_name(link_cache, i->name); new_link = rtnl_link_alloc(); if (!link) { tox_trace(i->context->tox, "can't find link \"%s\"", i->name); return -1; } rtnl_link_set_mtu(new_link, mtu); if ((err = rtnl_link_change(sock, link, new_link, 0)) < 0) { tox_trace(i->context->tox, "unable to change link \"%s\" flags: %s", rtnl_link_get_name(link), nl_geterror(err)); } rtnl_link_put(link); rtnl_link_put(new_link); nl_cache_free(link_cache); nl_socket_free(sock); return 0; }
NetLinkManager::NetLinkManager() : _initialized(false), _sock(NULL), _refresh_cache(false) { ibrcommon::MutexLock l(_call_mutex); _handle = nl_handle_alloc(); nl_connect(_handle, NETLINK_ROUTE); _link_cache = rtnl_link_alloc_cache(_handle); if (_link_cache == NULL) { nl_close(_handle); nl_handle_destroy(_handle); throw ibrcommon::vsocket_exception("netlink cache allocation failed"); } _addr_cache = rtnl_addr_alloc_cache(_handle); if (_addr_cache == NULL) { nl_close(_handle); nl_handle_destroy(_handle); nl_cache_free(_link_cache); _link_cache = NULL; throw ibrcommon::vsocket_exception("netlink cache allocation failed"); } _initialized = true; // create a new socket for the netlink interface _sock = new ibrcommon::vsocket(); }
static void 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) nm_netlink_monitor_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; } if (priv->nlh_sync) { nl_socket_free (priv->nlh_sync); priv->nlh_sync = NULL; } g_hash_table_destroy (priv->subscriptions); G_OBJECT_CLASS (nm_netlink_monitor_parent_class)->finalize (object); }
bool TNlHtb::Valid(const TNlLink &link, uint32_t defaultClass) { int ret; struct nl_cache *qdiscCache; bool valid = true; ret = rtnl_qdisc_alloc_cache(link.GetSock(), &qdiscCache); if (ret < 0) { L_ERR() << "can't alloc qdisc cache" << std::endl; return false; } struct rtnl_qdisc *qdisc = rtnl_qdisc_get(qdiscCache, link.GetIndex(), Handle); if (qdisc) { link.Dump("found", qdisc); if (rtnl_tc_get_ifindex(TC_CAST(qdisc)) != link.GetIndex()) valid = false; else if (rtnl_tc_get_parent(TC_CAST(qdisc)) != Parent) valid = false; else if (rtnl_tc_get_handle(TC_CAST(qdisc)) != Handle) valid = false; else if (rtnl_tc_get_kind(TC_CAST(qdisc)) != std::string("htb")) valid = false; else if (rtnl_htb_get_defcls(qdisc) != TC_H_MIN(defaultClass)) valid = false; } else { valid = false; } rtnl_qdisc_put(qdisc); nl_cache_free(qdiscCache); return valid; }
/** * nm_netlink_foreach_route: * @ifindex: the interface index to filter routes for * @family: the address family to filter routes for * @scope: route scope, eg RT_SCOPE_LINK * @ignore_inet6_ll_mc: if %TRUE ignore IPv6 link-local and multi-cast routes * @callback: function called when a route matches the filter * @user_data: data passed to @callback * * Filters each route in the routing table against the given @ifindex and * @family (if given) and calls @callback for each matching route. * * Returns: a route if @callback returned one; the caller must dispose of the * route using rtnl_route_put() when it is no longer required. **/ struct rtnl_route * nm_netlink_foreach_route (int ifindex, int family, int scope, gboolean ignore_inet6_ll_mc, NlRouteForeachFunc callback, gpointer user_data) { struct nl_cache *cache; ForeachRouteInfo info; memset (&info, 0, sizeof (info)); info.ifindex = ifindex; info.family = family; info.scope = scope; info.ignore_inet6_ll_mc = ignore_inet6_ll_mc; info.callback = callback; info.user_data = user_data; info.iface = nm_netlink_index_to_iface (ifindex); rtnl_route_alloc_cache (nm_netlink_get_default_handle (), family, 0, &cache); g_warn_if_fail (cache != NULL); if (cache) { nl_cache_foreach (cache, foreach_route_cb, &info); nl_cache_free (cache); } g_free (info.iface); return info.out_route; }
bool TNlCgFilter::Exists(const TNlLink &link) { int ret; struct nl_cache *clsCache; ret = rtnl_cls_alloc_cache(link.GetSock(), link.GetIndex(), Parent, &clsCache); if (ret < 0) { L_ERR() << "Can't allocate filter cache: " << nl_geterror(ret) << std::endl; return false; } link.LogCache(clsCache); struct CgFilterIter { uint32_t parent; uint32_t handle; bool exists; } data = { Parent, Handle, false }; nl_cache_foreach(clsCache, [](struct nl_object *obj, void *data) { CgFilterIter *p = (CgFilterIter *)data; if (rtnl_tc_get_handle(TC_CAST(obj)) == p->handle && rtnl_tc_get_parent(TC_CAST(obj)) == p->parent) p->exists = true; }, &data); nl_cache_free(clsCache); return data.exists; }
/** * Add cache to cache manager * @arg mngr Cache manager. * @arg name Name of cache to keep track of * @arg cb Function to be called upon changes. * @arg data Argument passed on to change callback * @arg result Pointer to store added cache (optional) * * Allocates a new cache of the specified type and adds it to the manager. * The operation will trigger a full dump request from the kernel to * initially fill the contents of the cache. The manager will subscribe * to the notification group of the cache and keep track of any further * changes. * * The user is responsible for calling nl_cache_mngr_poll() or monitor * the socket and call nl_cache_mngr_data_ready() to allow the library * to process netlink notification events. * * @see nl_cache_mngr_poll() * @see nl_cache_mngr_data_ready() * * @return 0 on success or a negative error code. * @return -NLE_NOCACHE Unknown cache type * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache manager and * cache type * @return -NLE_OPNOTSUPP Cache type does not support updates * @return -NLE_EXIST Cache of this type already being managed */ int nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name, change_func_t cb, void *data, struct nl_cache **result) { struct nl_cache_ops *ops; struct nl_cache *cache; int err; ops = nl_cache_ops_lookup_safe(name); if (!ops) return -NLE_NOCACHE; cache = nl_cache_alloc(ops); nl_cache_ops_put(ops); if (!cache) return -NLE_NOMEM; err = nl_cache_mngr_add_cache(mngr, cache, cb, data); if (err < 0) goto errout_free_cache; *result = cache; return 0; errout_free_cache: nl_cache_free(cache); return err; }
/** * Free cache manager and all caches. * @arg mngr Cache manager. * * Release all resources held by a cache manager. */ void nl_cache_mngr_free(struct nl_cache_mngr *mngr) { int i; if (!mngr) return; if (mngr->cm_sock) nl_close(mngr->cm_sock); if (mngr->cm_sync_sock) { nl_close(mngr->cm_sync_sock); nl_socket_free(mngr->cm_sync_sock); } if (mngr->cm_flags & NL_ALLOCATED_SOCK) nl_socket_free(mngr->cm_sock); for (i = 0; i < mngr->cm_nassocs; i++) { if (mngr->cm_assocs[i].ca_cache) { nl_cache_mngt_unprovide(mngr->cm_assocs[i].ca_cache); nl_cache_free(mngr->cm_assocs[i].ca_cache); } } free(mngr->cm_assocs); NL_DBG(1, "Cache manager %p freed\n", mngr); free(mngr); }
static void finalize (GObject *object) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (object); g_signal_handler_disconnect (priv->monitor, priv->netlink_id); g_hash_table_destroy (priv->devices); g_object_unref (priv->monitor); nl_cache_free (priv->addr_cache); nl_cache_free (priv->route_cache); singleton = NULL; G_OBJECT_CLASS (nm_ip6_manager_parent_class)->finalize (object); }
static void nl80211_cleanup(struct nl80211_state *state) { genl_family_put(state->nl80211); nl_cache_free(state->nl_cache); nl_socket_free(state->nl_sock); }
static void netlink_exit(void) { g_io_channel_unref(channel); genl_family_put(family); nl_cache_free(cache); nl_handle_destroy(handle); }
static void __dump_link(int ifindex, struct rtnl_cls *filter) { struct nl_cache *cache; uint32_t parent = rtnl_tc_get_parent((struct rtnl_tc *) filter); cache = nl_cli_cls_alloc_cache(sock, ifindex, parent); nl_cache_dump_filter(cache, ¶ms, OBJ_CAST(filter)); nl_cache_free(cache); }
static void __delete_link(int ifindex, struct rtnl_cls *filter) { struct nl_cache *cache; uint32_t parent = rtnl_tc_get_parent((struct rtnl_tc *) filter); cache = nl_cli_cls_alloc_cache(sock, ifindex, parent); nl_cache_foreach_filter(cache, OBJ_CAST(filter), delete_cb, NULL); nl_cache_free(cache); }
int main(int argc, char *argv[]) { struct nl_cache *link_cache; if (nltool_init(argc, argv) < 0) return -1; dump_params.dp_fd = stdout; if (argc > 1) { if (!strcasecmp(argv[1], "brief")) dump_params.dp_type = NL_DUMP_BRIEF; else if (!strcasecmp(argv[1], "full")) dump_params.dp_type = NL_DUMP_FULL; else if (!strcasecmp(argv[1], "stats")) dump_params.dp_type = NL_DUMP_STATS; } nl_handle = nl_handle_alloc_nondefault(nltool_cbset); if (!nl_handle) return 1; if (nltool_connect(nl_handle, NETLINK_ROUTE) < 0) return 1; link_cache = nltool_alloc_link_cache(nl_handle); if (!link_cache) return 1; qdisc_cache = nltool_alloc_qdisc_cache(nl_handle); if (!qdisc_cache) return 1; nl_cache_foreach(link_cache, &print_link, NULL); nl_cache_free(qdisc_cache); nl_cache_free(link_cache); nl_close(nl_handle); nl_handle_destroy(nl_handle); return 0; }
int main(int argc, char *argv[]) { struct rtnl_link *link; struct nl_cache *link_cache; struct nl_sock *sk; int err; sk = nl_socket_alloc(); if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { nl_perror(err, "Unable to connect socket"); return err; } if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { nl_perror(err, "Unable to allocate cache"); return err; } if ((err = create_bridge(sk, link_cache, TEST_BRIDGE_NAME)) < 0) { nl_perror(err, "Unable to allocate testbridge"); return err; } nl_cache_refill(sk, link_cache); link = rtnl_link_get_by_name(link_cache, TEST_BRIDGE_NAME); struct rtnl_link *ltap = rtnl_link_get_by_name(link_cache, TEST_INTERFACE_NAME); if (!ltap) { fprintf(stderr, "You should create a tap interface before lunch this test (# tunctl -t %s)\n", TEST_INTERFACE_NAME); return -1; } if ((err = rtnl_link_enslave(sk, link, ltap)) < 0) { nl_perror(err, "Unable to enslave interface to his bridge\n"); return err; } if(rtnl_link_is_bridge(link) == 0) { fprintf(stderr, "Link is not a bridge\n"); return -2; } if(rtnl_link_get_master(ltap) <= 0) { fprintf(stderr, "Interface is not attached to a bridge\n"); return -3; } rtnl_link_put(ltap); rtnl_link_put(link); nl_cache_free(link_cache); nl_socket_free(sk); return 0; }
static int netlink_init(void) { info("Starting experimental netlink support"); handle = nl_handle_alloc(); if (!handle) { error("Failed to allocate netlink handle"); return -ENOMEM; } if (genl_connect(handle) < 0) { error("Failed to connect to generic netlink"); nl_handle_destroy(handle); return -ENOLINK; } cache = genl_ctrl_alloc_cache(handle); if (!cache) { error("Failed to allocate generic netlink cache"); return -ENOMEM; nl_handle_destroy(handle); } family = genl_ctrl_search_by_name(cache, "bluetooth"); if (!family) { error("Failed to find Bluetooth netlink family"); nl_cache_free(cache); nl_handle_destroy(handle); return -ENOENT; } if (create_channel(nl_socket_get_fd(handle)) < 0) { error("Failed to create netlink IO channel"); genl_family_put(family); nl_cache_free(cache); nl_handle_destroy(handle); return -ENOMEM; } return 0; }
static void list_cls(int ifindex, uint32_t parent) { struct nl_cache *cls_cache; cls_cache = nl_cli_cls_alloc_cache(sock, ifindex, parent); params.dp_prefix += NUM_INDENT; nl_cache_dump(cls_cache, ¶ms); params.dp_prefix -= NUM_INDENT; nl_cache_free(cls_cache); }
void unl_free(struct unl *unl) { if (unl->family_name) free(unl->family_name); if (unl->sock) nl_socket_free(unl->sock); if (unl->cache) nl_cache_free(unl->cache); memset(unl, 0, sizeof(*unl)); }
TError TNlLink::WaitAddress(int timeout_s) { struct nl_cache *cache; int ret; L() << "Wait for autoconf at " << GetDesc() << std::endl; ret = rtnl_addr_alloc_cache(GetSock(), &cache); if (ret < 0) return Nl->Error(ret, "Cannot allocate addr cache"); do { for (auto obj = nl_cache_get_first(cache); obj; obj = nl_cache_get_next(obj)) { auto addr = (struct rtnl_addr *)obj; if (!rtnl_addr_get_local(addr) || rtnl_addr_get_ifindex(addr) != GetIndex() || rtnl_addr_get_family(addr) != AF_INET6 || rtnl_addr_get_scope(addr) >= RT_SCOPE_LINK || (rtnl_addr_get_flags(addr) & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))) continue; L() << "Got " << TNlAddr(rtnl_addr_get_local(addr)).Format() << " at " << GetDesc() << std::endl; nl_cache_free(cache); return TError::Success(); } usleep(1000000); ret = nl_cache_refill(GetSock(), cache); if (ret < 0) return Nl->Error(ret, "Cannot refill address cache"); } while (--timeout_s > 0); nl_cache_free(cache); return TError(EError::Unknown, "Network autoconf timeout"); }
void nl80211_close(void) { if (nls) { if (nls->nl_sock) nl_socket_free(nls->nl_sock); if (nls->nl_cache) nl_cache_free(nls->nl_cache); free(nls); nls = NULL; } }