Exemple #1
0
int
kern_bcache_init()
{
	supsocket_t *sock;

	nl_bcache = nl_handle_alloc();
	nl_disable_sequence_check(nl_bcache);
	nl_join_groups(nl_bcache, ~0);

	nl_cb_set(nl_handle_get_cb(nl_bcache), NL_CB_VALID, NL_CB_CUSTOM,
		  nl_bcache_event, NULL);

	if (nl_connect(nl_bcache, NETLINK_IP6MBLTY) < 0) {
		debug_log(1, "nl_connect(NETLINK_IP6MBLTY) failed: %s.\n",
			  strerror(errno));
		nl_close(nl_bcache);
		nl_bcache = NULL;
		return -1;
	}

	fcntl(nl_handle_get_fd(nl_bcache), F_SETFL, O_NONBLOCK);

	sock = support_register_socket(nl_handle_get_fd(nl_bcache),
				       nl_bcache_events_waiting, NULL, NULL);
	sock->mode = SUPSOCKET_READ;

	return 0;
}
Exemple #2
0
static struct nl_handle *init_netlink(void)
{
	struct nl_handle *handle;
	int ret, multicast_id;

	handle = nl_handle_alloc();
	if (!handle){
		elog("Cannot allocate netlink handle!\n");
		return NULL;
	}
	nl_disable_sequence_check(handle);
	ret = genl_connect(handle);
	if (ret < 0){
		elog("Cannot connect to netlink socket\n");
		return NULL;
	}

	/*
	familyid = genl_ctrl_resolve(handle, SAMPLE_NL_FAMILY_NAME);
	if (!familyid){
		elog("Cannot resolve family name(%s)\n", SAMPLE_NL_FAMILY_NAME);
		return NULL;
	}
	dlog("familyid %d\n", familyid);
	*/

	multicast_id = nl_get_multicast_id(handle, SAMPLE_NL_FAMILY_NAME, SAMPLE_NL_GRP_NAME);
	if (multicast_id < 0){
		elog("Cannot resolve grp name(%d)\n", SAMPLE_NL_GRP_NAME);
		return NULL;
	}

	ret = nl_socket_add_membership(handle, multicast_id);
	if (ret < 0){
		elog("Cannot join fs multicast group\n");
		return NULL;
	}

	ret = nl_socket_modify_cb(handle, NL_CB_VALID, NL_CB_CUSTOM,
			sample_nl_cb, NULL);
	if (ret < 0){
		elog("Cannot register callback for"
			 " netlink messages\n");
		return NULL;
	}

	return handle;
}
int usnic_rtnl_sk_alloc(struct usnic_rtnl_sk **p_sk)
{
	struct usnic_rtnl_sk *unlsk;
	struct nl_handle *nlh;
	int err;

	unlsk = calloc(1, sizeof(*unlsk));
	if (!unlsk) {
		usnic_err("Failed to allocate usnic_rtnl_sk struct\n");
		return -ENOMEM;
	}

	nlh =  nl_handle_alloc();
	if (!nlh) {
		usnic_err("Failed to allocate nl handle\n");
		err = -ENOMEM;
		goto err_free_unlsk;
	}

	err = nl_connect(nlh, NETLINK_ROUTE);
	if (err < 0) {
		usnic_err("Failed to connnect netlink route socket\n");
		goto err_free_nlh;
	}

	nl_disable_sequence_check(nlh);
	err = nl_set_recv_timeout(nlh);
	if (err < 0)
		goto err_close_nlh;

	unlsk->nlh = nlh;
	unlsk->seq = time(NULL);
	*p_sk = unlsk;
	return 0;

err_close_nlh:
	nl_close(nlh);
err_free_nlh:
	nl_handle_destroy(nlh);
err_free_unlsk:
	free(unlsk);
	return err;
}
Exemple #4
0
static void obj_input(struct nl_object *obj, void *arg)
{
	struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) obj;
	struct nl_dump_params dp = {
		.dp_type = NL_DUMP_STATS,
		.dp_fd = stdout,
		.dp_dump_msgtype = 1,
	};

	nfnl_queue_msg_set_verdict(msg, NF_ACCEPT);
	nl_object_dump(obj, &dp);
	nfnl_queue_msg_send_verdict(nfnlh, msg);
}

static int event_input(struct nl_msg *msg, void *arg)
{
	if (nl_msg_parse(msg, &obj_input, NULL) < 0)
		fprintf(stderr, "<<EVENT>> Unknown message type\n");

	/* Exit nl_recvmsgs_def() and return to the main select() */
	return NL_STOP;
}

int main(int argc, char *argv[])
{
	struct nl_handle *rtnlh;
	struct nl_cache *link_cache;
	struct nfnl_queue *queue;
	enum nfnl_queue_copy_mode copy_mode;
	uint32_t copy_range;
	int err = 1;
	int family;

	if (nltool_init(argc, argv) < 0)
		return -1;

	nfnlh = nltool_alloc_handle();
	if (nfnlh == NULL)
		return -1;

	nl_disable_sequence_check(nfnlh);

	nl_socket_modify_cb(nfnlh, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);

	if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) {
		printf("Usage: nf-queue family group [ copy_mode ] "
		       "[ copy_range ]\n");
		return 2;
	}

	if (nfnl_connect(nfnlh) < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout;
	}

	family = nl_str2af(argv[1]);
	if (family == AF_UNSPEC) {
		fprintf(stderr, "Unknown family: %s\n", argv[1]);
		goto errout;
	}

	nfnl_queue_pf_unbind(nfnlh, family);
	if (nfnl_queue_pf_bind(nfnlh, family) < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout;
	}

	queue = nfnl_queue_alloc();
	if (queue == NULL) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout;
	}

	nfnl_queue_set_group(queue, atoi(argv[2]));

	copy_mode = NFNL_QUEUE_COPY_PACKET;
	if (argc > 3) {
		copy_mode = nfnl_queue_str2copy_mode(argv[3]);
		if (copy_mode < 0) {
			fprintf(stderr, "%s\n", nl_geterror());
			goto errout;
		}
	}
	nfnl_queue_set_copy_mode(queue, copy_mode);

	copy_range = 0xFFFF;
	if (argc > 4)
		copy_range = atoi(argv[4]);
	nfnl_queue_set_copy_range(queue, copy_range);

	if (nfnl_queue_create(nfnlh, queue) < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout;
	}

	rtnlh = nltool_alloc_handle();
	if (rtnlh == NULL) {
		goto errout_close;
	}

	if (nl_connect(rtnlh, NETLINK_ROUTE) < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout;
	}

	if ((link_cache = rtnl_link_alloc_cache(rtnlh)) == NULL) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout_close;
	}

	nl_cache_mngt_provide(link_cache);

	while (1) {
		fd_set rfds;
		int nffd, rtfd, maxfd, retval;

		FD_ZERO(&rfds);

		maxfd = nffd = nl_socket_get_fd(nfnlh);
		FD_SET(nffd, &rfds);

		rtfd = nl_socket_get_fd(rtnlh);
		FD_SET(rtfd, &rfds);
		if (maxfd < rtfd)
			maxfd = rtfd;

		/* wait for an incoming message on the netlink socket */
		retval = select(maxfd+1, &rfds, NULL, NULL, NULL);

		if (retval) {
			if (FD_ISSET(nffd, &rfds))
				nl_recvmsgs_default(nfnlh);
			if (FD_ISSET(rtfd, &rfds))
				nl_recvmsgs_default(rtnlh);
		}
	}

	nl_cache_mngt_unprovide(link_cache);
	nl_cache_free(link_cache);

	nfnl_queue_put(queue);

	nl_close(rtnlh);
	nl_handle_destroy(rtnlh);
errout_close:
	nl_close(nfnlh);
	nl_handle_destroy(nfnlh);
errout:
	return err;
}
Exemple #5
0
/** 
 * Setups generic netlink connection with the kernel module and retrieves assocaited family id
 *
 * @return 0 on success
 */
static int initialize_netlink_family(void) {
	struct nl_handle* hndl;
	struct nl_msg* msg = NULL;
	struct nl_msg *ans_msg = NULL;
	struct nlmsghdr *nl_hdr;
	struct genlmsghdr* genl_hdr;
	struct nlattr *nla;
	int ret_val = 0;

	hndl = nl_handle_alloc();
	nl_set_buffer_size(hndl, 15000000, 15000000);
	
	//nl_handle_set_peer_pid(hndl, 0);
	//nl_set_passcred(hndl, 1);
	nl_disable_sequence_check(hndl);

	if ( (ret_val=nl_connect(hndl, NETLINK_GENERIC)) )
		goto init_return;
	
	nl_set_buffer_size(hndl, 15000000, 15000000);
  
	if ( (ret_val=prepare_request_message(hndl, CTRL_CMD_GETFAMILY, GENL_ID_CTRL, &msg) ) != 0 ) {
		goto init_return;
  	}
  
	ret_val = nla_put_string(msg,
		   CTRL_ATTR_FAMILY_NAME,
		   "DIRECTORCHNL");

  	if (ret_val != 0)
		goto init_return;

	if ( (ret_val = send_request_message(hndl, msg, 0) ) != 0 )
		goto init_return;
	if ( (ret_val = read_message(hndl, &ans_msg) ) != 0 )
		goto init_return;

	genl_hdr = nl_msg_genlhdr(ans_msg);
 	if (genl_hdr == NULL || genl_hdr->cmd != CTRL_CMD_NEWFAMILY) {
    		ret_val = -EBADMSG;
    		goto init_return;
  	}

	nla = nlmsg_find_attr(nlmsg_hdr(ans_msg), sizeof(struct genlmsghdr), CTRL_ATTR_FAMILY_ID);
  	if (nla == NULL) {
    		ret_val = -EBADMSG;
    		goto init_return;
  	}

  	state.gnl_fid = nla_get_u16(nla);  
  	if (state.gnl_fid == 0) {
    		ret_val = -EBADMSG;
    		goto init_return;
  	}
  	  	

  	state.handle = hndl;

	return 0;

init_return:
	nlmsg_free(ans_msg);
	
	if ( state.handle == NULL ) {
		nl_close(hndl);
		nl_handle_destroy(hndl);
  	}

	return -EINVAL;
}
Exemple #6
0
int netlink_wrapper::open_channel()
{
	auto_unlocker lock(m_cache_lock);
	nl_logdbg("opening netlink channel");

	/*
	 // build to subscriptions groups mask for indicating what type of events the kernel will send on channel
	 unsigned subscriptions = ~RTMGRP_TC;
	 if (netlink_route_group_mask & nlgrpLINK) {
	 subscriptions |= (1 << (RTNLGRP_LINK - 1));
	 }
	 if (netlink_route_group_mask & nlgrpADDRESS) {
	 if (!m_preferred_family || m_preferred_family == AF_INET)
	 subscriptions |= (1 << (RTNLGRP_IPV4_IFADDR - 1));
	 if (!m_preferred_family || m_preferred_family == AF_INET6)
	 subscriptions |= (1 << (RTNLGRP_IPV6_IFADDR - 1));
	 }
	 if (netlink_route_group_mask & nlgrpROUTE) {
	 if (!m_preferred_family || m_preferred_family == AF_INET)
	 subscriptions |= (1 << (RTNLGRP_IPV4_ROUTE - 1));
	 if (!m_preferred_family || m_preferred_family == AF_INET6)
	 subscriptions |= (1 << (RTNLGRP_IPV4_ROUTE - 1));
	 }
	 if (netlink_route_group_mask & nlgrpPREFIX) {
	 if (!m_preferred_family || m_preferred_family == AF_INET6)
	 subscriptions |= (1 << (RTNLGRP_IPV6_PREFIX - 1));
	 }
	 if (netlink_route_group_mask & nlgrpNEIGH) {
	 subscriptions |= (1 << (RTNLGRP_NEIGH - 1));
	 }
	 */

	// Allocate a new netlink handle
	m_handle = nl_handle_alloc();

	BULLSEYE_EXCLUDE_BLOCK_START
	if (m_handle == NULL) {
		nl_logerr("failed to allocate netlink handle, nl_errno=%d", nl_get_errno());
		return -1;
	}
	BULLSEYE_EXCLUDE_BLOCK_END

	// set internal structure to pass the handle with callbacks from netlink
	g_nl_rcv_arg.handle = m_handle;

	// if multiple handles being allocated then a unique netlink PID need to be provided
	// If port is 0, a unique port identifier will be generated automatically as a unique PID
	nl_socket_set_local_port(m_handle, 0);


	//Disables checking of sequence numbers on the netlink handle.
	//This is required to allow messages to be processed which were not requested by a preceding request message, e.g. netlink events.
	nl_disable_sequence_check(m_handle);

	//joining group
	//nl_join_groups(m_handle, 0);

	// Allocate a new cache manager for RTNETLINK
	// NL_AUTO_PROVIDE = automatically provide the caches added to the manager.
	m_mngr = nl_cache_mngr_alloc(m_handle, NETLINK_ROUTE, NL_AUTO_PROVIDE);

	BULLSEYE_EXCLUDE_BLOCK_START
	if (!m_mngr) {
		nl_logerr("Fail to allocate cac he manager");
		return -1;
	}
	BULLSEYE_EXCLUDE_BLOCK_END

	nl_logdbg("netlink socket is open");

	m_cache_neigh = nl_cache_mngr_add(m_mngr, "route/neigh", neigh_cache_callback);
	m_cache_link = nl_cache_mngr_add(m_mngr, "route/link", link_cache_callback);
	m_cache_route = nl_cache_mngr_add(m_mngr, "route/route", route_cache_callback);

	// set custom callback for every message to update message
	nl_socket_modify_cb(m_handle, NL_CB_MSG_IN, NL_CB_CUSTOM, nl_msg_rcv_cb ,NULL);

	// set the socket non-blocking
	BULLSEYE_EXCLUDE_BLOCK_START
	if (nl_socket_set_nonblocking(m_handle)) {
		nl_logerr("Failed to set the socket non-blocking");
		return -1;
	}
	BULLSEYE_EXCLUDE_BLOCK_END

	return 0;

}
static void obj_input(struct nl_object *obj, void *arg)
{
	struct nl_dump_params dp = {
		.dp_type = NL_DUMP_STATS,
		.dp_fd = stdout,
		.dp_dump_msgtype = 1,
	};

	nl_object_dump(obj, &dp);
}

static int event_input(struct nl_msg *msg, void *arg)
{
	if (nl_msg_parse(msg, &obj_input, NULL) < 0)
		fprintf(stderr, "<<EVENT>> Unknown message type\n");

	/* Exit nl_recvmsgs_def() and return to the main select() */
	return NL_STOP;
}

int main(int argc, char *argv[])
{
	struct nl_handle *nlh;
	int err = 1;
	int i, idx;

	static const struct {
		enum nfnetlink_groups gr_id;
		const char* gr_name;
	} known_groups[] = {
		{ NFNLGRP_CONNTRACK_NEW, "ct-new" },
		{ NFNLGRP_CONNTRACK_UPDATE, "ct-update" },
		{ NFNLGRP_CONNTRACK_DESTROY, "ct-destroy" },
		{ NFNLGRP_NONE, NULL }
	};

	if (nltool_init(argc, argv) < 0)
		return -1;

	nlh = nltool_alloc_handle();
	if (nlh == NULL)
		return -1;

	nl_disable_sequence_check(nlh);

	nl_socket_modify_cb(nlh, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);

	if (argc > 1 && !strcasecmp(argv[1], "-h")) {
		printf("Usage: nf-monitor [<groups>]\n");

		printf("Known groups:");
		for (i = 0; known_groups[i].gr_id != NFNLGRP_NONE; i++)
			printf(" %s", known_groups[i].gr_name);
		printf("\n");
		return 2;
	}

	if (nfnl_connect(nlh) < 0) {
		fprintf(stderr, "%s\n", nl_geterror());
		goto errout;
	}

	for (idx = 1; argc > idx; idx++) {
		for (i = 0; known_groups[i].gr_id != NFNLGRP_NONE; i++) {
			if (!strcmp(argv[idx], known_groups[i].gr_name)) {

				if (nl_socket_add_membership(nlh, known_groups[i].gr_id) < 0) {
					fprintf(stderr, "%s: %s\n", argv[idx], nl_geterror());
					goto errout;
				}

				break;
			}
		}
		if (known_groups[i].gr_id == NFNLGRP_NONE)
			fprintf(stderr, "Warning: Unknown group: %s\n", argv[idx]);
	}

	while (1) {
		fd_set rfds;
		int fd, retval;

		fd = nl_socket_get_fd(nlh);

		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);
		/* wait for an incoming message on the netlink socket */
		retval = select(fd+1, &rfds, NULL, NULL, NULL);

		if (retval) {
			/* FD_ISSET(fd, &rfds) will be true */
			nl_recvmsgs_default(nlh);
		}
	}

	nl_close(nlh);
errout:
	return err;
}
static gboolean
open_connection (NMNetlinkListener *listener, GError **error)
{
	NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);
	int fd;
	GError *channel_error = NULL;
	GIOFlags channel_flags;

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

	priv->nlh_cb = nl_cb_alloc (NL_CB_DEFAULT);
	priv->nlh = nl_handle_alloc_cb (priv->nlh_cb);
	if (!priv->nlh) {
		g_set_error (error, NM_NETLINK_LISTENER_ERROR,
		             NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_HANDLE,
		             _("unable to allocate netlink handle: %s"),
		             nl_geterror ());
		goto error;
	}

	nl_disable_sequence_check (priv->nlh);
	nl_socket_modify_cb (priv->nlh, NL_CB_VALID, NL_CB_CUSTOM, netlink_event_input, listener);
	if (nl_connect (priv->nlh, NETLINK_ROUTE) < 0) {
		g_set_error (error, NM_NETLINK_LISTENER_ERROR,
		             NM_NETLINK_LISTENER_ERROR_NETLINK_CONNECT,
		             _("unable to connect to netlink: %s"),
		             nl_geterror ());
		goto error;
	}

	fd = nl_socket_get_fd (priv->nlh);
	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;
	}

	priv->event_id = g_io_add_watch (priv->io_channel,
	                                 (NM_NETLINK_LISTENER_EVENT_CONDITIONS |
	                                  NM_NETLINK_LISTENER_ERROR_CONDITIONS |
	                                  NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS),
	                                 nm_netlink_listener_event_handler,
	                                 listener);
	return TRUE;

error:
	if (priv->io_channel)
		close_connection (listener);

	if (priv->nlh) {
		nl_handle_destroy (priv->nlh);
		priv->nlh = NULL;
	}

	if (priv->nlh_cb) {
		nl_cb_put (priv->nlh_cb);
		priv->nlh_cb = NULL;
	}
	return FALSE;
}