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; }
/* * 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; }
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 nm_ip6_manager_init (NMIP6Manager *manager) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); priv->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) nm_ip6_device_destroy); priv->monitor = nm_netlink_monitor_get (); nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_IFADDR, NULL); nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_PREFIX, NULL); nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_ROUTE, NULL); nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_ND_USEROPT, NULL); nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_LINK, NULL); priv->netlink_id = g_signal_connect (priv->monitor, "notification", G_CALLBACK (netlink_notification), manager); priv->nlh = nm_netlink_get_default_handle (); rtnl_addr_alloc_cache (priv->nlh, &priv->addr_cache); g_warn_if_fail (priv->addr_cache != NULL); rtnl_route_alloc_cache (priv->nlh, NETLINK_ROUTE, NL_AUTO_PROVIDE, &priv->route_cache); g_warn_if_fail (priv->route_cache != NULL); }
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; }
struct nl_cache *nltool_alloc_addr_cache(struct nl_handle *nlh) { struct nl_cache *cache; cache = rtnl_addr_alloc_cache(nlh); if (!cache) fprintf(stderr, "Unable to retrieve address cache: %s\n", nl_geterror()); else nl_cache_mngt_provide(cache); return cache; }
static bool nl_new(struct dionaea *d) { g_debug("%s", __PRETTY_FUNCTION__); nl_runtime.sock = nl_socket_alloc(); struct nl_sock *sock = nl_runtime.sock; nl_socket_disable_seq_check(sock); nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, nl_event_input, NULL); nl_join_groups(sock, RTMGRP_LINK); int err; if ( (err = nl_connect(sock, NETLINK_ROUTE)) < 0) { g_error("Could not connect netlink (%s)", nl_geterror(err)); } nl_socket_add_membership(sock, RTNLGRP_LINK); nl_socket_add_membership(sock, RTNLGRP_NEIGH); nl_socket_add_membership(sock, RTNLGRP_IPV4_IFADDR); nl_socket_add_membership(sock, RTNLGRP_IPV6_IFADDR); if( (err=rtnl_neigh_alloc_cache(sock, &nl_runtime.neigh_cache)) != 0 ) { g_error("Could not allocate neigh cache! (%s)", nl_geterror(err)); } #if LIBNL_RTNL_LINK_ALLOC_CACHE_ARGC == 3 if( (err=rtnl_link_alloc_cache(sock, AF_UNSPEC, &nl_runtime.link_cache)) != 0 ) #elif LIBNL_RTNL_LINK_ALLOC_CACHE_ARGC == 2 if( (err=rtnl_link_alloc_cache(sock, &nl_runtime.link_cache)) != 0 ) #endif { g_error("Could not allocate link cache! (%s)", nl_geterror(err)); } if( (err=rtnl_addr_alloc_cache(sock, &nl_runtime.addr_cache)) != 0 ) { g_error("Could not allocate addr cache! (%s)", nl_geterror(err)); } nl_cache_mngt_provide(nl_runtime.neigh_cache); nl_cache_mngt_provide(nl_runtime.link_cache); nl_cache_mngt_provide(nl_runtime.addr_cache); nl_runtime.ihandler = ihandler_new("dionaea.connection.*.accept", nl_ihandler_cb, NULL); ev_io_init(&nl_runtime.io_in, nl_io_in_cb, nl_socket_get_fd(sock), EV_READ); ev_io_start(g_dionaea->loop, &nl_runtime.io_in); nl_runtime.link_addr_cache = g_hash_table_new(g_int_hash, g_int_equal); nl_cache_foreach(nl_runtime.link_cache, nl_obj_input, NULL); nl_cache_foreach(nl_runtime.addr_cache, nl_obj_input, NULL); return true; }
/** * nm_netlink_find_address: * @ifindex: interface index * @family: address family, either AF_INET or AF_INET6 * @addr: binary address, either struct in_addr* or struct in6_addr* * @prefix: prefix length * * Searches for a matching address on the given interface. * * Returns: %TRUE if the given address was found on the interface, %FALSE if it * was not found or an error occurred. **/ gboolean nm_netlink_find_address (int ifindex, int family, void *addr, /* struct in_addr or struct in6_addr */ int prefix) { struct nl_sock *nlh = NULL; struct nl_cache *cache = NULL; FindAddrInfo info; g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); g_return_val_if_fail (addr != NULL, FALSE); g_return_val_if_fail (prefix >= 0, FALSE); memset (&info, 0, sizeof (info)); info.ifindex = ifindex; info.family = family; info.prefix = prefix; info.addr = addr; if (family == AF_INET) info.addrlen = sizeof (struct in_addr); else if (family == AF_INET6) info.addrlen = sizeof (struct in6_addr); else g_assert_not_reached (); nlh = nm_netlink_get_default_handle (); if (nlh) { rtnl_addr_alloc_cache(nlh, &cache); if (cache) { nl_cache_mngt_provide (cache); nl_cache_foreach (cache, find_one_address, &info); nl_cache_free (cache); } } return info.found; }
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"); }
/** * 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; }
int main(int argc, char *argv[]) { struct nl_sock *nl_sock; struct nl_cache *link_cache; int ifindex; int ret = 0; int err = 0; if (argc < 2) { printf("%s ip gw on/off tip\n", argv[0]); return -1; } //link if (err = rtnl_route_read_table_names(ROUTE_TABLE)) { printf("failed to read %s. err = %s\n", ROUTE_TABLE, nl_geterror(err)); return -1;; } nl_sock = nl_socket_alloc(); if (NULL == nl_sock) { printf("failed to alloc netlink handler.\n"); return -1; } if (err = nl_connect(nl_sock, NETLINK_ROUTE)) { printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } if (err = rtnl_link_alloc_cache(nl_sock, AF_INET, &link_cache)) { printf("failed to allocate link cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } ifindex = rtnl_link_name2i(link_cache, NAME); if (0 == ifindex) { printf("%s - failed to find.\n", NAME); ret = -1; goto release_link_cache; } struct rtnl_link * link = rtnl_link_get(link_cache, ifindex); if (link == NULL) { printf("can't get link.\n"); ret = -1; goto release_link_cache; } //rtnl_link_get_by_name struct nl_addr *lladdr = rtnl_link_get_addr(link); if (NULL == lladdr || AF_LLC != nl_addr_get_family(lladdr)) { printf("failed to get MAC\n"); ret = -1; goto release_link; } uint8_t mac_address[ETHER_ADDR_LEN]; memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN); printf("%02X:%02X:%02X:%02X:%02X:%02X\n", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); //addr struct nl_cache * addr_cache; if (err = rtnl_addr_alloc_cache(nl_sock, &addr_cache)) { printf("fail to get addr_cache\n"); ret = -1; goto release_link; } struct rtnl_addr *addr = rtnl_addr_alloc(); rtnl_addr_set_ifindex(addr, ifindex); rtnl_addr_set_family(addr, AF_INET); int prefixlen = 16; nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, get_ip, &prefixlen); nl_cache_free(addr_cache); uint32_t ipaddr = inet_addr(argv[1]); struct nl_addr * local = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr)); rtnl_addr_set_local(addr, local); rtnl_addr_set_ifindex(addr, ifindex); rtnl_addr_set_family(addr, AF_INET); rtnl_addr_set_prefixlen(addr, 32); if (!strcmp(argv[2], "on")) { if (err = rtnl_addr_add(nl_sock, addr, 0)) { printf("fail to add addr %s\n", nl_geterror(err)); ret = -1; goto release_addr; } } else { if (err = rtnl_addr_delete(nl_sock, addr, 0)) { printf("fail to del addr %s\n", nl_geterror(err)); ret = -1; goto release_addr; } } //neigh struct nl_cache * neigh_cache; if (err = rtnl_neigh_alloc_cache(nl_sock, &neigh_cache)) { printf("failed to allocate neighbor cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_neigh_cache; } uint32_t gw = inet_addr(argv[3]); struct nl_addr * gw_addr = nl_addr_build(AF_INET, &gw, sizeof(gw)); struct rtnl_neigh * neigh = rtnl_neigh_get(neigh_cache, ifindex, gw_addr); if (neigh) { // It's optional struct nl_addr * lladdr = rtnl_neigh_get_lladdr(neigh); if (lladdr) { uint8_t mac_address[ETHER_ADDR_LEN]; memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN); printf("gw %02X:%02X:%02X:%02X:%02X:%02X\n", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]); } } nl_addr_put(gw_addr); //route struct nl_cache *route_cache; if (err = rtnl_route_alloc_cache(nl_sock, AF_INET, 0, &route_cache)) { printf("failed to allocate route cache. err = %s\n", nl_geterror(err)); ret = -1; goto release_neigh_cache; } struct rtnl_route *route = rtnl_route_alloc(); struct nl_addr * taddr; err = nl_addr_parse(argv[4], AF_INET, &taddr); if (err) { printf("failed to get taddr. err = %s\n", nl_geterror(err)); ret = -1; goto release_route_cache; } nl_cache_foreach_filter(route_cache, OBJ_CAST(route), get_route, NULL); /* struct nl_sock *nl_fib_sock; nl_fib_sock = nl_socket_alloc(); if (err = nl_connect(nl_fib_sock, NETLINK_FIB_LOOKUP)) { printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err)); ret = -1; goto release_nl; } struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_DETAILS, }; struct nl_cache *route_cache = flnl_result_alloc_cache(); struct flnl_request *req = flnl_request_alloc(); struct nl_addr * taddr; err = nl_addr_parse(argv[4], AF_INET, &taddr); if (err) { printf("failed to get taddr. err = %s\n", nl_geterror(err)); ret = -1; goto release_route; } int table = RT_TABLE_UNSPEC, scope = RT_SCOPE_UNIVERSE; flnl_request_set_addr(req, taddr); flnl_request_set_table(req, table); flnl_request_set_scope(req, scope); err = flnl_lookup(nl_fib_sock, req, route_cache); if (err) { printf("failed to fib lookup. err = %s\n", nl_geterror(err)); ret = -1; goto release_route_addr; } nl_cache_dump(route_cache, ¶ms); release_route_addr: nl_addr_put(taddr); release_route: nl_cache_free(route_cache); nl_object_put(OBJ_CAST(req)); nl_close(nl_fib_sock); nl_socket_free(nl_fib_sock); */ release_route_cache: nl_cache_free(route_cache); release_neigh_cache: nl_cache_free(neigh_cache); release_addr: nl_addr_put(local); rtnl_addr_put(addr); release_link: rtnl_link_put(link); release_link_cache: nl_cache_free(link_cache); release_nl: nl_close(nl_sock); nl_socket_free(nl_sock); return ret; }
static J4statusPluginContext * _j4status_nl_init(J4statusCoreInterface *core) { gchar **interfaces = NULL; guint64 addresses = ADDRESSES_ALL; GKeyFile *key_file; key_file = j4status_config_get_key_file("Netlink"); if ( key_file != NULL ) { interfaces = g_key_file_get_string_list(key_file, "Netlink", "Interfaces", NULL, NULL); j4status_config_key_file_get_enum(key_file, "Netlink", "Addresses", _j4status_nl_addresses, G_N_ELEMENTS(_j4status_nl_addresses), &addresses); g_key_file_free(key_file); } if ( interfaces == NULL ) { g_message("No interface to monitor, aborting"); return NULL; } gint err; J4statusPluginContext *self; self = g_new0(J4statusPluginContext, 1); self->addresses = addresses; self->sections = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _j4status_nl_section_free); self->source = g_water_nl_source_new_cache_mngr(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &err); if ( self->source == NULL ) { g_warning("Couldn't subscribe to events: %s", nl_geterror(err)); goto error; } self->sock = g_water_nl_source_get_sock(self->source); self->cache_mngr = g_water_nl_source_get_cache_mngr(self->source); err = rtnl_link_alloc_cache(self->sock, AF_UNSPEC, &self->link_cache); if ( err < 0 ) { g_warning("Couldn't allocate links cache: %s", nl_geterror(err)); goto error; } err = nl_cache_mngr_add_cache(self->cache_mngr, self->link_cache, _j4status_nl_cache_change, self); if ( err < 0 ) { g_warning("Couldn't manage links cache: %s", nl_geterror(err)); goto error; } err = rtnl_addr_alloc_cache(self->sock, &self->addr_cache); if ( err < 0 ) { g_warning("Couldn't allocate addresses cache: %s", nl_geterror(err)); goto error; } err = nl_cache_mngr_add_cache(self->cache_mngr, self->addr_cache, _j4status_nl_cache_change, self); if ( err < 0 ) { g_warning("Couldn't manage addresses cache: %s", nl_geterror(err)); goto error; } gchar **interface; for ( interface = interfaces ; *interface != NULL ; ++interface ) { J4statusNlSection *section; section = _j4status_nl_section_new(self, core, *interface); if ( section != NULL ) g_hash_table_insert(self->sections, GINT_TO_POINTER(section->ifindex), section); else g_free(*interface); } g_free(interfaces); if ( g_hash_table_size(self->sections) < 1 ) goto error; self->formats.up = j4status_format_string_parse(NULL, _j4status_nl_format_up_tokens, G_N_ELEMENTS(_j4status_nl_format_up_tokens), J4STATUS_NL_DEFAULT_UP_FORMAT, NULL); self->formats.down = j4status_format_string_parse(NULL, NULL, 0, J4STATUS_NL_DEFAULT_DOWN_FORMAT, NULL); return self; error: _j4status_nl_uninit(self); return NULL; }