Beispiel #1
0
void
ind_ovs_port_init(void)
{
    int nlerr;

    route_cache_sock = nl_socket_alloc();
    if (route_cache_sock == NULL) {
        LOG_ERROR("nl_socket_alloc failed");
        abort();
    }

    if ((nlerr = nl_cache_mngr_alloc(route_cache_sock, NETLINK_ROUTE,
                                     0, &route_cache_mngr)) < 0) {
        LOG_ERROR("nl_cache_mngr_alloc failed: %s", nl_geterror(nlerr));
        abort();
    }

    if ((nlerr = nl_cache_mngr_add(route_cache_mngr, "route/link", link_change_cb, NULL, &link_cache)) < 0) {
        LOG_ERROR("nl_cache_mngr_add failed: %s", nl_geterror(nlerr));
        abort();
    }

    if (ind_soc_socket_register(nl_cache_mngr_get_fd(route_cache_mngr),
                                (ind_soc_socket_ready_callback_f)route_cache_mngr_socket_cb,
                                NULL) < 0) {
        LOG_ERROR("failed to register socket");
        abort();
    }

    netlink_callbacks = nl_cb_alloc(NL_CB_DEFAULT);
    if (netlink_callbacks == NULL) {
        LOG_ERROR("failed to allocate netlink callbacks");
        abort();
    }
}
Beispiel #2
0
/**
 * Print a libnl error message
 * @arg s		error message prefix
 *
 * Prints the error message of the call that failed last.
 *
 * If s is not NULL and *s is not a null byte the argument
 * string is printed, followed by a colon and a blank. Then
 * the error message and a new-line.
 */
void nl_perror(const char *s)
{
	if (s && *s)
		fprintf(stderr, "%s: %s\n", s, nl_geterror());
	else
		fprintf(stderr, "%s\n", nl_geterror());
}
static gboolean
nlh_setup (struct nl_sock *nlh,
           nl_recvmsg_msg_cb_t valid_func,
           gpointer cb_data,
           GError **error)
{
	int err;

	nl_socket_modify_cb (nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, cb_data);

	if (valid_func)
		nl_socket_modify_cb (nlh, NL_CB_VALID, NL_CB_CUSTOM, valid_func, cb_data);

	err = nl_connect (nlh, NETLINK_ROUTE);
	if (err < 0) {
		g_set_error (error, NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT,
		             _("unable to connect to netlink for monitoring link status: %s"),
		             nl_geterror (err));
		return FALSE;
	}

	/* Enable unix socket peer credentials which we use for verifying that the
	 * sender of the message is actually the kernel.
	 */
	if (nl_socket_set_passcred (nlh, 1) < 0) {
		g_set_error (error, NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT,
		             _("unable to enable netlink handle credential passing: %s"),
		             nl_geterror (err));
		return FALSE;
	}

	return TRUE;
}
static gboolean
sync_connection_setup (NMNetlinkMonitor *self, GError **error)
{
	NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND
	struct nl_cache *addr_cache;
#endif
	int err;

	/* Set up the event listener connection */
	priv->nlh_sync = nl_socket_alloc ();
	if (!priv->nlh_sync) {
		g_set_error (error, NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE,
		             _("unable to allocate netlink handle for monitoring link status: %s"),
		             nl_geterror (ENOMEM));
		goto error;
	}

	if (!nlh_setup (priv->nlh_sync, NULL, self, error))
		goto error;

#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND
	/* Work around apparent libnl bug; rtnl_addr requires that all
	 * addresses have the "peer" attribute set in order to be compared
	 * for equality, but this attribute is not normally set. As a
	 * result, most addresses will not compare as equal even to
	 * themselves, busting caching.
	 */
	rtnl_addr_alloc_cache (priv->nlh_sync, &addr_cache);
	g_warn_if_fail (addr_cache != NULL);
	nl_cache_get_ops (addr_cache)->co_obj_ops->oo_id_attrs &= ~0x80;
	nl_cache_free (addr_cache);
#endif

	err = rtnl_link_alloc_cache (priv->nlh_sync, AF_UNSPEC, &priv->link_cache);
	if (err < 0) {
		g_set_error (error, NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE,
		             _("unable to allocate netlink link cache for monitoring link status: %s"),
		             nl_geterror (err));
		goto error;
	}
	nl_cache_mngt_provide (priv->link_cache);

	return TRUE;

error:
	if (priv->link_cache) {
		nl_cache_free (priv->link_cache);
		priv->link_cache = NULL;
	}

	if (priv->nlh_sync) {
		nl_socket_free (priv->nlh_sync);
		priv->nlh_sync = NULL;
	}

	return FALSE;
}
Beispiel #5
0
bool TaskstatsSocket::Open() {
  std::unique_ptr<nl_sock, decltype(&nl_socket_free)> nl(
      nl_socket_alloc(), nl_socket_free);
  if (!nl.get()) {
    LOG(ERROR) << "Failed to allocate netlink socket";
    return false;
  }

  int ret = genl_connect(nl.get());
  if (ret < 0) {
    LOG(ERROR) << nl_geterror(ret) << std::endl << "Unable to open netlink socket (are you root?)";
    return false;
  }

  int family_id = genl_ctrl_resolve(nl.get(), TASKSTATS_GENL_NAME);
  if (family_id < 0) {
    LOG(ERROR) << nl_geterror(family_id) << std::endl << "Unable to determine taskstats family id (does your kernel support taskstats?)";
    return false;
  }

  nl_ = std::move(nl);
  family_id_ = family_id;

  return true;
}
int main(int argc, char *argv[])
{
	struct nl_sock *sock;
	struct nl_msg *msg;
	void *hdr;
	int err;

	sock = nlt_alloc_socket();
	nlt_connect(sock, NETLINK_GENERIC);

	msg = nlmsg_alloc();
	if (msg == NULL)
		fatal(NLE_NOMEM, "Unable to allocate netlink message");

	hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, GENL_ID_CTRL,
			  0, 0, CTRL_CMD_GETFAMILY, 1);
	if (hdr == NULL)
		fatal(ENOMEM, "Unable to write genl header");

	if ((err = nla_put_u32(msg, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL)) < 0)
		fatal(err, "Unable to add attribute: %s", nl_geterror(err));

	if ((err = nl_send_auto_complete(sock, msg)) < 0)
		fatal(err, "Unable to send message: %s", nl_geterror(err));

	if ((err = nl_recvmsgs_default(sock)) < 0)
		fatal(err, "Unable to receive message: %s", nl_geterror(err));

	nlmsg_free(msg);
	nl_close(sock);
	nl_socket_free(sock);

	return 0;
}
Beispiel #7
0
TError TNlCgFilter::Remove(const TNlLink &link) {
    TError error = TError::Success();
    struct rtnl_cls *cls;
    int ret;

    cls = rtnl_cls_alloc();
    if (!cls)
        return TError(EError::Unknown, std::string("Unable to allocate filter object"));

    rtnl_tc_set_ifindex(TC_CAST(cls), link.GetIndex());

    ret = rtnl_tc_set_kind(TC_CAST(cls), FilterType);
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to set filter type: ") + nl_geterror(ret));
        goto free_cls;
    }

    rtnl_cls_set_prio(cls, FilterPrio);
    rtnl_cls_set_protocol(cls, 0);
    rtnl_tc_set_parent(TC_CAST(cls), Parent);

    link.Dump("remove", cls);

    ret = rtnl_cls_delete(link.GetSock(), cls, 0);
    if (ret < 0)
        error = TError(EError::Unknown, std::string("Unable to remove filter: ") + nl_geterror(ret));

free_cls:
    rtnl_cls_put(cls);

    return error;
}
int main(int argc, char *argv[])
{
	struct nl_cache_mngr *mngr;
	struct nl_cache *cache;
	int err, i;

	dp.dp_fd = stdout;

	signal(SIGINT, sigint);

	err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr);
	if (err < 0)
		nl_cli_fatal(err, "Unable to allocate cache manager: %s",
			     nl_geterror(err));

	for (i = 1; i < argc; i++) {
		err = nl_cache_mngr_add(mngr, argv[i], &change_cb, NULL, &cache);
		if (err < 0)
			nl_cli_fatal(err, "Unable to add cache %s: %s",
				     argv[i], nl_geterror(err));
	}

	while (!quit) {
		int err = nl_cache_mngr_poll(mngr, 1000);
		if (err < 0 && err != -NLE_INTR)
			nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err));

		nl_cache_mngr_info(mngr, &dp);
	}

	nl_cache_mngr_free(mngr);

	return 0;
}
Beispiel #9
0
TError TNlHtb::Create(const TNlLink &link, uint32_t defaultClass) {
    TError error = TError::Success();
    int ret;
    struct rtnl_qdisc *qdisc;

    qdisc = rtnl_qdisc_alloc();
    if (!qdisc)
        return TError(EError::Unknown, std::string("Unable to allocate qdisc object"));

    rtnl_tc_set_ifindex(TC_CAST(qdisc), link.GetIndex());
    rtnl_tc_set_parent(TC_CAST(qdisc), Parent);
    rtnl_tc_set_handle(TC_CAST(qdisc), Handle);

    ret = rtnl_tc_set_kind(TC_CAST(qdisc), "htb");
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to set qdisc type: ") + nl_geterror(ret));
        goto free_qdisc;
    }

    rtnl_htb_set_defcls(qdisc, TC_H_MIN(defaultClass));
    rtnl_htb_set_rate2quantum(qdisc, 10);

    link.Dump("add", qdisc);

    ret = rtnl_qdisc_add(link.GetSock(), qdisc, NLM_F_CREATE);
    if (ret < 0)
        error = TError(EError::Unknown, std::string("Unable to add qdisc: ") + nl_geterror(ret));

free_qdisc:
    rtnl_qdisc_put(qdisc);

    return error;
}
int main(int argc, char *argv[])
{
	struct nl_handle *nlh;
	struct rtnl_addr *addr;
	struct nl_addr *local;
	int err = 1;

	if (argc < 3 || !strcmp(argv[1], "-h")) {
		printf("Usage: nl-addr-delete <addr> <ifindex>\n");
		goto errout;
	}

	if (nltool_init(argc, argv) < 0)
		goto errout;

	nlh = nltool_alloc_handle();
	if (!nlh)
		goto errout;

	addr = rtnl_addr_alloc();
	if (!addr)
		goto errout_free_handle;

	if (nltool_connect(nlh, NETLINK_ROUTE) < 0)
		goto errout_free_addr;

	local = nltool_addr_parse(argv[1]);
	if (!local)
		goto errout_close;

	if (rtnl_addr_set_local(addr, local) < 0) {
		fprintf(stderr, "Unable to set local address: %s\n",
			nl_geterror());
		goto errout_addr_put;
	}

	rtnl_addr_set_ifindex(addr, strtoul(argv[2], NULL, 0));

	if (rtnl_addr_delete(nlh, addr, 0) < 0) {
		fprintf(stderr, "Unable to delete address: %s\n",
			nl_geterror());
		goto errout_addr_put;
	}

	err = 0;

errout_addr_put:
	nl_addr_put(local);
errout_close:
	nl_close(nlh);
errout_free_addr:
	rtnl_addr_put(addr);
errout_free_handle:
	nl_handle_destroy(nlh);
errout:
	return err;
}
Beispiel #11
0
int netlink_request(void *request, __u16 request_len, int (*cb)(struct nl_msg *, void *),
		void *cb_arg)
{
	struct nl_sock *sk;
	enum nl_cb_type callbacks[] = { NL_CB_VALID, NL_CB_FINISH, NL_CB_ACK };
	int i;
	int error;

	sk = nl_socket_alloc();
	if (!sk) {
		log_err(ERR_ALLOC_FAILED, "Could not allocate a socket; cannot speak to the NAT64.");
		return -ENOMEM;
	}

	for (i = 0; i < (sizeof(callbacks) / sizeof(callbacks[0])); i++) {
		error = nl_socket_modify_cb(sk, callbacks[i], NL_CB_CUSTOM, cb, cb_arg);
		if (error < 0) {
			log_err(ERR_NETLINK, "Could not register response handler. "
					"I won't be able to parse the NAT64's response, so I won't send the request.\n"
					"Netlink error message: %s (Code %d)", nl_geterror(error), error);
			goto fail_free;
		}
	}

	error = nl_connect(sk, NETLINK_USERSOCK);
	if (error < 0) {
		log_err(ERR_NETLINK, "Could not bind the socket to the NAT64.\n"
				"Netlink error message: %s (Code %d)", nl_geterror(error), error);
		goto fail_free;
	}

	error = nl_send_simple(sk, MSG_TYPE_NAT64, 0, request, request_len);
	if (error < 0) {
		log_err(ERR_NETLINK, "Could not send the request to the NAT64 (is it really up?).\n"
				"Netlink error message: %s (Code %d)", nl_geterror(error), error);
		goto fail_close;
	}

	error = nl_recvmsgs_default(sk);
	if (error < 0) {
		log_err(ERR_NETLINK, "%s (System error %d)", nl_geterror(error), error);
		goto fail_close;
	}

	nl_close(sk);
	nl_socket_free(sk);
	return 0;

fail_close:
	nl_close(sk);
	/* Fall through. */

fail_free:
	nl_socket_free(sk);
	return -EINVAL;
}
Beispiel #12
0
int netem_set_params(const char *iface, struct netem_params *params)
{
	struct rtnl_link *link;
	struct rtnl_qdisc *qdisc;
	int err;

	pthread_mutex_lock(&nl_sock_mutex);

	/* filter link by name */
	if ((link = rtnl_link_get_by_name(link_cache, iface)) == NULL) {
		fprintf(stderr, "unknown interface/link name.\n");
		pthread_mutex_unlock(&nl_sock_mutex);
		return -1;
	}

	if (!(qdisc = rtnl_qdisc_alloc())) {
		/* OOM error */
		fprintf(stderr, "couldn't alloc qdisc\n");
		pthread_mutex_unlock(&nl_sock_mutex);
		return -1;
	}

	rtnl_tc_set_link(TC_CAST(qdisc), link);
	rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);
	rtnl_tc_set_kind(TC_CAST(qdisc), "netem");

	rtnl_netem_set_delay(qdisc,
	                     params->delay * 1000); /* expects microseconds */
	rtnl_netem_set_jitter(qdisc, params->jitter * 1000);
	/* params->loss is given in 10ths of a percent */
	rtnl_netem_set_loss(qdisc, (params->loss * (UINT_MAX / 1000)));

	/* Submit request to kernel and wait for response */
	err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE | NLM_F_REPLACE);

	/* Return the qdisc object to free memory resources */
	rtnl_qdisc_put(qdisc);

	if (err < 0) {
		fprintf(stderr, "Unable to add qdisc: %s\n", nl_geterror(err));
		pthread_mutex_unlock(&nl_sock_mutex);
		return err;
	}

	if ((err = nl_cache_refill(sock, link_cache)) < 0) {
		fprintf(stderr, "Unable to resync link cache: %s\n",
		        nl_geterror(err));
		pthread_mutex_unlock(&nl_sock_mutex);
		return -1;
	}

	pthread_mutex_unlock(&nl_sock_mutex);
	return 0;
}
Beispiel #13
0
TError TNlCgFilter::Create(const TNlLink &link) {
    TError error = TError::Success();
    struct nl_msg *msg;
    int ret;
	struct tcmsg tchdr;

    tchdr.tcm_family = AF_UNSPEC;
    tchdr.tcm_ifindex = link.GetIndex();
    tchdr.tcm_handle = Handle;
    tchdr.tcm_parent = Parent;
	tchdr.tcm_info = TC_H_MAKE(FilterPrio << 16, htons(ETH_P_ALL));

	msg = nlmsg_alloc_simple(RTM_NEWTFILTER, NLM_F_EXCL|NLM_F_CREATE);
	if (!msg)
        return TError(EError::Unknown, "Unable to add filter: no memory");

    ret = nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO);
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret));
		goto free_msg;
    }

    ret = nla_put(msg, TCA_KIND, strlen(FilterType) + 1, FilterType);
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret));
		goto free_msg;
    }

    ret = nla_put(msg, TCA_OPTIONS, 0, NULL);
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret));
		goto free_msg;
    }

    L() << "netlink " << link.GetDesc()
        << ": add tfilter id 0x" << std::hex << Handle
        << " parent 0x" << Parent << std::dec  << std::endl;

    ret = nl_send_sync(link.GetSock(), msg);
    if (ret)
        error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret));

    if (!Exists(link))
        error = TError(EError::Unknown, "BUG: created filter doesn't exist");

    return error;

free_msg:
    nlmsg_free(msg);

    return error;
}
Beispiel #14
0
static bool nl_new(struct dionaea *d)
{
	g_debug("%s", __PRETTY_FUNCTION__);
	nl_runtime.sock = nl_socket_alloc();
	struct nl_sock  *sock = nl_runtime.sock;
	nl_socket_disable_seq_check(sock);
	nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, nl_event_input, NULL);
	nl_join_groups(sock, RTMGRP_LINK);
	int err;
	if ( (err = nl_connect(sock, NETLINK_ROUTE)) < 0) 
	{
		g_error("Could not connect netlink (%s)", nl_geterror(err));
	}

	nl_socket_add_membership(sock, RTNLGRP_LINK);
	nl_socket_add_membership(sock, RTNLGRP_NEIGH);
	nl_socket_add_membership(sock, RTNLGRP_IPV4_IFADDR);
	nl_socket_add_membership(sock, RTNLGRP_IPV6_IFADDR);

	if( (err=rtnl_neigh_alloc_cache(sock, &nl_runtime.neigh_cache)) != 0 )
	{
		g_error("Could not allocate neigh cache! (%s)", nl_geterror(err));
	}
#if LIBNL_RTNL_LINK_ALLOC_CACHE_ARGC == 3
	if( (err=rtnl_link_alloc_cache(sock, AF_UNSPEC, &nl_runtime.link_cache)) != 0 )
#elif LIBNL_RTNL_LINK_ALLOC_CACHE_ARGC == 2
	if( (err=rtnl_link_alloc_cache(sock, &nl_runtime.link_cache)) != 0 )
#endif
	{
		g_error("Could not allocate link cache! (%s)", nl_geterror(err));
	}

	if( (err=rtnl_addr_alloc_cache(sock, &nl_runtime.addr_cache)) != 0 )
	{
		g_error("Could not allocate addr cache! (%s)", nl_geterror(err));
	}

	nl_cache_mngt_provide(nl_runtime.neigh_cache);
	nl_cache_mngt_provide(nl_runtime.link_cache);
	nl_cache_mngt_provide(nl_runtime.addr_cache);
	
	nl_runtime.ihandler = ihandler_new("dionaea.connection.*.accept", nl_ihandler_cb, NULL);

	ev_io_init(&nl_runtime.io_in, nl_io_in_cb, nl_socket_get_fd(sock), EV_READ);
	ev_io_start(g_dionaea->loop, &nl_runtime.io_in);
	nl_runtime.link_addr_cache = g_hash_table_new(g_int_hash, g_int_equal);
	nl_cache_foreach(nl_runtime.link_cache, nl_obj_input, NULL);
	nl_cache_foreach(nl_runtime.addr_cache, nl_obj_input, NULL);
    return true;
}
Beispiel #15
0
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;
}
static int parse_prio_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc)
{
	int i, err, bands;
	uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP;

	if (argc > 0) {
		if (argc < 2 || strcasecmp(argv[0], "bands"))
			goto usage;

		bands = strtoul(argv[1], NULL, 0);
		err = rtnl_qdisc_prio_set_bands(qdisc, bands);
		if (err < 0) {
			fprintf(stderr, "%s\n", nl_geterror());
			return -1;
		}
	}

	if (argc > 2) {
		if (argc < 5 || strcasecmp(argv[2], "map"))
			goto usage;

		for (i = 3; i < (argc & ~1U); i += 2) {
			int prio, band;

			prio = rtnl_str2prio(argv[i]);
			if (prio < 0 || prio > sizeof(map)/sizeof(map[0])) {
				fprintf(stderr, "Invalid priority \"%s\"\n",
					argv[i]);
				return -1;
			}

			band = strtoul(argv[i+1], NULL, 0);

			map[prio] = band;
		}
	}

	err = rtnl_qdisc_prio_set_priomap(qdisc, map, sizeof(map));
	if (err < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		return -1;
	}

	return 0;
usage:
	fprintf(stderr, "Usage: ... prio bands <nbands> map MAP\n"
			"MAP := <prio> <band>\n");
	return -1;
}
Beispiel #17
0
static void basic_parse_argv(struct rtnl_cls *cls, int argc, char **argv)
{
	uint32_t classid;

	for (;;) {
		int c, optidx = 0, err;
		static struct option long_opts[] = {
			{ "help", 0, 0, 'h' },
			{ "ematch", 1, 0, 'e' },
			{ "classid", 1, 0, 'c' },
			{ 0, 0, 0, 0 }
		};
	
		c = getopt_long(argc, argv, "he:c:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case '?':
			exit(NLE_INVAL);

		case 'h':
			print_usage();

		case 'e':
#if 0
			if ((err = parse_ematch_syntax(optarg, &tree)) < 0)
				fatal(err, "Error while parsing ematch: %s",
				      nl_geterror(err));

			if ((err = rtnl_basic_set_ematch(cls, tree)) < 0)
				fatal(err, "Unable to set ematch: %s",
					nl_geterror(err));
#endif
			break;

		case 'c':
			if ((err = rtnl_tc_str2handle(optarg, &classid)) < 0)
				fatal(err, "Invalid classid \"%s\": %s",
				      optarg, nl_geterror(err));
				
			if ((err = rtnl_basic_set_classid(cls, classid)) < 0)
				fatal(err, "Unable to set classid: %s",
				      nl_geterror(err));
			break;
		}
 	}
}
Beispiel #18
0
/*
 * Receive netlink message and trigger processing by callback
 */
static void
__ni_rtevent_receive(ni_socket_t *sock)
{
	ni_rtevent_handle_t *handle = sock->user_data;
	int ret;

	if (handle && handle->nlsock) {
		do {
			ret = nl_recvmsgs_default(handle->nlsock);
		} while (ret == NLE_SUCCESS || ret == -NLE_INTR);

		switch (ret) {
		case NLE_SUCCESS:
		case -NLE_AGAIN:
			break;

		default:
			ni_error("rtnetlink event receive error: %s (%m)",
					nl_geterror(ret));
			if (__ni_rtevent_restart(sock)) {
				ni_note("restarted rtnetlink event listener");
			} else {
				ni_error("unable to restart rtnetlink event listener");
			}
			break;
		}
	}
}
static int parse_bfifo_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc)
{
	int err, limit;

	if (argc > 0) {
		if (argc != 2 || strcasecmp(argv[0], "limit")) {
			fprintf(stderr, "Usage: ... bfifo limit <limit>\n");
			return -1;
		}

		limit = nl_size2int(argv[1]);
		if (limit < 0) {
			fprintf(stderr, "Invalid value for limit.\n");
			return -1;
		}

		err = rtnl_qdisc_fifo_set_limit(qdisc, limit);
		if (err < 0) {
			fprintf(stderr, "%s\n", nl_geterror());
			return -1;
		}
	}

	return 0;
}
Beispiel #20
0
Try<vector<Info> > infos(int family, int states)
{
  Try<Netlink<struct nl_sock> > sock = routing::socket(NETLINK_INET_DIAG);
  if (sock.isError()) {
    return Error(sock.error());
  }

  struct nl_cache* c = NULL;
  int err = idiagnl_msg_alloc_cache(sock.get().get(), family, states, &c);
  if (err != 0) {
    return Error(nl_geterror(err));
  }

  Netlink<struct nl_cache> cache(c);

  vector<Info> results;
  for (struct nl_object* o = nl_cache_get_first(cache.get());
       o != NULL; o = nl_cache_get_next(o)) {
    struct idiagnl_msg* msg = (struct idiagnl_msg*)o;

    // For 'state', libnl-idiag only returns the number of left
    // shifts. Convert it back to power-of-2 number.
    results.push_back(Info(
        idiagnl_msg_get_family(msg),
        1 << idiagnl_msg_get_state(msg),
        idiagnl_msg_get_sport(msg),
        idiagnl_msg_get_dport(msg),
        IP(idiagnl_msg_get_src(msg)),
        IP(idiagnl_msg_get_dst(msg)),
        idiagnl_msg_get_tcpinfo(msg)));
  }

  return results;
}
Beispiel #21
0
/*
 * Get the first AF_INET address on 'link'. Returns 0 if successful. Caller
 * must release reference to *addr.
 */
static int get_link_inet_addr(struct nl_sock *sk, struct rtnl_link *link,
        struct nl_addr **addr)
{
    struct nl_cache *addr_cache;
    int err;
    err = rtnl_addr_alloc_cache(sk, &addr_cache);
    if (err < 0) {
        warnx("rtnl_addr_alloc_cache() failed: %s", nl_geterror(err));
        return 1;
    }

    /* Retrieve the first AF_INET address on the requested interface. */
    struct rtnl_addr *filter;
    filter = rtnl_addr_alloc();
    assert(filter);
    rtnl_addr_set_ifindex(filter, rtnl_link_get_ifindex(link));
    rtnl_addr_set_family(filter, AF_INET);

    *addr = NULL;
    nl_cache_foreach_filter(addr_cache, (struct nl_object *)filter,
            match_first_addr, addr);
    if (*addr == NULL) {
        warnx("No AF_INET address found on veth");
        
        rtnl_addr_put(filter);
        nl_cache_free(addr_cache);
        return 1;
    }

    rtnl_addr_put(filter);
    nl_cache_free(addr_cache);
    return 0;
}
Beispiel #22
0
static void delete_cb(struct nl_object *obj, void *arg)
{
	struct rtnl_qdisc *qdisc = nl_object_priv(obj);
	struct nl_dump_params params = {
		.dp_type = NL_DUMP_LINE,
		.dp_fd = stdout,
	};
	int err;

	/* Ignore default qdiscs, unable to delete */
	if (rtnl_tc_get_handle((struct rtnl_tc *) qdisc) == 0)
		return;

	if (interactive && !nl_cli_confirm(obj, &params, default_yes))
		return;

	if ((err = rtnl_qdisc_delete(sock, qdisc)) < 0)
		nl_cli_fatal(err, "Unable to delete qdisc: %s\n", nl_geterror(err));

	if (!quiet) {
		printf("Deleted ");
		nl_object_dump(obj, &params);
	}

	deleted++;
}
Beispiel #23
0
static gboolean
sync_connection_setup (NMNetlinkMonitor *self, GError **error)
{
	NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
	/* Set up the event listener connection */
	priv->nlh_sync = nl_socket_alloc ();
	if (!priv->nlh_sync) {
		g_set_error (error, NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE,
		             _("unable to allocate netlink handle for monitoring link status: %s"),
		             nl_geterror (ENOMEM));
		goto error;
	}

	if (!nlh_setup (priv->nlh_sync, NULL, self, error))
		goto error;

	return TRUE;
error:
	if (priv->nlh_sync) {
		nl_socket_free (priv->nlh_sync);
		priv->nlh_sync = NULL;
	}

	return FALSE;
}
static gboolean
nm_netlink_listener_event_handler (GIOChannel       *channel,
								   GIOCondition      io_condition,
								   gpointer          user_data)
{
	NMNetlinkListener *listener = (NMNetlinkListener *) user_data;
	NMNetlinkListenerPrivate *priv;
	GError *error = NULL;

	g_return_val_if_fail (NM_IS_NETLINK_LISTENER (listener), TRUE);

	priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);
	g_return_val_if_fail (priv->event_id > 0, TRUE);

	if (io_condition & NM_NETLINK_LISTENER_ERROR_CONDITIONS)
		return nm_netlink_listener_error_handler (channel, io_condition, listener);
	else if (io_condition & NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS)
		return nm_netlink_listener_disconnect_handler (channel, io_condition, listener);

	g_return_val_if_fail (!(io_condition & ~(NM_NETLINK_LISTENER_EVENT_CONDITIONS)), FALSE);

	if (nl_recvmsgs_default (priv->nlh) < 0) {
		error = g_error_new (NM_NETLINK_LISTENER_ERROR,
		                     NM_NETLINK_LISTENER_ERROR_PROCESSING_MESSAGE,
		                     _("error processing netlink message: %s"),
		                     nl_geterror ());

		g_signal_emit (G_OBJECT (listener),
		               signals[ERROR],
		               0, error);
		g_error_free (error);
	}

	return TRUE;
}
Beispiel #25
0
/*
 * Heads up:
 * Netlink wants this function to return either a negative error code or an enum
 * nl_cb_action.
 * Because NL_SKIP == EPERM and NL_STOP == ENOENT, you should mind the sign of
 * the result HARD.
 */
static int response_handler(struct nl_msg *msg, void *void_arg)
{
	struct jool_response response;
	struct nlattr *attrs[__ATTR_MAX + 1];
	struct response_cb *arg;
	int error;

	error = genlmsg_parse(nlmsg_hdr(msg), 0, attrs, __ATTR_MAX, NULL);
	if (error) {
		log_err("%s (error code %d)", nl_geterror(error), error);
		return -abs(error);
	}

	if (!attrs[ATTR_DATA]) {
		log_err("The module's response seems to be empty.");
		return -EINVAL;
	}
	error = netlink_parse_response(nla_data(attrs[ATTR_DATA]),
			nla_len(attrs[ATTR_DATA]),
			&response);
	if (error)
		return -abs(error);

	arg = void_arg;
	return (arg && arg->cb) ? (-abs(arg->cb(&response, arg->arg))) : 0;
}
Beispiel #26
0
static int remus_netbuf_op(libxl__remus_device_nic *remus_nic,
                           libxl__checkpoint_devices_state *cds,
                           int buffer_op)
{
    int rc, ret;
    libxl__remus_state *rs = cds->concrete_data;

    STATE_AO_GC(cds->ao);

    if (buffer_op == tc_buffer_start)
        ret = rtnl_qdisc_plug_buffer(remus_nic->qdisc);
    else
        ret = rtnl_qdisc_plug_release_one(remus_nic->qdisc);

    if (ret) {
        rc = ERROR_FAIL;
        goto out;
    }

    ret = rtnl_qdisc_add(rs->nlsock, remus_nic->qdisc, NLM_F_REQUEST);
    if (ret) {
        rc = ERROR_FAIL;
        goto out;
    }

    rc = 0;

out:
    if (rc)
        LOGD(ERROR, cds-> domid, "Remus: cannot do netbuf op %s on %s:%s",
             ((buffer_op == tc_buffer_start) ?
             "start_new_epoch" : "release_prev_epoch"),
             remus_nic->ifb, nl_geterror(ret));
    return rc;
}
static gboolean
event_connection_setup (NMNetlinkMonitor *self, GError **error)
{
	NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);
	GError *channel_error = NULL;
	GIOFlags channel_flags;
	int fd;

	g_return_val_if_fail (priv->io_channel == NULL, FALSE);

	/* Set up the event listener connection */
	priv->nlh_event = nl_socket_alloc ();
	if (!priv->nlh_event) {
		g_set_error (error, NM_NETLINK_MONITOR_ERROR,
		             NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE,
		             _("unable to allocate netlink handle for monitoring link status: %s"),
		             nl_geterror (ENOMEM));
		goto error;
	}

	if (!nlh_setup (priv->nlh_event, event_msg_ready, self, error))
		goto error;

	nl_socket_disable_seq_check (priv->nlh_event);

	/* Subscribe to the LINK group for internal carrier signals */
	if (!nm_netlink_monitor_subscribe (self, RTNLGRP_LINK, error))
		goto error;

	fd = nl_socket_get_fd (priv->nlh_event);
	priv->io_channel = g_io_channel_unix_new (fd);

	g_io_channel_set_encoding (priv->io_channel, NULL, &channel_error);
	/* Encoding is NULL, so no conversion error can possibly occur */
	g_assert (channel_error == NULL);

	g_io_channel_set_close_on_unref (priv->io_channel, TRUE);
	channel_flags = g_io_channel_get_flags (priv->io_channel);
	channel_error = NULL;
	g_io_channel_set_flags (priv->io_channel,
	                        channel_flags | G_IO_FLAG_NONBLOCK,
	                        &channel_error);
	if (channel_error != NULL) {
		g_propagate_error (error, channel_error);
		goto error;
	}

	return TRUE;

error:
	if (priv->io_channel)
		nm_netlink_monitor_close_connection (self);

	if (priv->nlh_event) {
		nl_socket_free (priv->nlh_event);
		priv->nlh_event = NULL;
	}

	return FALSE;
}
Beispiel #28
0
bool TNlCgFilter::Exists(const TNlLink &link) {
    int ret;
    struct nl_cache *clsCache;

    ret = rtnl_cls_alloc_cache(link.GetSock(), link.GetIndex(), Parent, &clsCache);
    if (ret < 0) {
        L_ERR() << "Can't allocate filter cache: " << nl_geterror(ret) << std::endl;
        return false;
    }

    link.LogCache(clsCache);

    struct CgFilterIter {
        uint32_t parent;
        uint32_t handle;
        bool exists;
    } data = { Parent, Handle, false };
    nl_cache_foreach(clsCache, [](struct nl_object *obj, void *data) {
                     CgFilterIter *p = (CgFilterIter *)data;
                     if (rtnl_tc_get_handle(TC_CAST(obj)) == p->handle &&
                         rtnl_tc_get_parent(TC_CAST(obj)) == p->parent)
                         p->exists = true;
                     }, &data);

    nl_cache_free(clsCache);
    return data.exists;
}
gboolean
nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error)
{
	NMNetlinkMonitorPrivate *priv;
	int subs, err;

	g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE);

	priv = NM_NETLINK_MONITOR_GET_PRIVATE (self);

	if (!priv->nlh_event) {
		if (!nm_netlink_monitor_open_connection (self, error))
			return FALSE;
	}

	subs = get_subs (self, group) + 1;
	if (subs == 1) {
		err = nl_socket_add_membership (priv->nlh_event, group);
		if (err < 0) {
			g_set_error (error, NM_NETLINK_MONITOR_ERROR,
			             NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP,
			             _("unable to join netlink group: %s"),
			             nl_geterror (err));
			return FALSE;
		}
	}

	/* Update # of subscriptions for this group */
	set_subs (self, group, subs);

	return TRUE;
}
gboolean
nm_netlink_listener_subscribe (NMNetlinkListener *listener,
							   int group,
							   GError **error)
{
	NMNetlinkListenerPrivate *priv;

	g_return_val_if_fail (NM_IS_NETLINK_LISTENER (listener), FALSE);

	priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);

	if (!priv->nlh) {
		if (!open_connection (listener, error))
			return FALSE;
	}

	if (nl_socket_add_membership (priv->nlh, group) < 0) {
		g_set_error (error, NM_NETLINK_LISTENER_ERROR,
		             NM_NETLINK_LISTENER_ERROR_NETLINK_JOIN_GROUP,
		             _("unable to join netlink group: %s"),
		             nl_geterror ());
		return FALSE;
	}

	return TRUE;
}