/** * 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_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; }
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; }
/** * 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; }
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(); }
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(); }
/** * Allocate link object of type VLAN * * @return Allocated link object or NULL. */ struct rtnl_link *rtnl_link_vlan_alloc(void) { struct rtnl_link *link; int err; if (!(link = rtnl_link_alloc())) return NULL; if ((err = rtnl_link_set_type(link, "vlan")) < 0) { rtnl_link_put(link); return NULL; } return link; }
int main(int argc, char *argv[]) { struct nl_handle *nlh; struct nl_cache *link_cache; struct rtnl_link *link; struct nl_dump_params params = { .dp_fd = stdout, .dp_type = NL_DUMP_BRIEF }; int err = 1; if (nltool_init(argc, argv) < 0) return -1; if (argc < 2 || !strcmp(argv[1], "-h")) print_usage(); nlh = nltool_alloc_handle(); if (!nlh) return -1; link = rtnl_link_alloc(); if (!link) goto errout; if (nltool_connect(nlh, NETLINK_ROUTE) < 0) goto errout_put; link_cache = nltool_alloc_link_cache(nlh); if (!link_cache) goto errout_put; params.dp_type = nltool_parse_dumptype(argv[1]); if (params.dp_type < 0) goto errout_put; get_filter(link, argc, argv, 2, link_cache); nl_cache_dump_filter(link_cache, ¶ms, (struct nl_object *) link); nl_cache_free(link_cache); err = 0; errout_put: rtnl_link_put(link); errout: nl_close(nlh); 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; }
static int veth_clone(struct rtnl_link *dst, struct rtnl_link *src) { struct rtnl_link *dst_peer , *src_peer = src->l_info; int err; dst_peer = dst->l_info = rtnl_link_alloc(); if (!dst_peer || !src_peer) return -NLE_NOMEM; if ((err = rtnl_link_set_type(dst, "veth")) < 0) { rtnl_link_put(dst_peer); return err; } memcpy(dst_peer, src_peer, sizeof(struct rtnl_link)); return 0; }
void dabbad_interface_statistics_get(Dabba__DabbaService_Service * service, const Dabba__InterfaceIdList * id_list, Dabba__InterfaceStatisticsList_Closure closure, void *closure_data) { Dabba__InterfaceStatisticsList statistics_list = DABBA__INTERFACE_STATISTICS_LIST__INIT; Dabba__InterfaceStatisticsList *statistics_listp = NULL; struct nl_sock *sock = NULL; struct nl_cache *cache; struct rtnl_link *link; size_t a; assert(service); assert(closure_data); cache = link_cache_alloc(&sock); link = rtnl_link_alloc(); if (!link || !cache) goto out; if (id_list->n_list) { for (a = 0; a < id_list->n_list; a++) { rtnl_link_set_name(link, id_list->list[a]->name); nl_cache_foreach_filter(cache, OBJ_CAST(link), __interface_statistics_get, &statistics_list); } } else nl_cache_foreach(cache, __interface_statistics_get, &statistics_list); statistics_listp = &statistics_list; out: closure(statistics_listp, closure_data); for (a = 0; a < statistics_list.n_list; a++) { free(statistics_list.list[a]->status); free(statistics_list.list[a]->id); free(statistics_list.list[a]); } free(statistics_list.list); link_destroy(link); link_cache_destroy(sock, cache); }
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; }
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 the MTU on the specified device. */ int iface_set_interface_mtu(char *ifname, int mtu) { int ret = 0; struct nl_handle *handle = NULL; struct nl_cache *cache = NULL; struct rtnl_link *link = NULL; struct rtnl_link *request = NULL; if (ifname == NULL) { return -1; } if (mtu <= 0) { return -2; } if ((cache = _iface_get_link_cache(&handle)) == NULL) { return -3; } if ((link = rtnl_link_get_by_name(cache, ifname)) == NULL) { ret = -4; goto ifacemtu_error1; } request = rtnl_link_alloc(); rtnl_link_set_mtu(request, mtu); if (rtnl_link_change(handle, link, request, 0)) { ret = -5; goto ifacemtu_error2; } ifacemtu_error2: rtnl_link_put(link); ifacemtu_error1: nl_close(handle); nl_handle_destroy(handle); return ret; }
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); }
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(); }
/** * 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; }
int main(int argc, char *argv[]) { char *unikernel; enum { QEMU, KVM, UKVM, UNIX } hypervisor; if (argc < 3) { fprintf(stderr, "usage: runner HYPERVISOR UNIKERNEL [ ARGS... ]\n"); fprintf(stderr, "HYPERVISOR: qemu | kvm | ukvm | unix\n"); return 1; } if (strcmp(argv[1], "qemu") == 0) hypervisor = QEMU; else if (strcmp(argv[1], "kvm") == 0) hypervisor = KVM; else if (strcmp(argv[1], "ukvm") == 0) hypervisor = UKVM; else if (strcmp(argv[1], "unix") == 0) hypervisor = UNIX; else { warnx("error: Invalid hypervisor: %s", argv[1]); return 1; } unikernel = argv[2]; /* * Remaining arguments are to be passed on to the unikernel. */ argv += 3; argc -= 3; /* * Check we have CAP_NET_ADMIN. */ if (capng_get_caps_process() != 0) { warnx("error: capng_get_caps_process() failed"); return 1; } if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_ADMIN)) { warnx("error: CAP_NET_ADMIN is required"); return 1; } /* * Connect to netlink, load link cache from kernel. */ struct nl_sock *sk; struct nl_cache *link_cache; int err; sk = nl_socket_alloc(); assert(sk); err = nl_connect(sk, NETLINK_ROUTE); if (err < 0) { warnx("nl_connect() failed: %s", nl_geterror(err)); return 1; } err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); if (err < 0) { warnx("rtnl_link_alloc_cache() failed: %s", nl_geterror(err)); return 1; } /* * Retrieve container network configuration -- IP address and * default gateway. */ struct rtnl_link *l_veth; l_veth = rtnl_link_get_by_name(link_cache, VETH_LINK_NAME); if (l_veth == NULL) { warnx("error: Could not get link information for %s", VETH_LINK_NAME); return 1; } struct nl_addr *veth_addr; err = get_link_inet_addr(sk, l_veth, &veth_addr); if (err) { warnx("error: Unable to determine IP address of %s", VETH_LINK_NAME); return 1; } struct nl_addr *gw_addr; err = get_default_gw_inet_addr(sk, &gw_addr); if (err) { warnx("error: get_deGfault_gw_inet_addr() failed"); return 1; } if (gw_addr == NULL) { warnx("error: No default gateway found. This is currently " "not supported"); return 1; } /* * Create bridge and tap interface, enslave veth and tap interfaces to * bridge. */ err = create_bridge_link(sk, BRIDGE_LINK_NAME); if (err < 0) { warnx("create_bridge_link(%s) failed: %s", BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } int tap_fd; if (hypervisor == UKVM) err = create_tap_link(TAP_LINK_NAME, &tap_fd); else err = create_tap_link(TAP_LINK_NAME, NULL); if (err != 0) { warnx("create_tap_link(%s) failed: %s", TAP_LINK_NAME, strerror(err)); return 1; } /* Refill link cache with newly-created interfaces */ nl_cache_refill(sk, link_cache); struct rtnl_link *l_bridge; l_bridge = rtnl_link_get_by_name(link_cache, BRIDGE_LINK_NAME); if (l_bridge == NULL) { warnx("error: Could not get link information for %s", BRIDGE_LINK_NAME); return 1; } struct rtnl_link *l_tap; l_tap = rtnl_link_get_by_name(link_cache, TAP_LINK_NAME); if (l_tap == NULL) { warnx("error: Could not get link information for %s", TAP_LINK_NAME); return 1; } err = rtnl_link_enslave(sk, l_bridge, l_veth); if (err < 0) { warnx("error: Unable to enslave %s to %s: %s", VETH_LINK_NAME, BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } err = rtnl_link_enslave(sk, l_bridge, l_tap); if (err < 0) { warnx("error: Unable to enslave %s to %s: %s", TAP_LINK_NAME, BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } /* * Flush all IPv4 addresses from the veth interface. This is now safe * as we are good to commit and have retrieved the existing configuration. */ struct rtnl_addr *flush_addr; flush_addr = rtnl_addr_alloc(); assert(flush_addr); rtnl_addr_set_ifindex(flush_addr, rtnl_link_get_ifindex(l_veth)); rtnl_addr_set_family(flush_addr, AF_INET); rtnl_addr_set_local(flush_addr, veth_addr); err = rtnl_addr_delete(sk, flush_addr, 0); if (err < 0) { warnx("error: Could not flush addresses on %s: %s", VETH_LINK_NAME, nl_geterror(err)); return 1; } rtnl_addr_put(flush_addr); /* * Bring up the tap and bridge interfaces. */ struct rtnl_link *l_up; l_up = rtnl_link_alloc(); assert(l_up); /* You'd think set_operstate was the thing to do here. It's not. */ rtnl_link_set_flags(l_up, IFF_UP); err = rtnl_link_change(sk, l_tap, l_up, 0); if (err < 0) { warnx("error: rtnl_link_change(%s, UP) failed: %s", TAP_LINK_NAME, nl_geterror(err)); return 1; } err = rtnl_link_change(sk, l_bridge, l_up, 0); if (err < 0) { warnx("error: rtnl_link_change(%s, UP) failed: %s", BRIDGE_LINK_NAME, nl_geterror(err)); return 1; } rtnl_link_put(l_up); /* * Collect network configuration data. */ char ip[AF_INET_BUFSIZE]; if (inet_ntop(AF_INET, nl_addr_get_binary_addr(veth_addr), ip, sizeof ip) == NULL) { perror("inet_ntop()"); return 1; } char uarg_ip[AF_INET_BUFSIZE]; unsigned int prefixlen = nl_addr_get_prefixlen(veth_addr); snprintf(uarg_ip, sizeof uarg_ip, "%s/%u", ip, prefixlen); char uarg_gw[AF_INET_BUFSIZE]; if (inet_ntop(AF_INET, nl_addr_get_binary_addr(gw_addr), uarg_gw, sizeof uarg_gw) == NULL) { perror("inet_ntop()"); return 1; } /* * Build unikernel and hypervisor arguments. */ ptrvec* uargpv = pvnew(); char *uarg_buf; /* * QEMU/KVM: * /usr/bin/qemu-system-x86_64 <qemu args> -kernel <unikernel> -append "<unikernel args>" */ if (hypervisor == QEMU || hypervisor == KVM) { pvadd(uargpv, "/usr/bin/qemu-system-x86_64"); pvadd(uargpv, "-nodefaults"); pvadd(uargpv, "-no-acpi"); pvadd(uargpv, "-display"); pvadd(uargpv, "none"); pvadd(uargpv, "-serial"); pvadd(uargpv, "stdio"); pvadd(uargpv, "-m"); pvadd(uargpv, "512"); if (hypervisor == KVM) { pvadd(uargpv, "-enable-kvm"); pvadd(uargpv, "-cpu"); pvadd(uargpv, "host"); } else { /* * Required for AESNI use in Mirage. */ pvadd(uargpv, "-cpu"); pvadd(uargpv, "Westmere"); } pvadd(uargpv, "-device"); char *guest_mac = generate_mac(); assert(guest_mac); err = asprintf(&uarg_buf, "virtio-net-pci,netdev=n0,mac=%s", guest_mac); assert(err != -1); pvadd(uargpv, uarg_buf); pvadd(uargpv, "-netdev"); err = asprintf(&uarg_buf, "tap,id=n0,ifname=%s,script=no,downscript=no", TAP_LINK_NAME); assert(err != -1); pvadd(uargpv, uarg_buf); pvadd(uargpv, "-kernel"); pvadd(uargpv, unikernel); pvadd(uargpv, "-append"); /* * TODO: Replace any occurences of ',' with ',,' in -append, because * QEMU arguments are insane. */ char cmdline[1024]; char *cmdline_p = cmdline; size_t cmdline_free = sizeof cmdline; for (; *argv; argc--, argv++) { size_t alen = snprintf(cmdline_p, cmdline_free, "%s%s", *argv, (argc > 1) ? " " : ""); if (alen >= cmdline_free) { warnx("error: Command line too long"); return 1; } cmdline_free -= alen; cmdline_p += alen; } size_t alen = snprintf(cmdline_p, cmdline_free, "--ipv4=%s --ipv4-gateway=%s", uarg_ip, uarg_gw); if (alen >= cmdline_free) { warnx("error: Command line too long"); return 1; } pvadd(uargpv, cmdline); } /* * UKVM: * /unikernel/ukvm <ukvm args> <unikernel> -- <unikernel args> */ else if (hypervisor == UKVM) { pvadd(uargpv, "/unikernel/ukvm"); err = asprintf(&uarg_buf, "--net=@%d", tap_fd); assert(err != -1); pvadd(uargpv, uarg_buf); pvadd(uargpv, "--"); pvadd(uargpv, unikernel); for (; *argv; argc--, argv++) { pvadd(uargpv, *argv); } err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip); assert(err != -1); pvadd(uargpv, uarg_buf); err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw); assert(err != -1); pvadd(uargpv, uarg_buf); } /* * UNIX: * <unikernel> <unikernel args> */ else if (hypervisor == UNIX) { pvadd(uargpv, unikernel); err = asprintf(&uarg_buf, "--interface=%s", TAP_LINK_NAME); assert(err != -1); pvadd(uargpv, uarg_buf); for (; *argv; argc--, argv++) { pvadd(uargpv, *argv); } err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip); assert(err != -1); pvadd(uargpv, uarg_buf); err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw); assert(err != -1); pvadd(uargpv, uarg_buf); } char **uargv = (char **)pvfinal(uargpv); /* * Done with netlink, free all resources and close socket. */ rtnl_link_put(l_veth); rtnl_link_put(l_bridge); rtnl_link_put(l_tap); nl_addr_put(veth_addr); nl_addr_put(gw_addr); nl_cache_free(link_cache); nl_close(sk); nl_socket_free(sk); /* * Drop all capabilities except CAP_NET_BIND_SERVICE. */ capng_clear(CAPNG_SELECT_BOTH); capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE); if (capng_apply(CAPNG_SELECT_BOTH) != 0) { warnx("error: Could not drop capabilities"); return 1; } /* * Run the unikernel. */ err = execv(uargv[0], uargv); warn("error: execv() of %s failed", uargv[0]); return 1; }
/* * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and * tagged interface 'if_name'. * * returns -1 on error * returns 1 if the interface already exists * returns 0 otherwise */ int vlan_add(const char *if_name, int vid, const char *vlan_if_name) { int ret = -1; struct nl_sock *handle = NULL; struct nl_cache *cache = NULL; struct rtnl_link *rlink = NULL; int if_idx = 0; wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, " "vlan_if_name=%s)", if_name, vid, vlan_if_name); if ((os_strlen(if_name) + 1) > IFNAMSIZ) { wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", if_name); return -1; } if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) { wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", vlan_if_name); return -1; } handle = nl_socket_alloc(); if (!handle) { wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket"); goto vlan_add_error; } if (nl_connect(handle, NETLINK_ROUTE) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink"); goto vlan_add_error; } if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) { cache = NULL; wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache"); goto vlan_add_error; } if (!(if_idx = rtnl_link_name2i(cache, if_name))) { /* link does not exist */ wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist", if_name); goto vlan_add_error; } if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) { /* link does exist */ rtnl_link_put(rlink); rlink = NULL; wpa_printf(MSG_ERROR, "VLAN: interface %s already exists", vlan_if_name); ret = 1; goto vlan_add_error; } rlink = rtnl_link_alloc(); if (!rlink) { wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link"); goto vlan_add_error; } if (rtnl_link_set_type(rlink, "vlan") < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to set link type"); goto vlan_add_error; } rtnl_link_set_link(rlink, if_idx); rtnl_link_set_name(rlink, vlan_if_name); if (rtnl_link_vlan_set_id(rlink, vid) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id"); goto vlan_add_error; } if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for " "vlan %d on %s (%d)", vlan_if_name, vid, if_name, if_idx); goto vlan_add_error; } ret = 0; vlan_add_error: if (rlink) rtnl_link_put(rlink); if (cache) nl_cache_free(cache); if (handle) nl_socket_free(handle); return ret; }
int configure_loopback_interface() { struct nl_sock *sock = NULL; struct rtnl_addr *addr = NULL; struct nl_addr* lo_addr = NULL; struct nl_cache *cache = NULL; struct rtnl_link *link = NULL, *link2 = NULL; int err, nlflags = NLM_F_CREATE, ret = 0; if(!want_cap(CAP_NET_ADMIN)) { errWarn("Cannot set the CAP_NET_ADMIN effective capability"); return -1; } sock = nl_socket_alloc(); if(sock == NULL) { errWarn("nl_socket_alloc"); return -1; } if((err = nl_connect(sock, NETLINK_ROUTE)) < 0) { fprintf(stderr, "Unable to connect to netlink: %s\n", nl_geterror(err)); ret = -1; goto out2; } if(rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache) < 0) { ret = -1; goto out; } link = rtnl_link_get_by_name(cache, "lo"); if (link == NULL) { ret = -1; goto out; } addr = rtnl_addr_alloc(); if(addr == NULL) { ret = -1; goto out; } rtnl_addr_set_link(addr, link); rtnl_addr_set_family(addr, AF_INET); if((err = nl_addr_parse("127.0.0.1/8", AF_INET, &lo_addr)) < 0) { fprintf(stderr, "Unable to parse address: %s\n", nl_geterror(err)); ret = -1; goto out; } if((err = rtnl_addr_set_local(addr, lo_addr)) < 0) { fprintf(stderr, "Unable to set address: %s\n", nl_geterror(err)); ret = -1; goto out; } nl_addr_put(lo_addr); lo_addr = NULL; if ((err = rtnl_addr_add(sock, addr, nlflags)) < 0) { fprintf(stderr, "Unable to add address: %s\n", nl_geterror(err)); ret = -1; goto out; } rtnl_addr_set_family(addr, AF_INET6); if((err = nl_addr_parse("::1/128", AF_INET6, &lo_addr)) < 0) { fprintf(stderr, "Unable to parse address: %s\n", nl_geterror(err)); ret = -1; goto out; } if((err = rtnl_addr_set_local(addr, lo_addr)) < 0) { fprintf(stderr, "Unable to set address: %s\n", nl_geterror(err)); ret = -1; goto out; } nl_addr_put(lo_addr); lo_addr = NULL; if ((err = rtnl_addr_add(sock, addr, nlflags)) < 0) { fprintf(stderr, "Unable to add address: %s\n", nl_geterror(err)); ret = -1; goto out; } link2 = rtnl_link_alloc(); if(link2 == NULL) { ret = -1; goto out; } rtnl_link_set_flags(link2, IFF_UP); if((err = rtnl_link_change(sock, link, link2, 0)) < 0) { fprintf(stderr, "Unable to change link: %s\n", nl_geterror(err)); ret = -1; goto out; } out: if(lo_addr!=NULL) nl_addr_put(lo_addr); if(link2!=NULL) rtnl_link_put(link2); if(link!=NULL) rtnl_link_put(link); if(cache!=NULL) nl_cache_put(cache); if(addr!=NULL) rtnl_addr_put(addr); nl_close(sock); out2: nl_socket_free(sock); drop_caps(); return ret; }
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; }
TNlLink::TNlLink(std::shared_ptr<TNl> sock, const std::string &name) { Nl = sock; Link = rtnl_link_alloc(); PORTO_ASSERT(Link); rtnl_link_set_name(Link, name.c_str()); }