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; }
int main(int argc, char *argv[]) { struct nl_handle *nlh; struct nl_cache *link_cache; int err = 1; if (nltool_init(argc, argv) < 0) return -1; if (argc < 3 || !strcmp(argv[1], "-h")) print_usage(); nlh = nltool_alloc_handle(); if (!nlh) return -1; if (nltool_connect(nlh, NETLINK_ROUTE) < 0) goto errout; link_cache = nltool_alloc_link_cache(nlh); if (!link_cache) goto errout_close; gargv = &argv[2]; gargc = argc - 2; if (!strcasecmp(argv[1], "all")) nl_cache_foreach(link_cache, dump_stats, NULL); else { int ifindex = strtoul(argv[1], NULL, 0); struct rtnl_link *link = rtnl_link_get(link_cache, ifindex); if (!link) { fprintf(stderr, "Could not find ifindex %d\n", ifindex); goto errout_link_cache; } dump_stats((struct nl_object *) link, NULL); rtnl_link_put(link); } err = 0; errout_link_cache: nl_cache_free(link_cache); errout_close: nl_close(nlh); errout: nl_handle_destroy(nlh); return err; }
static int netlink3_reset_interface_parameters(const interface_t* ifp) { struct nl_sock *sk; struct nl_cache *cache; struct rtnl_link *link = NULL; struct rtnl_link *new_state = NULL; int res = 0; if (!(sk = nl_socket_alloc())) { log_message(LOG_INFO, "Unable to open netlink socket"); return -1; } if (nl_connect(sk, NETLINK_ROUTE) < 0) goto err; if (rtnl_link_alloc_cache(sk, AF_UNSPEC, &cache)) goto err; if (!(link = rtnl_link_get(cache, ifp->ifindex))) goto err; if (!(new_state = rtnl_link_alloc())) goto err; if (rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_ARP_IGNORE, ifp->reset_arp_ignore_value) || rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_ARPFILTER, ifp->reset_arp_filter_value) || rtnl_link_change(sk, link, new_state, 0)) goto err; rtnl_link_put(link); link = NULL; rtnl_link_put(new_state); new_state = NULL; goto exit; err: res = -1; if (link) rtnl_link_put(link); if (new_state) rtnl_link_put(new_state); exit: nl_socket_free(sk); return res; }
/* Given an interface's MAC address, return the name (e.g., eth0) in human * readable format. Return NULL for no match */ char *iface_mac2device(char *mac) { struct nl_handle *handle = NULL; struct nl_cache *cache = NULL; struct rtnl_link *link = NULL; struct nl_addr *mac_as_nl_addr = NULL; char *retval = NULL; int i, n; if (mac == NULL) { return NULL; } if ((mac_as_nl_addr = nl_addr_parse(mac, AF_LLC)) == NULL) { return NULL; } if ((cache = _iface_get_link_cache(&handle)) == NULL) { return NULL; } n = nl_cache_nitems(cache); for (i = 0; i <= n; i++) { struct nl_addr *addr; if ((link = rtnl_link_get(cache, i)) == NULL) { continue; } addr = rtnl_link_get_addr(link); if (!nl_addr_cmp(mac_as_nl_addr, addr)) { retval = strdup(rtnl_link_get_name(link)); rtnl_link_put(link); break; } rtnl_link_put(link); } nl_close(handle); nl_handle_destroy(handle); return retval; }
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); g_object_unref (self); return ret; }
// Returns the netlink link object associated with a given link by its // interface index. Returns None if the link is not found. inline Result<Netlink<struct rtnl_link>> get(int index) { Try<Netlink<struct nl_sock>> socket = routing::socket(); if (socket.isError()) { return Error(socket.error()); } // Dump all the netlink link objects from kernel. Note that the flag // AF_UNSPEC means all available families. struct nl_cache* c = NULL; int error = rtnl_link_alloc_cache(socket.get().get(), AF_UNSPEC, &c); if (error != 0) { return Error(nl_geterror(error)); } Netlink<struct nl_cache> cache(c); struct rtnl_link* l = rtnl_link_get(cache.get(), index); if (l == NULL) { return None(); } return Netlink<struct rtnl_link>(l); }
static int netlink3_set_interface_parameters(const interface_t *ifp, interface_t *base_ifp) { struct nl_sock *sk; struct nl_cache *cache; struct rtnl_link *link = NULL; struct rtnl_link *new_state = NULL; int res = 0; if (!(sk = nl_socket_alloc())) { log_message(LOG_INFO, "Unable to open netlink socket"); return -1; } if (nl_connect(sk, NETLINK_ROUTE) < 0) goto err; if (rtnl_link_alloc_cache(sk, AF_UNSPEC, &cache)) goto err; if (!(link = rtnl_link_get(cache, ifp->ifindex))) goto err; // Allocate a new link if (!(new_state = rtnl_link_alloc())) goto err; if (rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_ARP_IGNORE, 1) || rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_ACCEPT_LOCAL, 1) || rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_RP_FILTER, 0) || rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_PROMOTE_SECONDARIES, 1) || rtnl_link_change (sk, link, new_state, 0)) goto err; rtnl_link_put(new_state); new_state = NULL; rtnl_link_put(link); link = NULL; /* Set arp_ignore and arp_filter on base interface if needed */ if (base_ifp->reset_arp_config) (base_ifp->reset_arp_config)++; else { if (!(link = rtnl_link_get(cache, base_ifp->ifindex))) goto err; if (rtnl_link_inet_get_conf(link, IPV4_DEVCONF_ARP_IGNORE, &base_ifp->reset_arp_ignore_value) < 0) goto err; if (rtnl_link_inet_get_conf(link, IPV4_DEVCONF_ARPFILTER, &base_ifp->reset_arp_filter_value) < 0) goto err; if (base_ifp->reset_arp_ignore_value != 1 || base_ifp->reset_arp_filter_value != 1 ) { /* The underlying interface mustn't reply for our address(es) */ if (!(new_state = rtnl_link_alloc())) goto err; if (rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_ARP_IGNORE, 1) || rtnl_link_inet_set_conf(new_state, IPV4_DEVCONF_ARPFILTER, 1) || rtnl_link_change(sk, link, new_state, 0)) goto err; rtnl_link_put(new_state); new_state = NULL; rtnl_link_put(link); link = NULL; base_ifp->reset_arp_config = 1; } } goto exit; err: res = -1; if (link) rtnl_link_put(link); if (new_state) rtnl_link_put(new_state); exit: nl_socket_free(sk); return res; }
int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc) { struct nl_cache *link_cache; struct rtnl_tc_ops *ops; struct nlattr *tb[TCA_MAX + 1]; char kind[TCKINDSIZ]; struct tcmsg *tm; int err; tc->ce_msgtype = n->nlmsg_type; err = nlmsg_parse(n, sizeof(*tm), tb, TCA_MAX, tc_policy); if (err < 0) return err; if (tb[TCA_KIND] == NULL) return -NLE_MISSING_ATTR; nla_strlcpy(kind, tb[TCA_KIND], sizeof(kind)); rtnl_tc_set_kind(tc, kind); tm = nlmsg_data(n); tc->tc_family = tm->tcm_family; tc->tc_ifindex = tm->tcm_ifindex; tc->tc_handle = tm->tcm_handle; tc->tc_parent = tm->tcm_parent; tc->tc_info = tm->tcm_info; tc->ce_mask |= (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE| TCA_ATTR_PARENT | TCA_ATTR_INFO); if (tb[TCA_OPTIONS]) { tc->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]); if (!tc->tc_opts) return -NLE_NOMEM; tc->ce_mask |= TCA_ATTR_OPTS; } if (tb[TCA_STATS2]) { struct nlattr *tbs[TCA_STATS_MAX + 1]; err = nla_parse_nested(tbs, TCA_STATS_MAX, tb[TCA_STATS2], tc_stats2_policy); if (err < 0) return err; if (tbs[TCA_STATS_BASIC]) { struct gnet_stats_basic *bs; bs = nla_data(tbs[TCA_STATS_BASIC]); tc->tc_stats[RTNL_TC_BYTES] = bs->bytes; tc->tc_stats[RTNL_TC_PACKETS] = bs->packets; } if (tbs[TCA_STATS_RATE_EST]) { struct gnet_stats_rate_est *re; re = nla_data(tbs[TCA_STATS_RATE_EST]); tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps; tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps; } if (tbs[TCA_STATS_QUEUE]) { struct gnet_stats_queue *q; q = nla_data(tbs[TCA_STATS_QUEUE]); tc->tc_stats[RTNL_TC_QLEN] = q->qlen; tc->tc_stats[RTNL_TC_BACKLOG] = q->backlog; tc->tc_stats[RTNL_TC_DROPS] = q->drops; tc->tc_stats[RTNL_TC_REQUEUES] = q->requeues; tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits; } tc->ce_mask |= TCA_ATTR_STATS; if (tbs[TCA_STATS_APP]) { tc->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]); if (tc->tc_xstats == NULL) return -NLE_NOMEM; tc->ce_mask |= TCA_ATTR_XSTATS; } else goto compat_xstats; } else { if (tb[TCA_STATS]) { struct tc_stats *st = nla_data(tb[TCA_STATS]); tc->tc_stats[RTNL_TC_BYTES] = st->bytes; tc->tc_stats[RTNL_TC_PACKETS] = st->packets; tc->tc_stats[RTNL_TC_RATE_BPS] = st->bps; tc->tc_stats[RTNL_TC_RATE_PPS] = st->pps; tc->tc_stats[RTNL_TC_QLEN] = st->qlen; tc->tc_stats[RTNL_TC_BACKLOG] = st->backlog; tc->tc_stats[RTNL_TC_DROPS] = st->drops; tc->tc_stats[RTNL_TC_OVERLIMITS]= st->overlimits; tc->ce_mask |= TCA_ATTR_STATS; } compat_xstats: if (tb[TCA_XSTATS]) { tc->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]); if (tc->tc_xstats == NULL) return -NLE_NOMEM; tc->ce_mask |= TCA_ATTR_XSTATS; } } ops = rtnl_tc_get_ops(tc); if (ops && ops->to_msg_parser) { void *data = rtnl_tc_data(tc); if (!data) return -NLE_NOMEM; err = ops->to_msg_parser(tc, data); if (err < 0) return err; } if ((link_cache = __nl_cache_mngt_require("route/link"))) { struct rtnl_link *link; if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) { rtnl_tc_set_link(tc, link); /* rtnl_tc_set_link incs refcnt */ rtnl_link_put(link); } } return 0; }
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; }