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; }
/** * Allocate link object of type veth * * @return Allocated link object or NULL. */ struct rtnl_link *rtnl_link_veth_alloc(void) { struct rtnl_link *link, *peer; int err; if (!(link = rtnl_link_alloc())) return NULL; if (!(peer = rtnl_link_alloc())) { rtnl_link_put(link); return NULL; } if ((err = rtnl_link_set_type(link, "veth")) < 0) { rtnl_link_put(peer); rtnl_link_put(link); return NULL; } if ((err = rtnl_link_set_type(peer, "veth")) < 0) { rtnl_link_put(peer); rtnl_link_put(link); return NULL; } link->l_info = peer; peer->l_info = link; return link; }
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 read_counters(const char *iface, struct sample *stats) { struct rtnl_link *link; assert(nl_sock); pthread_mutex_lock(&nl_sock_mutex); /* iface index zero means use the iface name */ if (rtnl_link_get_kernel(nl_sock, 0, iface, &link) < 0) { syslog(LOG_ERR, "unknown interface/link name: %s\n", iface); pthread_mutex_unlock(&nl_sock_mutex); return -1; } /* read and return counter */ stats->rx_bytes = rtnl_link_get_stat(link, RTNL_LINK_RX_BYTES); stats->tx_bytes = rtnl_link_get_stat(link, RTNL_LINK_TX_BYTES); stats->rx_packets = rtnl_link_get_stat(link, RTNL_LINK_RX_PACKETS); stats->rx_packets += rtnl_link_get_stat(link, RTNL_LINK_RX_COMPRESSED); stats->tx_packets = rtnl_link_get_stat(link, RTNL_LINK_TX_PACKETS); stats->tx_packets += rtnl_link_get_stat(link, RTNL_LINK_TX_COMPRESSED); rtnl_link_put(link); pthread_mutex_unlock(&nl_sock_mutex); return 0; }
/** * Create a new kernel bonding device * @arg sock netlink socket * @arg name name of bonding device or NULL * @arg opts bonding options (currently unused) * * Creates a new bonding device in the kernel. If no name is * provided, the kernel will automatically pick a name of the * form "type%d" (e.g. bond0, vlan1, etc.) * * The \a opts argument is currently unused. In the future, it * may be used to carry additional bonding options to be set * when creating the bonding device. * * @note When letting the kernel assign a name, it will become * difficult to retrieve the interface afterwards because * you have to guess the name the kernel has chosen. It is * therefore not recommended to not provide a device name. * * @see rtnl_link_bond_enslave() * @see rtnl_link_bond_release() * * @return 0 on success or a negative error code */ int rtnl_link_bond_add(struct nl_sock *sock, const char *name, struct rtnl_link *opts) { struct rtnl_link *link; int err; if (!(link = rtnl_link_alloc())) return -NLE_NOMEM; if (!name) { if (opts) name = rtnl_link_get_name(opts); if (!name) return -NLE_MISSING_ATTR; } if ((err = rtnl_link_set_type(link, "bond")) < 0) goto errout; rtnl_link_set_name(link, name); err = rtnl_link_add(sock, link, NLM_F_CREATE); errout: rtnl_link_put(link); return err; }
int main(int argc, char *argv[]) { struct rtnl_link *link; 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; } link = rtnl_link_alloc(); rtnl_link_set_name(link, "my_bond"); if ((err = rtnl_link_delete(sk, link)) < 0) { nl_perror(err, "Unable to delete link"); return err; } rtnl_link_put(link); nl_close(sk); return 0; }
TError TNlLink::AddVeth(const std::string &name, const std::string &hw, int mtu, int nsFd) { struct rtnl_link *veth, *peer; int ret; peer = rtnl_link_veth_alloc(); if (!peer) return TError(EError::Unknown, "Unable to allocate veth"); rtnl_link_set_name(peer, rtnl_link_get_name(Link)); veth = rtnl_link_veth_get_peer(peer); rtnl_link_set_name(veth, name.c_str()); if (nsFd >= 0) rtnl_link_set_ns_fd(veth, nsFd); if (mtu > 0) { rtnl_link_set_mtu(peer, mtu); rtnl_link_set_mtu(veth, mtu); } if (!hw.empty()) { TNlAddr addr; TError error = addr.Parse(AF_LLC, hw.c_str()); if (error) return error; rtnl_link_set_addr(veth, addr.Addr); } rtnl_link_set_flags(peer, IFF_UP); Dump("add", veth); rtnl_link_put(veth); Dump("add", peer); ret = rtnl_link_add(GetSock(), peer, NLM_F_CREATE | NLM_F_EXCL); if (ret < 0) { rtnl_link_put(peer); return Error(ret, "Cannot add veth"); } rtnl_link_put(peer); return Load(); }
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; }
/* * Create a bridge interface. Returns 0 if successful, libnl error if not. */ static int create_bridge_link(struct nl_sock *sk, const char *name) { struct rtnl_link *l_bridge; int err; l_bridge = rtnl_link_bridge_alloc(); assert(l_bridge); rtnl_link_set_name(l_bridge, name); err = rtnl_link_add(sk, l_bridge, NLM_F_CREATE); if (err < 0) { rtnl_link_put(l_bridge); return err; } rtnl_link_put(l_bridge); return 0; }
int create_bridge(struct nl_sock *sk, struct nl_cache *link_cache, const char *name) { struct rtnl_link *link; int err; link = rtnl_link_alloc(); if ((err = rtnl_link_set_type(link, "bridge")) < 0) { rtnl_link_put(link); return err; } rtnl_link_set_name(link, name); if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { return err; } rtnl_link_put(link); return 0; }
/* 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; }
static void _j4status_nl_cache_change(struct nl_cache *cache, struct nl_object *object, int something, void *user_data) { J4statusPluginContext *self = user_data; J4statusNlSection *section; if ( cache == self->link_cache ) { struct rtnl_link *link = nl_object_priv(object); section = g_hash_table_lookup(self->sections, GINT_TO_POINTER(rtnl_link_get_ifindex(link))); if ( section == NULL ) return; g_debug("Link cache update: %p = %s", object, rtnl_link_get_ifalias(link)); if ( section->link != link ) { nl_object_get(object); rtnl_link_put(section->link); section->link = link; } } else if ( cache == self->addr_cache ) { struct rtnl_addr *addr = nl_object_priv(object); section = g_hash_table_lookup(self->sections, GINT_TO_POINTER(rtnl_addr_get_ifindex(addr))); if ( section == NULL ) return; g_debug("Addr cache update: %p = %d", object, rtnl_addr_get_ifindex(addr)); GList **list; switch ( rtnl_addr_get_family(addr) ) { case AF_INET: list = §ion->ipv4_addresses; break; case AF_INET6: list = §ion->ipv6_addresses; break; default: /* Not supported */ return; } if ( g_list_find_custom(*list, addr,_j4status_nl_address_compare) != NULL ) /* Already got it */ return; nl_object_get(object); *list = g_list_prepend(*list, addr); } else g_assert_not_reached(); _j4status_nl_section_update(section); }
static void iface_mon_handler2(struct nl_object *obj, void *arg) { struct rtnl_link *filter; struct rtnl_link *link_obj; int flags, up; char *ifname; iface_mon_cb cb = (iface_mon_cb)arg; filter = rtnl_link_alloc(); if (!filter) { fprintf(stderr, "error allocating filter\n"); return; } 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); ifname = rtnl_link_get_name(link_obj); /* * You can't bind a PF_PACKET socket to an interface that's not * up, so an interface going down is an "interface should be * removed" indication. * * XXX - what indication, if any, do we get if the interface * *completely goes away*? * * XXX - can we get events if an interface's link-layer or * network addresses change? */ up = (flags & IFF_UP) ? 1 : 0; cb(ifname, up); rtnl_link_put(filter); return; }
/** * Set interface index of traffic control object * @arg tc traffic control object * @arg ifindex interface index. * * Sets the interface index of a traffic control object. The interface * index defines the network device which this tc object is attached to. * This function will overwrite any network device assigned with previous * calls to rtnl_tc_set_ifindex() or rtnl_tc_set_link(). */ void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex) { /* Obsolete possible old link reference */ rtnl_link_put(tc->tc_link); tc->tc_link = NULL; tc->ce_mask &= ~TCA_ATTR_LINK; tc->tc_ifindex = ifindex; tc->ce_mask |= TCA_ATTR_IFINDEX; }
int main(int argc, char *argv[]) { struct nl_cache *link_cache; struct rtnl_link *link, *link2; struct nl_sock *sk; uint32_t tb_id; int err; sk = nl_socket_alloc(); if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { nl_perror(err, "Unable to connect socket"); return err; } if (!(link = rtnl_link_vrf_alloc())) { fprintf(stderr, "Unable to allocate link"); return -1; } rtnl_link_set_name(link, "vrf-red"); if ((err = rtnl_link_vrf_set_tableid(link, 10)) < 0) { nl_perror(err, "Unable to set VRF table id"); return err; } if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { nl_perror(err, "Unable to add link"); return err; } if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) { nl_perror(err, "Unable to allocate cache"); return err; } if (!(link2 = rtnl_link_get_by_name(link_cache, "vrf-red"))) { fprintf(stderr, "Unable to lookup vrf-red"); return -1; } if ((err = rtnl_link_vrf_get_tableid(link2, &tb_id)) < 0) { nl_perror(err, "Unable to get VRF table id"); return err; } if (tb_id != 10) { fprintf(stderr, "Mismatch with VRF table id\n"); } rtnl_link_put(link); nl_close(sk); return 0; }
/** * @ingroup cli * @defgroup cli_tc Traffic Control * @{ */ void nl_cli_tc_parse_dev(struct rtnl_tc *tc, struct nl_cache *link_cache, char *name) { struct rtnl_link *link; link = rtnl_link_get_by_name(link_cache, name); if (!link) nl_cli_fatal(ENOENT, "Link \"%s\" does not exist.", name); rtnl_tc_set_link(tc, link); rtnl_link_put(link); }
/** * Set link of traffic control object * @arg tc traffic control object * @arg link link object * * Sets the link of a traffic control object. This function serves * the same purpose as rtnl_tc_set_ifindex() but due to the continued * allowed access to the link object it gives it the possibility to * retrieve sane default values for the the MTU and the linktype. * Always prefer this function over rtnl_tc_set_ifindex() if you can * spare to have an additional link object around. */ void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link) { rtnl_link_put(tc->tc_link); if (!link) return; nl_object_get(OBJ_CAST(link)); tc->tc_link = link; tc->tc_ifindex = link->l_index; tc->ce_mask |= TCA_ATTR_LINK | TCA_ATTR_IFINDEX; }
int main(int argc, char *argv[]) { struct nl_cache *link_cache; struct rtnl_link *link; struct in_addr addr; struct nl_sock *sk; int err, if_index; sk = nl_socket_alloc(); if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { nl_perror(err, "Unable to connect socket"); return err; } err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); if ( err < 0) { nl_perror(err, "Unable to allocate cache"); return err; } if_index = rtnl_link_name2i(link_cache, "eno16777736"); if (!if_index) { fprintf(stderr, "Unable to lookup eno16777736"); return -1; } link = rtnl_link_sit_alloc(); if(!link) { nl_perror(err, "Unable to allocate link"); return -1; } rtnl_link_set_name(link, "sit-tun"); rtnl_link_sit_set_link(link, if_index); inet_pton(AF_INET, "192.168.254.12", &addr.s_addr); rtnl_link_sit_set_local(link, addr.s_addr); inet_pton(AF_INET, "192.168.254.13", &addr.s_addr); rtnl_link_sit_set_remote(link, addr.s_addr); rtnl_link_sit_set_ttl(link, 64); err = rtnl_link_add(sk, link, NLM_F_CREATE); if (err < 0) { nl_perror(err, "Unable to add link"); return err; } rtnl_link_put(link); nl_close(sk); return 0; }
TError TNlLink::Load() { struct rtnl_link *link; int ret; ret = rtnl_link_get_kernel(GetSock(), rtnl_link_get_ifindex(Link), rtnl_link_get_name(Link), &link); if (ret) return Error(ret, "Cannot load link"); rtnl_link_put(Link); Link = link; return TError::Success(); }
int main(int argc, char *argv[]) { struct nl_cache *link_cache; struct rtnl_link *link; struct in6_addr addr; struct nl_sock *sk; int err, if_index; sk = nl_socket_alloc(); if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { nl_perror(err, "Unable to connect socket"); return err; } err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); if ( err < 0) { nl_perror(err, "Unable to allocate cache"); return err; } if_index = rtnl_link_name2i(link_cache, "ens33"); if (!if_index) { fprintf(stderr, "Unable to lookup ens33"); return -1; } link = rtnl_link_ip6_tnl_alloc(); if(!link) { nl_perror(err, "Unable to allocate link"); return -1; } rtnl_link_set_name(link, "ip6tnl-tun"); rtnl_link_ip6_tnl_set_link(link, if_index); inet_pton(AF_INET6, "2607:f0d0:1002:51::4", &addr); rtnl_link_ip6_tnl_set_local(link, &addr); inet_pton(AF_INET6, "2607:f0d0:1002:52::5", &addr); rtnl_link_ip6_tnl_set_remote(link, &addr); err = rtnl_link_add(sk, link, NLM_F_CREATE); if (err < 0) { nl_perror(err, "Unable to add link"); return err; } rtnl_link_put(link); nl_close(sk); return 0; }
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 void _j4status_nl_section_free(gpointer data) { J4statusNlSection *self = data; j4status_section_free(self->section); _j4status_nl_section_free_addresses(self); rtnl_link_put(self->link); g_free(self); }
TError TNlLink::Enslave(const std::string &name) { struct rtnl_link *link; int ret; link = rtnl_link_alloc(); rtnl_link_set_name(link, name.c_str()); rtnl_link_set_master(link, GetIndex()); rtnl_link_set_flags(link, IFF_UP); Dump("mod", link); ret = rtnl_link_change(GetSock(), link, link, 0); if (ret < 0) { Dump("del", link); (void)rtnl_link_delete(GetSock(), link); rtnl_link_put(link); return Error(ret, "Cannot enslave interface " + name); } rtnl_link_put(link); return TError::Success(); }
TError TNlLink::ChangeNs(const std::string &newName, int nsFd) { auto change = rtnl_link_alloc(); if (!change) return Error(-NLE_NOMEM, "Cannot allocate link"); rtnl_link_set_name(change, newName.c_str()); rtnl_link_set_ns_fd(change, nsFd); Dump("change ns", change); int ret = rtnl_link_change(GetSock(), Link, change, 0); rtnl_link_put(change); if (ret < 0) return Error(ret, "Cannot change ns"); return TError::Success(); }
TError TNlLink::Up() { Dump("up"); auto change = rtnl_link_alloc(); if (!change) return Error(-NLE_NOMEM, "Cannot allocate link"); rtnl_link_set_flags(change, IFF_UP); int ret = rtnl_link_change(GetSock(), Link, change, 0); rtnl_link_put(change); if (ret < 0) return Error(ret, "Cannot set up"); return TError::Success(); }
/** * 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; }
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; }
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 vlan_rem(const char *if_name) { int ret = -1; struct nl_sock *handle = NULL; struct nl_cache *cache = NULL; struct rtnl_link *rlink = NULL; wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name); handle = nl_socket_alloc(); if (!handle) { wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket"); goto vlan_rem_error; } if (nl_connect(handle, NETLINK_ROUTE) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink"); goto vlan_rem_error; } if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) { cache = NULL; wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache"); goto vlan_rem_error; } if (!(rlink = rtnl_link_get_by_name(cache, if_name))) { /* link does not exist */ wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists", if_name); goto vlan_rem_error; } if (rtnl_link_delete(handle, rlink) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s", if_name); goto vlan_rem_error; } ret = 0; vlan_rem_error: if (rlink) rtnl_link_put(rlink); if (cache) nl_cache_free(cache); if (handle) nl_socket_free(handle); return ret; }
/** * Create a new kernel veth device * @arg sock netlink socket * @arg name name of the veth device or NULL * @arg peer_name name of its peer or NULL * @arg pid pid of the process in the new netns * * Creates a new veth device pair in the kernel and move the peer * to the network namespace where the process is. If no name is * provided, the kernel will automatically pick a name of the * form "veth%d" (e.g. veth0, veth1, etc.) * * @return 0 on success or a negative error code */ int rtnl_link_veth_add(struct nl_sock *sock, const char *name, const char *peer_name, pid_t pid) { struct rtnl_link *link, *peer; int err = -NLE_NOMEM; if (!(link = rtnl_link_veth_alloc())) return -NLE_NOMEM; peer = rtnl_link_veth_get_peer(link); if (name && peer_name) { rtnl_link_set_name(link, name); rtnl_link_set_name(peer, peer_name); } rtnl_link_set_ns_pid(peer, pid); err = rtnl_link_add(sock, link, NLM_F_CREATE); rtnl_link_put(peer); rtnl_link_put(link); return err; }