Esempio n. 1
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_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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
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();
}
Esempio n. 6
0
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();
}
Esempio n. 7
0
File: vlan.c Progetto: Domikk/libnl
/**
 * 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, &params, (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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
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);
}
Esempio n. 12
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;
}
Esempio n. 13
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;
}
Esempio n. 14
0
/*
 * 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);
}
Esempio n. 16
0
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();
}
Esempio n. 17
0
/**
 * 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 */
}
Esempio n. 19
0
/**
 * 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;
}
Esempio n. 20
0
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;
}
Esempio n. 21
0
File: vlan_util.c Progetto: imw/hapd
/*
 * 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;
}
Esempio n. 22
0
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;
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
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());
}